1 /*	$NetBSD: tlsa_52.c,v 1.9 2022/09/23 12:15:31 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /* rfc6698.txt */
17 
18 #ifndef RDATA_GENERIC_TLSA_52_C
19 #define RDATA_GENERIC_TLSA_52_C
20 
21 #define RRTYPE_TLSA_ATTRIBUTES 0
22 
23 static isc_result_t
generic_fromtext_tlsa(ARGS_FROMTEXT)24 generic_fromtext_tlsa(ARGS_FROMTEXT) {
25 	isc_token_t token;
26 
27 	UNUSED(type);
28 	UNUSED(rdclass);
29 	UNUSED(origin);
30 	UNUSED(options);
31 	UNUSED(callbacks);
32 
33 	/*
34 	 * Certificate Usage.
35 	 */
36 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
37 				      false));
38 	if (token.value.as_ulong > 0xffU) {
39 		RETTOK(ISC_R_RANGE);
40 	}
41 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
42 
43 	/*
44 	 * Selector.
45 	 */
46 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
47 				      false));
48 	if (token.value.as_ulong > 0xffU) {
49 		RETTOK(ISC_R_RANGE);
50 	}
51 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
52 
53 	/*
54 	 * Matching type.
55 	 */
56 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
57 				      false));
58 	if (token.value.as_ulong > 0xffU) {
59 		RETTOK(ISC_R_RANGE);
60 	}
61 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
62 
63 	/*
64 	 * Certificate Association Data.
65 	 */
66 	return (isc_hex_tobuffer(lexer, target, -2));
67 }
68 
69 static isc_result_t
generic_totext_tlsa(ARGS_TOTEXT)70 generic_totext_tlsa(ARGS_TOTEXT) {
71 	isc_region_t sr;
72 	char buf[sizeof("64000 ")];
73 	unsigned int n;
74 
75 	REQUIRE(rdata->length != 0);
76 
77 	UNUSED(tctx);
78 
79 	dns_rdata_toregion(rdata, &sr);
80 
81 	/*
82 	 * Certificate Usage.
83 	 */
84 	n = uint8_fromregion(&sr);
85 	isc_region_consume(&sr, 1);
86 	snprintf(buf, sizeof(buf), "%u ", n);
87 	RETERR(str_totext(buf, target));
88 
89 	/*
90 	 * Selector.
91 	 */
92 	n = uint8_fromregion(&sr);
93 	isc_region_consume(&sr, 1);
94 	snprintf(buf, sizeof(buf), "%u ", n);
95 	RETERR(str_totext(buf, target));
96 
97 	/*
98 	 * Matching type.
99 	 */
100 	n = uint8_fromregion(&sr);
101 	isc_region_consume(&sr, 1);
102 	snprintf(buf, sizeof(buf), "%u", n);
103 	RETERR(str_totext(buf, target));
104 
105 	/*
106 	 * Certificate Association Data.
107 	 */
108 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
109 		RETERR(str_totext(" (", target));
110 	}
111 	RETERR(str_totext(tctx->linebreak, target));
112 	if (tctx->width == 0) { /* No splitting */
113 		RETERR(isc_hex_totext(&sr, 0, "", target));
114 	} else {
115 		RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak,
116 				      target));
117 	}
118 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
119 		RETERR(str_totext(" )", target));
120 	}
121 	return (ISC_R_SUCCESS);
122 }
123 
124 static isc_result_t
generic_fromwire_tlsa(ARGS_FROMWIRE)125 generic_fromwire_tlsa(ARGS_FROMWIRE) {
126 	isc_region_t sr;
127 
128 	UNUSED(type);
129 	UNUSED(rdclass);
130 	UNUSED(dctx);
131 	UNUSED(options);
132 
133 	isc_buffer_activeregion(source, &sr);
134 
135 	/* Usage(1), Selector(1), Type(1), Data(1+) */
136 	if (sr.length < 4) {
137 		return (ISC_R_UNEXPECTEDEND);
138 	}
139 
140 	isc_buffer_forward(source, sr.length);
141 	return (mem_tobuffer(target, sr.base, sr.length));
142 }
143 
144 static isc_result_t
fromtext_tlsa(ARGS_FROMTEXT)145 fromtext_tlsa(ARGS_FROMTEXT) {
146 	REQUIRE(type == dns_rdatatype_tlsa);
147 
148 	return (generic_fromtext_tlsa(CALL_FROMTEXT));
149 }
150 
151 static isc_result_t
totext_tlsa(ARGS_TOTEXT)152 totext_tlsa(ARGS_TOTEXT) {
153 	REQUIRE(rdata->type == dns_rdatatype_tlsa);
154 
155 	return (generic_totext_tlsa(CALL_TOTEXT));
156 }
157 
158 static isc_result_t
fromwire_tlsa(ARGS_FROMWIRE)159 fromwire_tlsa(ARGS_FROMWIRE) {
160 	REQUIRE(type == dns_rdatatype_tlsa);
161 
162 	return (generic_fromwire_tlsa(CALL_FROMWIRE));
163 }
164 
165 static isc_result_t
towire_tlsa(ARGS_TOWIRE)166 towire_tlsa(ARGS_TOWIRE) {
167 	isc_region_t sr;
168 
169 	REQUIRE(rdata->type == dns_rdatatype_tlsa);
170 	REQUIRE(rdata->length != 0);
171 
172 	UNUSED(cctx);
173 
174 	dns_rdata_toregion(rdata, &sr);
175 	return (mem_tobuffer(target, sr.base, sr.length));
176 }
177 
178 static int
compare_tlsa(ARGS_COMPARE)179 compare_tlsa(ARGS_COMPARE) {
180 	isc_region_t r1;
181 	isc_region_t r2;
182 
183 	REQUIRE(rdata1->type == rdata2->type);
184 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
185 	REQUIRE(rdata1->type == dns_rdatatype_tlsa);
186 	REQUIRE(rdata1->length != 0);
187 	REQUIRE(rdata2->length != 0);
188 
189 	dns_rdata_toregion(rdata1, &r1);
190 	dns_rdata_toregion(rdata2, &r2);
191 	return (isc_region_compare(&r1, &r2));
192 }
193 
194 static isc_result_t
generic_fromstruct_tlsa(ARGS_FROMSTRUCT)195 generic_fromstruct_tlsa(ARGS_FROMSTRUCT) {
196 	dns_rdata_tlsa_t *tlsa = source;
197 
198 	REQUIRE(tlsa != NULL);
199 	REQUIRE(tlsa->common.rdtype == type);
200 	REQUIRE(tlsa->common.rdclass == rdclass);
201 
202 	UNUSED(type);
203 	UNUSED(rdclass);
204 
205 	RETERR(uint8_tobuffer(tlsa->usage, target));
206 	RETERR(uint8_tobuffer(tlsa->selector, target));
207 	RETERR(uint8_tobuffer(tlsa->match, target));
208 
209 	return (mem_tobuffer(target, tlsa->data, tlsa->length));
210 }
211 
212 static isc_result_t
generic_tostruct_tlsa(ARGS_TOSTRUCT)213 generic_tostruct_tlsa(ARGS_TOSTRUCT) {
214 	dns_rdata_tlsa_t *tlsa = target;
215 	isc_region_t region;
216 
217 	REQUIRE(tlsa != NULL);
218 	REQUIRE(rdata->length != 0);
219 
220 	REQUIRE(tlsa != NULL);
221 	REQUIRE(tlsa->common.rdclass == rdata->rdclass);
222 	REQUIRE(tlsa->common.rdtype == rdata->type);
223 	REQUIRE(!ISC_LINK_LINKED(&tlsa->common, link));
224 
225 	dns_rdata_toregion(rdata, &region);
226 
227 	tlsa->usage = uint8_fromregion(&region);
228 	isc_region_consume(&region, 1);
229 	tlsa->selector = uint8_fromregion(&region);
230 	isc_region_consume(&region, 1);
231 	tlsa->match = uint8_fromregion(&region);
232 	isc_region_consume(&region, 1);
233 	tlsa->length = region.length;
234 
235 	tlsa->data = mem_maybedup(mctx, region.base, region.length);
236 	if (tlsa->data == NULL) {
237 		return (ISC_R_NOMEMORY);
238 	}
239 
240 	tlsa->mctx = mctx;
241 	return (ISC_R_SUCCESS);
242 }
243 
244 static void
generic_freestruct_tlsa(ARGS_FREESTRUCT)245 generic_freestruct_tlsa(ARGS_FREESTRUCT) {
246 	dns_rdata_tlsa_t *tlsa = source;
247 
248 	REQUIRE(tlsa != NULL);
249 
250 	if (tlsa->mctx == NULL) {
251 		return;
252 	}
253 
254 	if (tlsa->data != NULL) {
255 		isc_mem_free(tlsa->mctx, tlsa->data);
256 	}
257 	tlsa->mctx = NULL;
258 }
259 
260 static isc_result_t
fromstruct_tlsa(ARGS_FROMSTRUCT)261 fromstruct_tlsa(ARGS_FROMSTRUCT) {
262 	REQUIRE(type == dns_rdatatype_tlsa);
263 
264 	return (generic_fromstruct_tlsa(CALL_FROMSTRUCT));
265 }
266 
267 static isc_result_t
tostruct_tlsa(ARGS_TOSTRUCT)268 tostruct_tlsa(ARGS_TOSTRUCT) {
269 	dns_rdata_tlsa_t *tlsa = target;
270 
271 	REQUIRE(rdata->type == dns_rdatatype_tlsa);
272 	REQUIRE(tlsa != NULL);
273 
274 	tlsa->common.rdclass = rdata->rdclass;
275 	tlsa->common.rdtype = rdata->type;
276 	ISC_LINK_INIT(&tlsa->common, link);
277 
278 	return (generic_tostruct_tlsa(CALL_TOSTRUCT));
279 }
280 
281 static void
freestruct_tlsa(ARGS_FREESTRUCT)282 freestruct_tlsa(ARGS_FREESTRUCT) {
283 	dns_rdata_tlsa_t *tlsa = source;
284 
285 	REQUIRE(tlsa != NULL);
286 	REQUIRE(tlsa->common.rdtype == dns_rdatatype_tlsa);
287 
288 	generic_freestruct_tlsa(source);
289 }
290 
291 static isc_result_t
additionaldata_tlsa(ARGS_ADDLDATA)292 additionaldata_tlsa(ARGS_ADDLDATA) {
293 	REQUIRE(rdata->type == dns_rdatatype_tlsa);
294 
295 	UNUSED(rdata);
296 	UNUSED(add);
297 	UNUSED(arg);
298 
299 	return (ISC_R_SUCCESS);
300 }
301 
302 static isc_result_t
digest_tlsa(ARGS_DIGEST)303 digest_tlsa(ARGS_DIGEST) {
304 	isc_region_t r;
305 
306 	REQUIRE(rdata->type == dns_rdatatype_tlsa);
307 
308 	dns_rdata_toregion(rdata, &r);
309 
310 	return ((digest)(arg, &r));
311 }
312 
313 static bool
checkowner_tlsa(ARGS_CHECKOWNER)314 checkowner_tlsa(ARGS_CHECKOWNER) {
315 	REQUIRE(type == dns_rdatatype_tlsa);
316 
317 	UNUSED(name);
318 	UNUSED(type);
319 	UNUSED(rdclass);
320 	UNUSED(wildcard);
321 
322 	return (true);
323 }
324 
325 static bool
checknames_tlsa(ARGS_CHECKNAMES)326 checknames_tlsa(ARGS_CHECKNAMES) {
327 	REQUIRE(rdata->type == dns_rdatatype_tlsa);
328 
329 	UNUSED(rdata);
330 	UNUSED(owner);
331 	UNUSED(bad);
332 
333 	return (true);
334 }
335 
336 static int
casecompare_tlsa(ARGS_COMPARE)337 casecompare_tlsa(ARGS_COMPARE) {
338 	return (compare_tlsa(rdata1, rdata2));
339 }
340 
341 #endif /* RDATA_GENERIC_TLSA_52_C */
342