/src/bind9/lib/dns/rdata/generic/zonemd_63.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
5 | | * |
6 | | * This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
9 | | * |
10 | | * See the COPYRIGHT file distributed with this work for additional |
11 | | * information regarding copyright ownership. |
12 | | */ |
13 | | |
14 | | /* RFC 8976 */ |
15 | | |
16 | | #ifndef RDATA_GENERIC_ZONEMD_63_C |
17 | | #define RDATA_GENERIC_ZONEMD_63_C |
18 | | |
19 | 12.7k | #define RRTYPE_ZONEMD_ATTRIBUTES 0 |
20 | | |
21 | | static isc_result_t |
22 | 562 | fromtext_zonemd(ARGS_FROMTEXT) { |
23 | 562 | isc_token_t token; |
24 | 562 | int digest_type, length; |
25 | 562 | isc_buffer_t save; |
26 | 562 | isc_result_t result; |
27 | | |
28 | 562 | UNUSED(type); |
29 | 562 | UNUSED(rdclass); |
30 | 562 | UNUSED(origin); |
31 | 562 | UNUSED(options); |
32 | 562 | UNUSED(callbacks); |
33 | | |
34 | | /* |
35 | | * Zone Serial. |
36 | | */ |
37 | 562 | RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, |
38 | 562 | false)); |
39 | 558 | RETERR(uint32_tobuffer(token.value.as_ulong, target)); |
40 | | |
41 | | /* |
42 | | * Digest Scheme. |
43 | | */ |
44 | 558 | RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, |
45 | 558 | false)); |
46 | 555 | RETERR(uint8_tobuffer(token.value.as_ulong, target)); |
47 | | |
48 | | /* |
49 | | * Digest Type. |
50 | | */ |
51 | 522 | RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, |
52 | 522 | false)); |
53 | 520 | digest_type = token.value.as_ulong; |
54 | 520 | RETERR(uint8_tobuffer(digest_type, target)); |
55 | | |
56 | | /* |
57 | | * Digest. |
58 | | */ |
59 | 516 | switch (digest_type) { |
60 | 271 | case DNS_ZONEMD_DIGEST_SHA384: |
61 | 271 | length = ISC_SHA384_DIGESTLENGTH; |
62 | 271 | break; |
63 | 182 | case DNS_ZONEMD_DIGEST_SHA512: |
64 | 182 | length = ISC_SHA512_DIGESTLENGTH; |
65 | 182 | break; |
66 | 63 | default: |
67 | 63 | length = -2; |
68 | 63 | break; |
69 | 516 | } |
70 | | |
71 | 516 | save = *target; |
72 | 516 | result = isc_hex_tobuffer(lexer, target, length); |
73 | | /* Minimum length of digest is 12 octets. */ |
74 | 516 | if (isc_buffer_usedlength(target) - isc_buffer_usedlength(&save) < 12) { |
75 | 12 | return (ISC_R_UNEXPECTEDEND); |
76 | 12 | } |
77 | 504 | return (result); |
78 | 516 | } |
79 | | |
80 | | static isc_result_t |
81 | 1.26k | totext_zonemd(ARGS_TOTEXT) { |
82 | 1.26k | isc_region_t sr; |
83 | 1.26k | char buf[sizeof("0123456789")]; |
84 | 1.26k | unsigned long num; |
85 | | |
86 | 1.26k | REQUIRE(rdata->length > 6); |
87 | | |
88 | 1.26k | UNUSED(tctx); |
89 | | |
90 | 1.26k | dns_rdata_toregion(rdata, &sr); |
91 | | |
92 | | /* |
93 | | * Zone Serial. |
94 | | */ |
95 | 1.26k | num = uint32_fromregion(&sr); |
96 | 1.26k | isc_region_consume(&sr, 4); |
97 | 1.26k | snprintf(buf, sizeof(buf), "%lu", num); |
98 | 1.26k | RETERR(str_totext(buf, target)); |
99 | | |
100 | 1.26k | RETERR(str_totext(" ", target)); |
101 | | |
102 | | /* |
103 | | * Digest scheme. |
104 | | */ |
105 | 1.26k | num = uint8_fromregion(&sr); |
106 | 1.26k | isc_region_consume(&sr, 1); |
107 | 1.26k | snprintf(buf, sizeof(buf), "%lu", num); |
108 | 1.26k | RETERR(str_totext(buf, target)); |
109 | | |
110 | 1.26k | RETERR(str_totext(" ", target)); |
111 | | |
112 | | /* |
113 | | * Digest type. |
114 | | */ |
115 | 1.26k | num = uint8_fromregion(&sr); |
116 | 1.26k | isc_region_consume(&sr, 1); |
117 | 1.26k | snprintf(buf, sizeof(buf), "%lu", num); |
118 | 1.26k | RETERR(str_totext(buf, target)); |
119 | | |
120 | | /* |
121 | | * Digest. |
122 | | */ |
123 | 1.26k | if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { |
124 | 19 | RETERR(str_totext(" (", target)); |
125 | 19 | } |
126 | 1.26k | RETERR(str_totext(tctx->linebreak, target)); |
127 | 1.26k | if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { |
128 | 1.26k | if (tctx->width == 0) { /* No splitting */ |
129 | 0 | RETERR(isc_hex_totext(&sr, 0, "", target)); |
130 | 1.26k | } else { |
131 | 1.26k | RETERR(isc_hex_totext(&sr, tctx->width - 2, |
132 | 1.26k | tctx->linebreak, target)); |
133 | 1.26k | } |
134 | 1.26k | } else { |
135 | 0 | RETERR(str_totext("[omitted]", target)); |
136 | 0 | } |
137 | 1.26k | if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { |
138 | 19 | RETERR(str_totext(" )", target)); |
139 | 19 | } |
140 | 1.26k | return (ISC_R_SUCCESS); |
141 | 1.26k | } |
142 | | |
143 | | static isc_result_t |
144 | 1.43k | fromwire_zonemd(ARGS_FROMWIRE) { |
145 | 1.43k | isc_region_t sr; |
146 | 1.43k | size_t digestlen = 0; |
147 | | |
148 | 1.43k | UNUSED(type); |
149 | 1.43k | UNUSED(rdclass); |
150 | 1.43k | UNUSED(dctx); |
151 | | |
152 | 1.43k | isc_buffer_activeregion(source, &sr); |
153 | | |
154 | | /* |
155 | | * If we do not recognize the digest type, ensure that the digest |
156 | | * meets minimum length (12). |
157 | | * |
158 | | * If we do recognize the digest type, ensure that the digest is of the |
159 | | * correct length. |
160 | | */ |
161 | 1.43k | if (sr.length < 18) { |
162 | 28 | return (ISC_R_UNEXPECTEDEND); |
163 | 28 | } |
164 | | |
165 | 1.40k | switch (sr.base[5]) { |
166 | 93 | case DNS_ZONEMD_DIGEST_SHA384: |
167 | 93 | digestlen = ISC_SHA384_DIGESTLENGTH; |
168 | 93 | break; |
169 | 28 | case DNS_ZONEMD_DIGEST_SHA512: |
170 | 28 | digestlen = ISC_SHA512_DIGESTLENGTH; |
171 | 28 | break; |
172 | 1.28k | default: |
173 | 1.28k | break; |
174 | 1.40k | } |
175 | | |
176 | 1.40k | if (digestlen != 0 && sr.length < 6 + digestlen) { |
177 | 10 | return (ISC_R_UNEXPECTEDEND); |
178 | 10 | } |
179 | | |
180 | | /* |
181 | | * Only specify the number of octets to consume if we recognize the |
182 | | * digest type. |
183 | | * |
184 | | * If there is extra data, dns_rdata_fromwire() will detect that. |
185 | | */ |
186 | 1.39k | if (digestlen != 0) { |
187 | 111 | sr.length = 6 + digestlen; |
188 | 111 | } |
189 | | |
190 | 1.39k | isc_buffer_forward(source, sr.length); |
191 | 1.39k | return (mem_tobuffer(target, sr.base, sr.length)); |
192 | 1.40k | } |
193 | | |
194 | | static isc_result_t |
195 | 650 | towire_zonemd(ARGS_TOWIRE) { |
196 | 650 | isc_region_t sr; |
197 | | |
198 | 650 | REQUIRE(rdata->type == dns_rdatatype_zonemd); |
199 | 650 | REQUIRE(rdata->length != 0); |
200 | | |
201 | 650 | UNUSED(cctx); |
202 | | |
203 | 650 | dns_rdata_toregion(rdata, &sr); |
204 | 650 | return (mem_tobuffer(target, sr.base, sr.length)); |
205 | 650 | } |
206 | | |
207 | | static int |
208 | 1.37k | compare_zonemd(ARGS_COMPARE) { |
209 | 1.37k | isc_region_t r1; |
210 | 1.37k | isc_region_t r2; |
211 | | |
212 | 1.37k | REQUIRE(rdata1->type == rdata2->type); |
213 | 1.37k | REQUIRE(rdata1->rdclass == rdata2->rdclass); |
214 | 1.37k | REQUIRE(rdata1->type == dns_rdatatype_zonemd); |
215 | 1.37k | REQUIRE(rdata1->length != 0); |
216 | 1.37k | REQUIRE(rdata2->length != 0); |
217 | | |
218 | 1.37k | dns_rdata_toregion(rdata1, &r1); |
219 | 1.37k | dns_rdata_toregion(rdata2, &r2); |
220 | 1.37k | return (isc_region_compare(&r1, &r2)); |
221 | 1.37k | } |
222 | | |
223 | | static isc_result_t |
224 | 0 | fromstruct_zonemd(ARGS_FROMSTRUCT) { |
225 | 0 | dns_rdata_zonemd_t *zonemd = source; |
226 | |
|
227 | 0 | REQUIRE(zonemd != NULL); |
228 | 0 | REQUIRE(zonemd->common.rdtype == type); |
229 | 0 | REQUIRE(zonemd->common.rdclass == rdclass); |
230 | |
|
231 | 0 | UNUSED(type); |
232 | 0 | UNUSED(rdclass); |
233 | |
|
234 | 0 | switch (zonemd->digest_type) { |
235 | 0 | case DNS_ZONEMD_DIGEST_SHA384: |
236 | 0 | REQUIRE(zonemd->length == ISC_SHA384_DIGESTLENGTH); |
237 | 0 | break; |
238 | 0 | case DNS_ZONEMD_DIGEST_SHA512: |
239 | 0 | REQUIRE(zonemd->length == ISC_SHA512_DIGESTLENGTH); |
240 | 0 | break; |
241 | 0 | } |
242 | | |
243 | 0 | RETERR(uint32_tobuffer(zonemd->serial, target)); |
244 | 0 | RETERR(uint8_tobuffer(zonemd->scheme, target)); |
245 | 0 | RETERR(uint8_tobuffer(zonemd->digest_type, target)); |
246 | | |
247 | 0 | return (mem_tobuffer(target, zonemd->digest, zonemd->length)); |
248 | 0 | } |
249 | | |
250 | | static isc_result_t |
251 | 0 | tostruct_zonemd(ARGS_TOSTRUCT) { |
252 | 0 | dns_rdata_zonemd_t *zonemd = target; |
253 | 0 | isc_region_t region; |
254 | |
|
255 | 0 | REQUIRE(rdata->type == dns_rdatatype_zonemd); |
256 | 0 | REQUIRE(zonemd != NULL); |
257 | 0 | REQUIRE(rdata->length != 0); |
258 | |
|
259 | 0 | zonemd->common.rdclass = rdata->rdclass; |
260 | 0 | zonemd->common.rdtype = rdata->type; |
261 | 0 | ISC_LINK_INIT(&zonemd->common, link); |
262 | |
|
263 | 0 | dns_rdata_toregion(rdata, ®ion); |
264 | |
|
265 | 0 | zonemd->serial = uint32_fromregion(®ion); |
266 | 0 | isc_region_consume(®ion, 4); |
267 | 0 | zonemd->scheme = uint8_fromregion(®ion); |
268 | 0 | isc_region_consume(®ion, 1); |
269 | 0 | zonemd->digest_type = uint8_fromregion(®ion); |
270 | 0 | isc_region_consume(®ion, 1); |
271 | 0 | zonemd->length = region.length; |
272 | |
|
273 | 0 | zonemd->digest = mem_maybedup(mctx, region.base, region.length); |
274 | 0 | zonemd->mctx = mctx; |
275 | 0 | return (ISC_R_SUCCESS); |
276 | 0 | } |
277 | | |
278 | | static void |
279 | 0 | freestruct_zonemd(ARGS_FREESTRUCT) { |
280 | 0 | dns_rdata_zonemd_t *zonemd = source; |
281 | |
|
282 | 0 | REQUIRE(zonemd != NULL); |
283 | 0 | REQUIRE(zonemd->common.rdtype == dns_rdatatype_zonemd); |
284 | |
|
285 | 0 | if (zonemd->mctx == NULL) { |
286 | 0 | return; |
287 | 0 | } |
288 | | |
289 | 0 | if (zonemd->digest != NULL) { |
290 | 0 | isc_mem_free(zonemd->mctx, zonemd->digest); |
291 | 0 | } |
292 | 0 | zonemd->mctx = NULL; |
293 | 0 | } |
294 | | |
295 | | static isc_result_t |
296 | 0 | additionaldata_zonemd(ARGS_ADDLDATA) { |
297 | 0 | REQUIRE(rdata->type == dns_rdatatype_zonemd); |
298 | |
|
299 | 0 | UNUSED(rdata); |
300 | 0 | UNUSED(owner); |
301 | 0 | UNUSED(add); |
302 | 0 | UNUSED(arg); |
303 | |
|
304 | 0 | return (ISC_R_SUCCESS); |
305 | 0 | } |
306 | | |
307 | | static isc_result_t |
308 | 0 | digest_zonemd(ARGS_DIGEST) { |
309 | 0 | isc_region_t r; |
310 | |
|
311 | 0 | REQUIRE(rdata->type == dns_rdatatype_zonemd); |
312 | |
|
313 | 0 | dns_rdata_toregion(rdata, &r); |
314 | |
|
315 | 0 | return ((digest)(arg, &r)); |
316 | 0 | } |
317 | | |
318 | | static bool |
319 | 0 | checkowner_zonemd(ARGS_CHECKOWNER) { |
320 | 0 | REQUIRE(type == dns_rdatatype_zonemd); |
321 | |
|
322 | 0 | UNUSED(name); |
323 | 0 | UNUSED(type); |
324 | 0 | UNUSED(rdclass); |
325 | 0 | UNUSED(wildcard); |
326 | |
|
327 | 0 | return (true); |
328 | 0 | } |
329 | | |
330 | | static bool |
331 | 0 | checknames_zonemd(ARGS_CHECKNAMES) { |
332 | 0 | REQUIRE(rdata->type == dns_rdatatype_zonemd); |
333 | |
|
334 | 0 | UNUSED(rdata); |
335 | 0 | UNUSED(owner); |
336 | 0 | UNUSED(bad); |
337 | |
|
338 | 0 | return (true); |
339 | 0 | } |
340 | | |
341 | | static int |
342 | 0 | casecompare_zonemd(ARGS_COMPARE) { |
343 | 0 | return (compare_zonemd(rdata1, rdata2)); |
344 | 0 | } |
345 | | |
346 | | #endif /* RDATA_GENERIC_ZONEMD_63_C */ |