2 * Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
17 /* $Id: nsec3_50.c,v 1.4.48.2 2009/01/18 23:47:41 tbox Exp $ */
20 * Copyright (C) 2004 Nominet, Ltd.
22 * Permission to use, copy, modify, and distribute this software for any
23 * purpose with or without fee is hereby granted, provided that the above
24 * copyright notice and this permission notice appear in all copies.
26 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
27 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
28 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
29 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
30 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
31 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
32 * PERFORMANCE OF THIS SOFTWARE.
37 #ifndef RDATA_GENERIC_NSEC3_50_C
38 #define RDATA_GENERIC_NSEC3_50_C
40 #include <isc/iterated_hash.h>
41 #include <isc/base32.h>
43 #define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
45 static inline isc_result_t
46 fromtext_nsec3(ARGS_FROMTEXT) {
48 unsigned char bm[8*1024]; /* 64k bits */
49 dns_rdatatype_t covered;
53 unsigned char hashalg;
65 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
67 RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
68 RETERR(uint8_tobuffer(hashalg, target));
71 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
73 flags = token.value.as_ulong;
76 RETERR(uint8_tobuffer(flags, target));
79 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
81 if (token.value.as_ulong > 0xffffU)
83 RETERR(uint16_tobuffer(token.value.as_ulong, target));
86 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
88 if (token.value.as_textregion.length > (255*2))
89 RETTOK(DNS_R_TEXTTOOLONG);
90 if (strcmp(DNS_AS_STR(token), "-") == 0) {
91 RETERR(uint8_tobuffer(0, target));
93 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
94 RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
98 * Next hash a single base32hex word.
100 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
102 isc_buffer_init(&b, bm, sizeof(bm));
103 RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token), &b));
104 if (isc_buffer_usedlength(&b) > 0xffU)
106 RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
107 RETERR(mem_tobuffer(target, &bm, isc_buffer_usedlength(&b)));
109 memset(bm, 0, sizeof(bm));
111 RETERR(isc_lex_getmastertoken(lexer, &token,
112 isc_tokentype_string, ISC_TRUE));
113 if (token.type != isc_tokentype_string)
115 RETTOK(dns_rdatatype_fromtext(&covered,
116 &token.value.as_textregion));
117 bm[covered/8] |= (0x80>>(covered%8));
119 isc_lex_ungettoken(lexer, &token);
120 for (window = 0; window < 256 ; window++) {
122 * Find if we have a type in this window.
124 for (octet = 31; octet >= 0; octet--)
125 if (bm[window * 32 + octet] != 0)
129 RETERR(uint8_tobuffer(window, target));
130 RETERR(uint8_tobuffer(octet + 1, target));
131 RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
133 return (ISC_R_SUCCESS);
136 static inline isc_result_t
137 totext_nsec3(ARGS_TOTEXT) {
139 unsigned int i, j, k;
140 unsigned int window, len;
143 char buf[sizeof("65535 ")];
144 isc_uint32_t iterations;
146 REQUIRE(rdata->type == 50);
147 REQUIRE(rdata->length != 0);
151 dns_rdata_toregion(rdata, &sr);
153 hash = uint8_fromregion(&sr);
154 isc_region_consume(&sr, 1);
156 flags = uint8_fromregion(&sr);
157 isc_region_consume(&sr, 1);
159 iterations = uint16_fromregion(&sr);
160 isc_region_consume(&sr, 2);
162 sprintf(buf, "%u ", hash);
163 RETERR(str_totext(buf, target));
165 sprintf(buf, "%u ", flags);
166 RETERR(str_totext(buf, target));
168 sprintf(buf, "%u ", iterations);
169 RETERR(str_totext(buf, target));
171 j = uint8_fromregion(&sr);
172 isc_region_consume(&sr, 1);
173 INSIST(j <= sr.length);
178 RETERR(isc_hex_totext(&sr, 1, "", target));
180 RETERR(str_totext(" ", target));
182 RETERR(str_totext("- ", target));
184 j = uint8_fromregion(&sr);
185 isc_region_consume(&sr, 1);
186 INSIST(j <= sr.length);
190 RETERR(isc_base32hex_totext(&sr, 1, "", target));
193 for (i = 0; i < sr.length; i += len) {
194 INSIST(i + 2 <= sr.length);
196 len = sr.base[i + 1];
197 INSIST(len > 0 && len <= 32);
199 INSIST(i + len <= sr.length);
200 for (j = 0; j < len; j++) {
202 if (sr.base[i + j] == 0)
204 for (k = 0; k < 8; k++) {
205 if ((sr.base[i + j] & (0x80 >> k)) == 0)
207 t = window * 256 + j * 8 + k;
208 RETERR(str_totext(" ", target));
209 if (dns_rdatatype_isknown(t)) {
210 RETERR(dns_rdatatype_totext(t, target));
212 char buf[sizeof("TYPE65535")];
213 sprintf(buf, "TYPE%u", t);
214 RETERR(str_totext(buf, target));
219 return (ISC_R_SUCCESS);
222 static inline isc_result_t
223 fromwire_nsec3(ARGS_FROMWIRE) {
225 unsigned int window, lastwindow = 0;
227 unsigned int saltlen, hashlen;
228 isc_boolean_t first = ISC_TRUE;
238 isc_buffer_activeregion(source, &sr);
241 /* hash(1), flags(1), iteration(2), saltlen(1) */
243 RETERR(DNS_R_FORMERR);
244 saltlen = sr.base[4];
245 isc_region_consume(&sr, 5);
247 if (sr.length < saltlen)
248 RETERR(DNS_R_FORMERR);
249 isc_region_consume(&sr, saltlen);
252 RETERR(DNS_R_FORMERR);
253 hashlen = sr.base[0];
254 isc_region_consume(&sr, 1);
256 if (sr.length < hashlen)
257 RETERR(DNS_R_FORMERR);
258 isc_region_consume(&sr, hashlen);
260 for (i = 0; i < sr.length; i += len) {
262 * Check for overflow.
264 if (i + 2 > sr.length)
265 RETERR(DNS_R_FORMERR);
267 len = sr.base[i + 1];
270 * Check that bitmap windows are in the correct order.
272 if (!first && window <= lastwindow)
273 RETERR(DNS_R_FORMERR);
275 * Check for legal lengths.
277 if (len < 1 || len > 32)
278 RETERR(DNS_R_FORMERR);
280 * Check for overflow.
282 if (i + len > sr.length)
283 RETERR(DNS_R_FORMERR);
285 * The last octet of the bitmap must be non zero.
287 if (sr.base[i + len - 1] == 0)
288 RETERR(DNS_R_FORMERR);
293 return (DNS_R_EXTRADATA);
294 RETERR(mem_tobuffer(target, rr.base, rr.length));
295 isc_buffer_forward(source, rr.length);
296 return (ISC_R_SUCCESS);
299 static inline isc_result_t
300 towire_nsec3(ARGS_TOWIRE) {
303 REQUIRE(rdata->type == 50);
304 REQUIRE(rdata->length != 0);
308 dns_rdata_toregion(rdata, &sr);
309 return (mem_tobuffer(target, sr.base, sr.length));
313 compare_nsec3(ARGS_COMPARE) {
317 REQUIRE(rdata1->type == rdata2->type);
318 REQUIRE(rdata1->rdclass == rdata2->rdclass);
319 REQUIRE(rdata1->type == 50);
320 REQUIRE(rdata1->length != 0);
321 REQUIRE(rdata2->length != 0);
323 dns_rdata_toregion(rdata1, &r1);
324 dns_rdata_toregion(rdata2, &r2);
325 return (isc_region_compare(&r1, &r2));
328 static inline isc_result_t
329 fromstruct_nsec3(ARGS_FROMSTRUCT) {
330 dns_rdata_nsec3_t *nsec3 = source;
331 unsigned int i, len, window, lastwindow = 0;
332 isc_boolean_t first = ISC_TRUE;
335 REQUIRE(source != NULL);
336 REQUIRE(nsec3->common.rdtype == type);
337 REQUIRE(nsec3->common.rdclass == rdclass);
338 REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
339 REQUIRE(nsec3->hash == dns_hash_sha1);
344 RETERR(uint8_tobuffer(nsec3->hash, target));
345 RETERR(uint8_tobuffer(nsec3->flags, target));
346 RETERR(uint16_tobuffer(nsec3->iterations, target));
347 RETERR(uint8_tobuffer(nsec3->salt_length, target));
348 RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
349 RETERR(uint8_tobuffer(nsec3->next_length, target));
350 RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
353 * Perform sanity check.
355 for (i = 0; i < nsec3->len ; i += len) {
356 INSIST(i + 2 <= nsec3->len);
357 window = nsec3->typebits[i];
358 len = nsec3->typebits[i+1];
360 INSIST(first || window > lastwindow);
361 INSIST(len > 0 && len <= 32);
362 INSIST(i + len <= nsec3->len);
363 INSIST(nsec3->typebits[i + len - 1] != 0);
367 return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
370 static inline isc_result_t
371 tostruct_nsec3(ARGS_TOSTRUCT) {
373 dns_rdata_nsec3_t *nsec3 = target;
375 REQUIRE(rdata->type == 50);
376 REQUIRE(target != NULL);
377 REQUIRE(rdata->length != 0);
379 nsec3->common.rdclass = rdata->rdclass;
380 nsec3->common.rdtype = rdata->type;
381 ISC_LINK_INIT(&nsec3->common, link);
383 region.base = rdata->data;
384 region.length = rdata->length;
385 nsec3->hash = uint8_consume_fromregion(®ion);
386 nsec3->flags = uint8_consume_fromregion(®ion);
387 nsec3->iterations = uint16_consume_fromregion(®ion);
389 nsec3->salt_length = uint8_consume_fromregion(®ion);
390 nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
391 if (nsec3->salt == NULL)
392 return (ISC_R_NOMEMORY);
393 isc_region_consume(®ion, nsec3->salt_length);
395 nsec3->next_length = uint8_consume_fromregion(®ion);
396 nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
397 if (nsec3->next == NULL)
399 isc_region_consume(®ion, nsec3->next_length);
401 nsec3->len = region.length;
402 nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
403 if (nsec3->typebits == NULL)
407 return (ISC_R_SUCCESS);
410 if (nsec3->next != NULL)
411 isc_mem_free(mctx, nsec3->next);
412 isc_mem_free(mctx, nsec3->salt);
413 return (ISC_R_NOMEMORY);
417 freestruct_nsec3(ARGS_FREESTRUCT) {
418 dns_rdata_nsec3_t *nsec3 = source;
420 REQUIRE(source != NULL);
421 REQUIRE(nsec3->common.rdtype == 50);
423 if (nsec3->mctx == NULL)
426 if (nsec3->salt != NULL)
427 isc_mem_free(nsec3->mctx, nsec3->salt);
428 if (nsec3->next != NULL)
429 isc_mem_free(nsec3->mctx, nsec3->next);
430 if (nsec3->typebits != NULL)
431 isc_mem_free(nsec3->mctx, nsec3->typebits);
435 static inline isc_result_t
436 additionaldata_nsec3(ARGS_ADDLDATA) {
437 REQUIRE(rdata->type == 50);
443 return (ISC_R_SUCCESS);
446 static inline isc_result_t
447 digest_nsec3(ARGS_DIGEST) {
450 REQUIRE(rdata->type == 50);
452 dns_rdata_toregion(rdata, &r);
453 return ((digest)(arg, &r));
456 static inline isc_boolean_t
457 checkowner_nsec3(ARGS_CHECKOWNER) {
469 static inline isc_boolean_t
470 checknames_nsec3(ARGS_CHECKNAMES) {
472 REQUIRE(rdata->type == 50);
481 #endif /* RDATA_GENERIC_NSEC3_50_C */