1 /* $NetBSD: nsec3_50.c,v 1.8 2015/07/08 17:28:59 christos Exp $ */
4 * Copyright (C) 2008, 2009, 2011, 2012, 2014, 2015 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.
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_base32hexnp_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("TYPE65535")];
146 isc_uint32_t iterations
;
149 REQUIRE(rdata
->type
== 50);
150 REQUIRE(rdata
->length
!= 0);
152 dns_rdata_toregion(rdata
, &sr
);
155 hash
= uint8_fromregion(&sr
);
156 isc_region_consume(&sr
, 1);
157 sprintf(buf
, "%u ", hash
);
158 RETERR(str_totext(buf
, target
));
161 flags
= uint8_fromregion(&sr
);
162 isc_region_consume(&sr
, 1);
163 sprintf(buf
, "%u ", flags
);
164 RETERR(str_totext(buf
, target
));
167 iterations
= uint16_fromregion(&sr
);
168 isc_region_consume(&sr
, 2);
169 sprintf(buf
, "%u ", iterations
);
170 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
));
183 RETERR(str_totext("-", target
));
185 if ((tctx
->flags
& DNS_STYLEFLAG_MULTILINE
) != 0)
186 RETERR(str_totext(" (", target
));
187 RETERR(str_totext(tctx
->linebreak
, target
));
190 j
= uint8_fromregion(&sr
);
191 isc_region_consume(&sr
, 1);
192 INSIST(j
<= sr
.length
);
196 RETERR(isc_base32hexnp_totext(&sr
, 1, "", target
));
199 if ((tctx
->flags
& DNS_STYLEFLAG_MULTILINE
) == 0)
200 RETERR(str_totext(" ", target
));
204 for (i
= 0; i
< sr
.length
; i
+= len
) {
205 if ((tctx
->flags
& DNS_STYLEFLAG_MULTILINE
) != 0) {
206 RETERR(str_totext(tctx
->linebreak
, target
));
209 INSIST(i
+ 2 <= sr
.length
);
211 len
= sr
.base
[i
+ 1];
212 INSIST(len
> 0 && len
<= 32);
214 INSIST(i
+ len
<= sr
.length
);
215 for (j
= 0; j
< len
; j
++) {
217 if (sr
.base
[i
+ j
] == 0)
219 for (k
= 0; k
< 8; k
++) {
220 if ((sr
.base
[i
+ j
] & (0x80 >> k
)) == 0)
222 t
= window
* 256 + j
* 8 + k
;
224 RETERR(str_totext(" ", target
));
226 if (dns_rdatatype_isknown(t
)) {
227 RETERR(dns_rdatatype_totext(t
, target
));
229 sprintf(buf
, "TYPE%u", t
);
230 RETERR(str_totext(buf
, target
));
236 if ((tctx
->flags
& DNS_STYLEFLAG_MULTILINE
) != 0)
237 RETERR(str_totext(" )", target
));
239 return (ISC_R_SUCCESS
);
242 static inline isc_result_t
243 fromwire_nsec3(ARGS_FROMWIRE
) {
245 unsigned int window
, lastwindow
= 0;
247 unsigned int saltlen
, hashlen
;
248 isc_boolean_t first
= ISC_TRUE
;
258 isc_buffer_activeregion(source
, &sr
);
261 /* hash(1), flags(1), iteration(2), saltlen(1) */
263 RETERR(DNS_R_FORMERR
);
264 saltlen
= sr
.base
[4];
265 isc_region_consume(&sr
, 5);
267 if (sr
.length
< saltlen
)
268 RETERR(DNS_R_FORMERR
);
269 isc_region_consume(&sr
, saltlen
);
272 RETERR(DNS_R_FORMERR
);
273 hashlen
= sr
.base
[0];
274 isc_region_consume(&sr
, 1);
276 if (sr
.length
< hashlen
)
277 RETERR(DNS_R_FORMERR
);
278 isc_region_consume(&sr
, hashlen
);
280 for (i
= 0; i
< sr
.length
; i
+= len
) {
282 * Check for overflow.
284 if (i
+ 2 > sr
.length
)
285 RETERR(DNS_R_FORMERR
);
287 len
= sr
.base
[i
+ 1];
290 * Check that bitmap windows are in the correct order.
292 if (!first
&& window
<= lastwindow
)
293 RETERR(DNS_R_FORMERR
);
295 * Check for legal lengths.
297 if (len
< 1 || len
> 32)
298 RETERR(DNS_R_FORMERR
);
300 * Check for overflow.
302 if (i
+ len
> sr
.length
)
303 RETERR(DNS_R_FORMERR
);
305 * The last octet of the bitmap must be non zero.
307 if (sr
.base
[i
+ len
- 1] == 0)
308 RETERR(DNS_R_FORMERR
);
313 return (DNS_R_EXTRADATA
);
314 RETERR(mem_tobuffer(target
, rr
.base
, rr
.length
));
315 isc_buffer_forward(source
, rr
.length
);
316 return (ISC_R_SUCCESS
);
319 static inline isc_result_t
320 towire_nsec3(ARGS_TOWIRE
) {
323 REQUIRE(rdata
->type
== 50);
324 REQUIRE(rdata
->length
!= 0);
328 dns_rdata_toregion(rdata
, &sr
);
329 return (mem_tobuffer(target
, sr
.base
, sr
.length
));
333 compare_nsec3(ARGS_COMPARE
) {
337 REQUIRE(rdata1
->type
== rdata2
->type
);
338 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
339 REQUIRE(rdata1
->type
== 50);
340 REQUIRE(rdata1
->length
!= 0);
341 REQUIRE(rdata2
->length
!= 0);
343 dns_rdata_toregion(rdata1
, &r1
);
344 dns_rdata_toregion(rdata2
, &r2
);
345 return (isc_region_compare(&r1
, &r2
));
348 static inline isc_result_t
349 fromstruct_nsec3(ARGS_FROMSTRUCT
) {
350 dns_rdata_nsec3_t
*nsec3
= source
;
351 unsigned int i
, len
, window
, lastwindow
= 0;
352 isc_boolean_t first
= ISC_TRUE
;
355 REQUIRE(source
!= NULL
);
356 REQUIRE(nsec3
->common
.rdtype
== type
);
357 REQUIRE(nsec3
->common
.rdclass
== rdclass
);
358 REQUIRE(nsec3
->typebits
!= NULL
|| nsec3
->len
== 0);
359 REQUIRE(nsec3
->hash
== dns_hash_sha1
);
364 RETERR(uint8_tobuffer(nsec3
->hash
, target
));
365 RETERR(uint8_tobuffer(nsec3
->flags
, target
));
366 RETERR(uint16_tobuffer(nsec3
->iterations
, target
));
367 RETERR(uint8_tobuffer(nsec3
->salt_length
, target
));
368 RETERR(mem_tobuffer(target
, nsec3
->salt
, nsec3
->salt_length
));
369 RETERR(uint8_tobuffer(nsec3
->next_length
, target
));
370 RETERR(mem_tobuffer(target
, nsec3
->next
, nsec3
->next_length
));
373 * Perform sanity check.
375 for (i
= 0; i
< nsec3
->len
; i
+= len
) {
376 INSIST(i
+ 2 <= nsec3
->len
);
377 window
= nsec3
->typebits
[i
];
378 len
= nsec3
->typebits
[i
+1];
380 INSIST(first
|| window
> lastwindow
);
381 INSIST(len
> 0 && len
<= 32);
382 INSIST(i
+ len
<= nsec3
->len
);
383 INSIST(nsec3
->typebits
[i
+ len
- 1] != 0);
387 return (mem_tobuffer(target
, nsec3
->typebits
, nsec3
->len
));
390 static inline isc_result_t
391 tostruct_nsec3(ARGS_TOSTRUCT
) {
393 dns_rdata_nsec3_t
*nsec3
= target
;
395 REQUIRE(rdata
->type
== 50);
396 REQUIRE(target
!= NULL
);
397 REQUIRE(rdata
->length
!= 0);
399 nsec3
->common
.rdclass
= rdata
->rdclass
;
400 nsec3
->common
.rdtype
= rdata
->type
;
401 ISC_LINK_INIT(&nsec3
->common
, link
);
403 region
.base
= rdata
->data
;
404 region
.length
= rdata
->length
;
405 nsec3
->hash
= uint8_consume_fromregion(®ion
);
406 nsec3
->flags
= uint8_consume_fromregion(®ion
);
407 nsec3
->iterations
= uint16_consume_fromregion(®ion
);
409 nsec3
->salt_length
= uint8_consume_fromregion(®ion
);
410 nsec3
->salt
= mem_maybedup(mctx
, region
.base
, nsec3
->salt_length
);
411 if (nsec3
->salt
== NULL
)
412 return (ISC_R_NOMEMORY
);
413 isc_region_consume(®ion
, nsec3
->salt_length
);
415 nsec3
->next_length
= uint8_consume_fromregion(®ion
);
416 nsec3
->next
= mem_maybedup(mctx
, region
.base
, nsec3
->next_length
);
417 if (nsec3
->next
== NULL
)
419 isc_region_consume(®ion
, nsec3
->next_length
);
421 nsec3
->len
= region
.length
;
422 nsec3
->typebits
= mem_maybedup(mctx
, region
.base
, region
.length
);
423 if (nsec3
->typebits
== NULL
)
427 return (ISC_R_SUCCESS
);
430 if (nsec3
->next
!= NULL
)
431 isc_mem_free(mctx
, nsec3
->next
);
432 isc_mem_free(mctx
, nsec3
->salt
);
433 return (ISC_R_NOMEMORY
);
437 freestruct_nsec3(ARGS_FREESTRUCT
) {
438 dns_rdata_nsec3_t
*nsec3
= source
;
440 REQUIRE(source
!= NULL
);
441 REQUIRE(nsec3
->common
.rdtype
== 50);
443 if (nsec3
->mctx
== NULL
)
446 if (nsec3
->salt
!= NULL
)
447 isc_mem_free(nsec3
->mctx
, nsec3
->salt
);
448 if (nsec3
->next
!= NULL
)
449 isc_mem_free(nsec3
->mctx
, nsec3
->next
);
450 if (nsec3
->typebits
!= NULL
)
451 isc_mem_free(nsec3
->mctx
, nsec3
->typebits
);
455 static inline isc_result_t
456 additionaldata_nsec3(ARGS_ADDLDATA
) {
457 REQUIRE(rdata
->type
== 50);
463 return (ISC_R_SUCCESS
);
466 static inline isc_result_t
467 digest_nsec3(ARGS_DIGEST
) {
470 REQUIRE(rdata
->type
== 50);
472 dns_rdata_toregion(rdata
, &r
);
473 return ((digest
)(arg
, &r
));
476 static inline isc_boolean_t
477 checkowner_nsec3(ARGS_CHECKOWNER
) {
478 unsigned char owner
[NSEC3_MAX_HASH_LENGTH
];
489 * First label is a base32hex string without padding.
491 dns_name_getlabel(name
, 0, &label
);
492 isc_region_consume(&label
, 1);
493 isc_buffer_init(&buffer
, owner
, sizeof(owner
));
494 if (isc_base32hexnp_decoderegion(&label
, &buffer
) == ISC_R_SUCCESS
)
500 static inline isc_boolean_t
501 checknames_nsec3(ARGS_CHECKNAMES
) {
503 REQUIRE(rdata
->type
== 50);
513 casecompare_nsec3(ARGS_COMPARE
) {
514 return (compare_nsec3(rdata1
, rdata2
));
517 #endif /* RDATA_GENERIC_NSEC3_50_C */