4 * Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: nsec3_50.c,v 1.7 2009/12/04 21:09:34 marka Exp */
22 * Copyright (C) 2004 Nominet, Ltd.
24 * Permission to use, copy, modify, and distribute this software for any
25 * purpose with or without fee is hereby granted, provided that the above
26 * copyright notice and this permission notice appear in all copies.
28 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
29 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
30 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
31 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
32 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
33 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
34 * PERFORMANCE OF THIS SOFTWARE.
39 #ifndef RDATA_GENERIC_NSEC3_50_C
40 #define RDATA_GENERIC_NSEC3_50_C
42 #include <isc/iterated_hash.h>
43 #include <isc/base32.h>
45 #define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
47 static inline isc_result_t
48 fromtext_nsec3(ARGS_FROMTEXT
) {
50 unsigned char bm
[8*1024]; /* 64k bits */
51 dns_rdatatype_t covered
;
55 unsigned char hashalg
;
67 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
69 RETTOK(dns_hashalg_fromtext(&hashalg
, &token
.value
.as_textregion
));
70 RETERR(uint8_tobuffer(hashalg
, target
));
73 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_number
,
75 flags
= token
.value
.as_ulong
;
78 RETERR(uint8_tobuffer(flags
, target
));
81 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_number
,
83 if (token
.value
.as_ulong
> 0xffffU
)
85 RETERR(uint16_tobuffer(token
.value
.as_ulong
, target
));
88 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
90 if (token
.value
.as_textregion
.length
> (255*2))
91 RETTOK(DNS_R_TEXTTOOLONG
);
92 if (strcmp(DNS_AS_STR(token
), "-") == 0) {
93 RETERR(uint8_tobuffer(0, target
));
95 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token
)) / 2, target
));
96 RETERR(isc_hex_decodestring(DNS_AS_STR(token
), target
));
100 * Next hash a single base32hex word.
102 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
104 isc_buffer_init(&b
, bm
, sizeof(bm
));
105 RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token
), &b
));
106 if (isc_buffer_usedlength(&b
) > 0xffU
)
108 RETERR(uint8_tobuffer(isc_buffer_usedlength(&b
), target
));
109 RETERR(mem_tobuffer(target
, &bm
, isc_buffer_usedlength(&b
)));
111 memset(bm
, 0, sizeof(bm
));
113 RETERR(isc_lex_getmastertoken(lexer
, &token
,
114 isc_tokentype_string
, ISC_TRUE
));
115 if (token
.type
!= isc_tokentype_string
)
117 RETTOK(dns_rdatatype_fromtext(&covered
,
118 &token
.value
.as_textregion
));
119 bm
[covered
/8] |= (0x80>>(covered
%8));
121 isc_lex_ungettoken(lexer
, &token
);
122 for (window
= 0; window
< 256 ; window
++) {
124 * Find if we have a type in this window.
126 for (octet
= 31; octet
>= 0; octet
--)
127 if (bm
[window
* 32 + octet
] != 0)
131 RETERR(uint8_tobuffer(window
, target
));
132 RETERR(uint8_tobuffer(octet
+ 1, target
));
133 RETERR(mem_tobuffer(target
, &bm
[window
* 32], octet
+ 1));
135 return (ISC_R_SUCCESS
);
138 static inline isc_result_t
139 totext_nsec3(ARGS_TOTEXT
) {
141 unsigned int i
, j
, k
;
142 unsigned int window
, len
;
145 char buf
[sizeof("65535 ")];
146 isc_uint32_t iterations
;
148 REQUIRE(rdata
->type
== 50);
149 REQUIRE(rdata
->length
!= 0);
153 dns_rdata_toregion(rdata
, &sr
);
155 hash
= uint8_fromregion(&sr
);
156 isc_region_consume(&sr
, 1);
158 flags
= uint8_fromregion(&sr
);
159 isc_region_consume(&sr
, 1);
161 iterations
= uint16_fromregion(&sr
);
162 isc_region_consume(&sr
, 2);
164 sprintf(buf
, "%u ", hash
);
165 RETERR(str_totext(buf
, target
));
167 sprintf(buf
, "%u ", flags
);
168 RETERR(str_totext(buf
, target
));
170 sprintf(buf
, "%u ", iterations
);
171 RETERR(str_totext(buf
, target
));
173 j
= uint8_fromregion(&sr
);
174 isc_region_consume(&sr
, 1);
175 INSIST(j
<= sr
.length
);
180 RETERR(isc_hex_totext(&sr
, 1, "", target
));
182 RETERR(str_totext(" ", target
));
184 RETERR(str_totext("- ", target
));
186 j
= uint8_fromregion(&sr
);
187 isc_region_consume(&sr
, 1);
188 INSIST(j
<= sr
.length
);
192 RETERR(isc_base32hex_totext(&sr
, 1, "", target
));
195 for (i
= 0; i
< sr
.length
; i
+= len
) {
196 INSIST(i
+ 2 <= sr
.length
);
198 len
= sr
.base
[i
+ 1];
199 INSIST(len
> 0 && len
<= 32);
201 INSIST(i
+ len
<= sr
.length
);
202 for (j
= 0; j
< len
; j
++) {
204 if (sr
.base
[i
+ j
] == 0)
206 for (k
= 0; k
< 8; k
++) {
207 if ((sr
.base
[i
+ j
] & (0x80 >> k
)) == 0)
209 t
= window
* 256 + j
* 8 + k
;
210 RETERR(str_totext(" ", target
));
211 if (dns_rdatatype_isknown(t
)) {
212 RETERR(dns_rdatatype_totext(t
, target
));
214 char buf
[sizeof("TYPE65535")];
215 sprintf(buf
, "TYPE%u", t
);
216 RETERR(str_totext(buf
, target
));
221 return (ISC_R_SUCCESS
);
224 static inline isc_result_t
225 fromwire_nsec3(ARGS_FROMWIRE
) {
227 unsigned int window
, lastwindow
= 0;
229 unsigned int saltlen
, hashlen
;
230 isc_boolean_t first
= ISC_TRUE
;
240 isc_buffer_activeregion(source
, &sr
);
243 /* hash(1), flags(1), iteration(2), saltlen(1) */
245 RETERR(DNS_R_FORMERR
);
246 saltlen
= sr
.base
[4];
247 isc_region_consume(&sr
, 5);
249 if (sr
.length
< saltlen
)
250 RETERR(DNS_R_FORMERR
);
251 isc_region_consume(&sr
, saltlen
);
254 RETERR(DNS_R_FORMERR
);
255 hashlen
= sr
.base
[0];
256 isc_region_consume(&sr
, 1);
258 if (sr
.length
< hashlen
)
259 RETERR(DNS_R_FORMERR
);
260 isc_region_consume(&sr
, hashlen
);
262 for (i
= 0; i
< sr
.length
; i
+= len
) {
264 * Check for overflow.
266 if (i
+ 2 > sr
.length
)
267 RETERR(DNS_R_FORMERR
);
269 len
= sr
.base
[i
+ 1];
272 * Check that bitmap windows are in the correct order.
274 if (!first
&& window
<= lastwindow
)
275 RETERR(DNS_R_FORMERR
);
277 * Check for legal lengths.
279 if (len
< 1 || len
> 32)
280 RETERR(DNS_R_FORMERR
);
282 * Check for overflow.
284 if (i
+ len
> sr
.length
)
285 RETERR(DNS_R_FORMERR
);
287 * The last octet of the bitmap must be non zero.
289 if (sr
.base
[i
+ len
- 1] == 0)
290 RETERR(DNS_R_FORMERR
);
295 return (DNS_R_EXTRADATA
);
296 RETERR(mem_tobuffer(target
, rr
.base
, rr
.length
));
297 isc_buffer_forward(source
, rr
.length
);
298 return (ISC_R_SUCCESS
);
301 static inline isc_result_t
302 towire_nsec3(ARGS_TOWIRE
) {
305 REQUIRE(rdata
->type
== 50);
306 REQUIRE(rdata
->length
!= 0);
310 dns_rdata_toregion(rdata
, &sr
);
311 return (mem_tobuffer(target
, sr
.base
, sr
.length
));
315 compare_nsec3(ARGS_COMPARE
) {
319 REQUIRE(rdata1
->type
== rdata2
->type
);
320 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
321 REQUIRE(rdata1
->type
== 50);
322 REQUIRE(rdata1
->length
!= 0);
323 REQUIRE(rdata2
->length
!= 0);
325 dns_rdata_toregion(rdata1
, &r1
);
326 dns_rdata_toregion(rdata2
, &r2
);
327 return (isc_region_compare(&r1
, &r2
));
330 static inline isc_result_t
331 fromstruct_nsec3(ARGS_FROMSTRUCT
) {
332 dns_rdata_nsec3_t
*nsec3
= source
;
333 unsigned int i
, len
, window
, lastwindow
= 0;
334 isc_boolean_t first
= ISC_TRUE
;
337 REQUIRE(source
!= NULL
);
338 REQUIRE(nsec3
->common
.rdtype
== type
);
339 REQUIRE(nsec3
->common
.rdclass
== rdclass
);
340 REQUIRE(nsec3
->typebits
!= NULL
|| nsec3
->len
== 0);
341 REQUIRE(nsec3
->hash
== dns_hash_sha1
);
346 RETERR(uint8_tobuffer(nsec3
->hash
, target
));
347 RETERR(uint8_tobuffer(nsec3
->flags
, target
));
348 RETERR(uint16_tobuffer(nsec3
->iterations
, target
));
349 RETERR(uint8_tobuffer(nsec3
->salt_length
, target
));
350 RETERR(mem_tobuffer(target
, nsec3
->salt
, nsec3
->salt_length
));
351 RETERR(uint8_tobuffer(nsec3
->next_length
, target
));
352 RETERR(mem_tobuffer(target
, nsec3
->next
, nsec3
->next_length
));
355 * Perform sanity check.
357 for (i
= 0; i
< nsec3
->len
; i
+= len
) {
358 INSIST(i
+ 2 <= nsec3
->len
);
359 window
= nsec3
->typebits
[i
];
360 len
= nsec3
->typebits
[i
+1];
362 INSIST(first
|| window
> lastwindow
);
363 INSIST(len
> 0 && len
<= 32);
364 INSIST(i
+ len
<= nsec3
->len
);
365 INSIST(nsec3
->typebits
[i
+ len
- 1] != 0);
369 return (mem_tobuffer(target
, nsec3
->typebits
, nsec3
->len
));
372 static inline isc_result_t
373 tostruct_nsec3(ARGS_TOSTRUCT
) {
375 dns_rdata_nsec3_t
*nsec3
= target
;
377 REQUIRE(rdata
->type
== 50);
378 REQUIRE(target
!= NULL
);
379 REQUIRE(rdata
->length
!= 0);
381 nsec3
->common
.rdclass
= rdata
->rdclass
;
382 nsec3
->common
.rdtype
= rdata
->type
;
383 ISC_LINK_INIT(&nsec3
->common
, link
);
385 region
.base
= rdata
->data
;
386 region
.length
= rdata
->length
;
387 nsec3
->hash
= uint8_consume_fromregion(®ion
);
388 nsec3
->flags
= uint8_consume_fromregion(®ion
);
389 nsec3
->iterations
= uint16_consume_fromregion(®ion
);
391 nsec3
->salt_length
= uint8_consume_fromregion(®ion
);
392 nsec3
->salt
= mem_maybedup(mctx
, region
.base
, nsec3
->salt_length
);
393 if (nsec3
->salt
== NULL
)
394 return (ISC_R_NOMEMORY
);
395 isc_region_consume(®ion
, nsec3
->salt_length
);
397 nsec3
->next_length
= uint8_consume_fromregion(®ion
);
398 nsec3
->next
= mem_maybedup(mctx
, region
.base
, nsec3
->next_length
);
399 if (nsec3
->next
== NULL
)
401 isc_region_consume(®ion
, nsec3
->next_length
);
403 nsec3
->len
= region
.length
;
404 nsec3
->typebits
= mem_maybedup(mctx
, region
.base
, region
.length
);
405 if (nsec3
->typebits
== NULL
)
409 return (ISC_R_SUCCESS
);
412 if (nsec3
->next
!= NULL
)
413 isc_mem_free(mctx
, nsec3
->next
);
414 isc_mem_free(mctx
, nsec3
->salt
);
415 return (ISC_R_NOMEMORY
);
419 freestruct_nsec3(ARGS_FREESTRUCT
) {
420 dns_rdata_nsec3_t
*nsec3
= source
;
422 REQUIRE(source
!= NULL
);
423 REQUIRE(nsec3
->common
.rdtype
== 50);
425 if (nsec3
->mctx
== NULL
)
428 if (nsec3
->salt
!= NULL
)
429 isc_mem_free(nsec3
->mctx
, nsec3
->salt
);
430 if (nsec3
->next
!= NULL
)
431 isc_mem_free(nsec3
->mctx
, nsec3
->next
);
432 if (nsec3
->typebits
!= NULL
)
433 isc_mem_free(nsec3
->mctx
, nsec3
->typebits
);
437 static inline isc_result_t
438 additionaldata_nsec3(ARGS_ADDLDATA
) {
439 REQUIRE(rdata
->type
== 50);
445 return (ISC_R_SUCCESS
);
448 static inline isc_result_t
449 digest_nsec3(ARGS_DIGEST
) {
452 REQUIRE(rdata
->type
== 50);
454 dns_rdata_toregion(rdata
, &r
);
455 return ((digest
)(arg
, &r
));
458 static inline isc_boolean_t
459 checkowner_nsec3(ARGS_CHECKOWNER
) {
471 static inline isc_boolean_t
472 checknames_nsec3(ARGS_CHECKNAMES
) {
474 REQUIRE(rdata
->type
== 50);
484 casecompare_nsec3(ARGS_COMPARE
) {
485 return (compare_nsec3(rdata1
, rdata2
));
488 #endif /* RDATA_GENERIC_NSEC3_50_C */