1/*
2 * Copyright (C) 2008, 2009  Internet Systems Consortium, Inc. ("ISC")
3 *
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.
7 *
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.
15 */
16
17/* $Id: nsec3param_51.c,v 1.7 2009/12/04 21:09:34 marka Exp $ */
18
19/*
20 * Copyright (C) 2004  Nominet, Ltd.
21 *
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.
25 *
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.
33 */
34
35/* RFC 5155 */
36
37#ifndef RDATA_GENERIC_NSEC3PARAM_51_C
38#define RDATA_GENERIC_NSEC3PARAM_51_C
39
40#include <isc/iterated_hash.h>
41#include <isc/base32.h>
42
43#define RRTYPE_NSEC3PARAM_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
44
45static inline isc_result_t
46fromtext_nsec3param(ARGS_FROMTEXT) {
47	isc_token_t token;
48	unsigned int flags = 0;
49	unsigned char hashalg;
50
51	REQUIRE(type == 51);
52
53	UNUSED(type);
54	UNUSED(rdclass);
55	UNUSED(callbacks);
56	UNUSED(origin);
57	UNUSED(options);
58
59	/* Hash. */
60	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
61				      ISC_FALSE));
62	RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
63	RETERR(uint8_tobuffer(hashalg, target));
64
65	/* Flags. */
66	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
67				      ISC_FALSE));
68	flags = token.value.as_ulong;
69	if (flags > 255U)
70		RETTOK(ISC_R_RANGE);
71	RETERR(uint8_tobuffer(flags, target));
72
73	/* Iterations. */
74	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
75				      ISC_FALSE));
76	if (token.value.as_ulong > 0xffffU)
77		RETTOK(ISC_R_RANGE);
78	RETERR(uint16_tobuffer(token.value.as_ulong, target));
79
80	/* Salt. */
81	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
82				      ISC_FALSE));
83	if (token.value.as_textregion.length > (255*2))
84		RETTOK(DNS_R_TEXTTOOLONG);
85	if (strcmp(DNS_AS_STR(token), "-") == 0) {
86		RETERR(uint8_tobuffer(0, target));
87	} else {
88		RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
89		RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
90	}
91
92	return (ISC_R_SUCCESS);
93}
94
95static inline isc_result_t
96totext_nsec3param(ARGS_TOTEXT) {
97	isc_region_t sr;
98	unsigned int i, j;
99	unsigned char hash;
100	unsigned char flags;
101	char buf[sizeof("65535 ")];
102	isc_uint32_t iterations;
103
104	REQUIRE(rdata->type == 51);
105	REQUIRE(rdata->length != 0);
106
107	UNUSED(tctx);
108
109	dns_rdata_toregion(rdata, &sr);
110
111	hash = uint8_fromregion(&sr);
112	isc_region_consume(&sr, 1);
113
114	flags = uint8_fromregion(&sr);
115	isc_region_consume(&sr, 1);
116
117	iterations = uint16_fromregion(&sr);
118	isc_region_consume(&sr, 2);
119
120	sprintf(buf, "%u ", hash);
121	RETERR(str_totext(buf, target));
122
123	sprintf(buf, "%u ", flags);
124	RETERR(str_totext(buf, target));
125
126	sprintf(buf, "%u ", iterations);
127	RETERR(str_totext(buf, target));
128
129	j = uint8_fromregion(&sr);
130	isc_region_consume(&sr, 1);
131	INSIST(j <= sr.length);
132
133	if (j != 0) {
134		i = sr.length;
135		sr.length = j;
136		RETERR(isc_hex_totext(&sr, 1, "", target));
137		sr.length = i - j;
138	} else
139		RETERR(str_totext("-", target));
140
141	return (ISC_R_SUCCESS);
142}
143
144static inline isc_result_t
145fromwire_nsec3param(ARGS_FROMWIRE) {
146	isc_region_t sr, rr;
147	unsigned int saltlen;
148
149	REQUIRE(type == 51);
150
151	UNUSED(type);
152	UNUSED(rdclass);
153	UNUSED(options);
154	UNUSED(dctx);
155
156	isc_buffer_activeregion(source, &sr);
157	rr = sr;
158
159	/* hash(1), flags(1), iterations(2), saltlen(1) */
160	if (sr.length < 5U)
161		RETERR(DNS_R_FORMERR);
162	saltlen = sr.base[4];
163	isc_region_consume(&sr, 5);
164
165	if (sr.length < saltlen)
166		RETERR(DNS_R_FORMERR);
167	isc_region_consume(&sr, saltlen);
168	RETERR(mem_tobuffer(target, rr.base, rr.length));
169	isc_buffer_forward(source, rr.length);
170	return (ISC_R_SUCCESS);
171}
172
173static inline isc_result_t
174towire_nsec3param(ARGS_TOWIRE) {
175	isc_region_t sr;
176
177	REQUIRE(rdata->type == 51);
178	REQUIRE(rdata->length != 0);
179
180	UNUSED(cctx);
181
182	dns_rdata_toregion(rdata, &sr);
183	return (mem_tobuffer(target, sr.base, sr.length));
184}
185
186static inline int
187compare_nsec3param(ARGS_COMPARE) {
188	isc_region_t r1;
189	isc_region_t r2;
190
191	REQUIRE(rdata1->type == rdata2->type);
192	REQUIRE(rdata1->rdclass == rdata2->rdclass);
193	REQUIRE(rdata1->type == 51);
194	REQUIRE(rdata1->length != 0);
195	REQUIRE(rdata2->length != 0);
196
197	dns_rdata_toregion(rdata1, &r1);
198	dns_rdata_toregion(rdata2, &r2);
199	return (isc_region_compare(&r1, &r2));
200}
201
202static inline isc_result_t
203fromstruct_nsec3param(ARGS_FROMSTRUCT) {
204	dns_rdata_nsec3param_t *nsec3param = source;
205
206	REQUIRE(type == 51);
207	REQUIRE(source != NULL);
208	REQUIRE(nsec3param->common.rdtype == type);
209	REQUIRE(nsec3param->common.rdclass == rdclass);
210
211	UNUSED(type);
212	UNUSED(rdclass);
213
214	RETERR(uint8_tobuffer(nsec3param->hash, target));
215	RETERR(uint8_tobuffer(nsec3param->flags, target));
216	RETERR(uint16_tobuffer(nsec3param->iterations, target));
217	RETERR(uint8_tobuffer(nsec3param->salt_length, target));
218	RETERR(mem_tobuffer(target, nsec3param->salt,
219			    nsec3param->salt_length));
220	return (ISC_R_SUCCESS);
221}
222
223static inline isc_result_t
224tostruct_nsec3param(ARGS_TOSTRUCT) {
225	isc_region_t region;
226	dns_rdata_nsec3param_t *nsec3param = target;
227
228	REQUIRE(rdata->type == 51);
229	REQUIRE(target != NULL);
230	REQUIRE(rdata->length != 0);
231
232	nsec3param->common.rdclass = rdata->rdclass;
233	nsec3param->common.rdtype = rdata->type;
234	ISC_LINK_INIT(&nsec3param->common, link);
235
236	region.base = rdata->data;
237	region.length = rdata->length;
238	nsec3param->hash = uint8_consume_fromregion(&region);
239	nsec3param->flags = uint8_consume_fromregion(&region);
240	nsec3param->iterations = uint16_consume_fromregion(&region);
241
242	nsec3param->salt_length = uint8_consume_fromregion(&region);
243	nsec3param->salt = mem_maybedup(mctx, region.base,
244					nsec3param->salt_length);
245	if (nsec3param->salt == NULL)
246		return (ISC_R_NOMEMORY);
247	isc_region_consume(&region, nsec3param->salt_length);
248
249	nsec3param->mctx = mctx;
250	return (ISC_R_SUCCESS);
251}
252
253static inline void
254freestruct_nsec3param(ARGS_FREESTRUCT) {
255	dns_rdata_nsec3param_t *nsec3param = source;
256
257	REQUIRE(source != NULL);
258	REQUIRE(nsec3param->common.rdtype == 51);
259
260	if (nsec3param->mctx == NULL)
261		return;
262
263	if (nsec3param->salt != NULL)
264		isc_mem_free(nsec3param->mctx, nsec3param->salt);
265	nsec3param->mctx = NULL;
266}
267
268static inline isc_result_t
269additionaldata_nsec3param(ARGS_ADDLDATA) {
270	REQUIRE(rdata->type == 51);
271
272	UNUSED(rdata);
273	UNUSED(add);
274	UNUSED(arg);
275
276	return (ISC_R_SUCCESS);
277}
278
279static inline isc_result_t
280digest_nsec3param(ARGS_DIGEST) {
281	isc_region_t r;
282
283	REQUIRE(rdata->type == 51);
284
285	dns_rdata_toregion(rdata, &r);
286	return ((digest)(arg, &r));
287}
288
289static inline isc_boolean_t
290checkowner_nsec3param(ARGS_CHECKOWNER) {
291
292       REQUIRE(type == 51);
293
294       UNUSED(name);
295       UNUSED(type);
296       UNUSED(rdclass);
297       UNUSED(wildcard);
298
299       return (ISC_TRUE);
300}
301
302static inline isc_boolean_t
303checknames_nsec3param(ARGS_CHECKNAMES) {
304
305	REQUIRE(rdata->type == 51);
306
307	UNUSED(rdata);
308	UNUSED(owner);
309	UNUSED(bad);
310
311	return (ISC_TRUE);
312}
313
314static inline int
315casecompare_nsec3param(ARGS_COMPARE) {
316	return (compare_nsec3param(rdata1, rdata2));
317}
318
319#endif	/* RDATA_GENERIC_NSEC3PARAM_51_C */
320