Coverage Report

Created: 2026-07-16 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/rdata/generic/zonemd_63.c
Line
Count
Source
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.6k
#define RRTYPE_ZONEMD_ATTRIBUTES 0
20
21
static isc_result_t
22
480
fromtext_zonemd(ARGS_FROMTEXT) {
23
480
  isc_token_t token;
24
480
  int digest_type, length;
25
480
  isc_buffer_t save;
26
480
  isc_result_t result;
27
28
480
  UNUSED(type);
29
480
  UNUSED(rdclass);
30
480
  UNUSED(origin);
31
480
  UNUSED(options);
32
480
  UNUSED(callbacks);
33
34
  /*
35
   * Zone Serial.
36
   */
37
480
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
38
480
              false));
39
476
  RETERR(uint32_tobuffer(token.value.as_ulong, target));
40
41
  /*
42
   * Digest Scheme.
43
   */
44
476
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
45
476
              false));
46
474
  RETERR(uint8_tobuffer(token.value.as_ulong, target));
47
48
  /*
49
   * Digest Type.
50
   */
51
445
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
52
445
              false));
53
442
  digest_type = token.value.as_ulong;
54
442
  RETERR(uint8_tobuffer(digest_type, target));
55
56
  /*
57
   * Digest.
58
   */
59
375
  switch (digest_type) {
60
2
  case DNS_ZONEMD_DIGEST_SHA384:
61
2
    length = ISC_SHA384_DIGESTLENGTH;
62
2
    break;
63
1
  case DNS_ZONEMD_DIGEST_SHA512:
64
1
    length = ISC_SHA512_DIGESTLENGTH;
65
1
    break;
66
372
  default:
67
372
    length = -2;
68
372
    break;
69
375
  }
70
71
375
  save = *target;
72
375
  result = isc_hex_tobuffer(lexer, target, length);
73
  /* Minimum length of digest is 12 octets. */
74
375
  if (isc_buffer_usedlength(target) - isc_buffer_usedlength(&save) < 12) {
75
15
    return ISC_R_UNEXPECTEDEND;
76
15
  }
77
360
  return result;
78
375
}
79
80
static isc_result_t
81
1.28k
totext_zonemd(ARGS_TOTEXT) {
82
1.28k
  isc_region_t sr;
83
1.28k
  char buf[sizeof("0123456789")];
84
1.28k
  unsigned long num;
85
86
1.28k
  REQUIRE(rdata->length > 6);
87
88
1.28k
  UNUSED(tctx);
89
90
1.28k
  dns_rdata_toregion(rdata, &sr);
91
92
  /*
93
   * Zone Serial.
94
   */
95
1.28k
  num = uint32_fromregion(&sr);
96
1.28k
  isc_region_consume(&sr, 4);
97
1.28k
  snprintf(buf, sizeof(buf), "%lu", num);
98
1.28k
  RETERR(str_totext(buf, target));
99
100
1.28k
  RETERR(str_totext(" ", target));
101
102
  /*
103
   * Digest scheme.
104
   */
105
1.28k
  num = uint8_fromregion(&sr);
106
1.28k
  isc_region_consume(&sr, 1);
107
1.28k
  snprintf(buf, sizeof(buf), "%lu", num);
108
1.28k
  RETERR(str_totext(buf, target));
109
110
1.28k
  RETERR(str_totext(" ", target));
111
112
  /*
113
   * Digest type.
114
   */
115
1.28k
  num = uint8_fromregion(&sr);
116
1.28k
  isc_region_consume(&sr, 1);
117
1.28k
  snprintf(buf, sizeof(buf), "%lu", num);
118
1.28k
  RETERR(str_totext(buf, target));
119
120
  /*
121
   * Digest.
122
   */
123
1.28k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
124
11
    RETERR(str_totext(" (", target));
125
11
  }
126
1.28k
  RETERR(str_totext(tctx->linebreak, target));
127
1.28k
  if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
128
1.28k
    if (tctx->width == 0) { /* No splitting */
129
0
      RETERR(isc_hex_totext(&sr, 0, "", target));
130
1.28k
    } else {
131
1.28k
      RETERR(isc_hex_totext(&sr, tctx->width - 2,
132
1.28k
                tctx->linebreak, target));
133
1.28k
    }
134
1.28k
  } else {
135
0
    RETERR(str_totext("[omitted]", target));
136
0
  }
137
1.28k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
138
11
    RETERR(str_totext(" )", target));
139
11
  }
140
1.28k
  return ISC_R_SUCCESS;
141
1.28k
}
142
143
static isc_result_t
144
2.21k
fromwire_zonemd(ARGS_FROMWIRE) {
145
2.21k
  isc_region_t sr;
146
2.21k
  size_t digestlen = 0;
147
148
2.21k
  UNUSED(type);
149
2.21k
  UNUSED(rdclass);
150
2.21k
  UNUSED(dctx);
151
152
2.21k
  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
2.21k
  if (sr.length < 18) {
162
23
    return ISC_R_UNEXPECTEDEND;
163
23
  }
164
165
2.18k
  switch (sr.base[5]) {
166
253
  case DNS_ZONEMD_DIGEST_SHA384:
167
253
    digestlen = ISC_SHA384_DIGESTLENGTH;
168
253
    break;
169
219
  case DNS_ZONEMD_DIGEST_SHA512:
170
219
    digestlen = ISC_SHA512_DIGESTLENGTH;
171
219
    break;
172
1.71k
  default:
173
1.71k
    break;
174
2.18k
  }
175
176
2.18k
  if (digestlen != 0 && sr.length < 6 + digestlen) {
177
19
    return ISC_R_UNEXPECTEDEND;
178
19
  }
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
2.16k
  if (digestlen != 0) {
187
453
    sr.length = 6 + digestlen;
188
453
  }
189
190
2.16k
  isc_buffer_forward(source, sr.length);
191
2.16k
  return mem_tobuffer(target, sr.base, sr.length);
192
2.18k
}
193
194
static isc_result_t
195
647
towire_zonemd(ARGS_TOWIRE) {
196
647
  isc_region_t sr;
197
198
647
  REQUIRE(rdata->type == dns_rdatatype_zonemd);
199
647
  REQUIRE(rdata->length != 0);
200
201
647
  UNUSED(cctx);
202
203
647
  dns_rdata_toregion(rdata, &sr);
204
647
  return mem_tobuffer(target, sr.base, sr.length);
205
647
}
206
207
static int
208
4.35k
compare_zonemd(ARGS_COMPARE) {
209
4.35k
  isc_region_t r1;
210
4.35k
  isc_region_t r2;
211
212
4.35k
  REQUIRE(rdata1->type == rdata2->type);
213
4.35k
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
214
4.35k
  REQUIRE(rdata1->type == dns_rdatatype_zonemd);
215
4.35k
  REQUIRE(rdata1->length != 0);
216
4.35k
  REQUIRE(rdata2->length != 0);
217
218
4.35k
  dns_rdata_toregion(rdata1, &r1);
219
4.35k
  dns_rdata_toregion(rdata2, &r2);
220
4.35k
  return isc_region_compare(&r1, &r2);
221
4.35k
}
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
  DNS_RDATACOMMON_INIT(zonemd, rdata->type, rdata->rdclass);
260
261
0
  dns_rdata_toregion(rdata, &region);
262
263
0
  zonemd->serial = uint32_fromregion(&region);
264
0
  isc_region_consume(&region, 4);
265
0
  zonemd->scheme = uint8_fromregion(&region);
266
0
  isc_region_consume(&region, 1);
267
0
  zonemd->digest_type = uint8_fromregion(&region);
268
0
  isc_region_consume(&region, 1);
269
0
  zonemd->length = region.length;
270
271
0
  zonemd->digest = mem_maybedup(mctx, region.base, region.length);
272
0
  zonemd->mctx = mctx;
273
0
  return ISC_R_SUCCESS;
274
0
}
275
276
static void
277
0
freestruct_zonemd(ARGS_FREESTRUCT) {
278
0
  dns_rdata_zonemd_t *zonemd = source;
279
280
0
  REQUIRE(zonemd != NULL);
281
0
  REQUIRE(zonemd->common.rdtype == dns_rdatatype_zonemd);
282
283
0
  if (zonemd->mctx == NULL) {
284
0
    return;
285
0
  }
286
287
0
  if (zonemd->digest != NULL) {
288
0
    isc_mem_free(zonemd->mctx, zonemd->digest);
289
0
  }
290
0
  zonemd->mctx = NULL;
291
0
}
292
293
static isc_result_t
294
0
additionaldata_zonemd(ARGS_ADDLDATA) {
295
0
  REQUIRE(rdata->type == dns_rdatatype_zonemd);
296
297
0
  UNUSED(rdata);
298
0
  UNUSED(owner);
299
0
  UNUSED(add);
300
0
  UNUSED(arg);
301
302
0
  return ISC_R_SUCCESS;
303
0
}
304
305
static isc_result_t
306
0
digest_zonemd(ARGS_DIGEST) {
307
0
  isc_region_t r;
308
309
0
  REQUIRE(rdata->type == dns_rdatatype_zonemd);
310
311
0
  dns_rdata_toregion(rdata, &r);
312
313
0
  return (digest)(arg, &r);
314
0
}
315
316
static bool
317
0
checkowner_zonemd(ARGS_CHECKOWNER) {
318
0
  REQUIRE(type == dns_rdatatype_zonemd);
319
320
0
  UNUSED(name);
321
0
  UNUSED(type);
322
0
  UNUSED(rdclass);
323
0
  UNUSED(wildcard);
324
325
0
  return true;
326
0
}
327
328
static bool
329
0
checknames_zonemd(ARGS_CHECKNAMES) {
330
0
  REQUIRE(rdata->type == dns_rdatatype_zonemd);
331
332
0
  UNUSED(rdata);
333
0
  UNUSED(owner);
334
0
  UNUSED(bad);
335
336
0
  return true;
337
0
}
338
339
static int
340
0
casecompare_zonemd(ARGS_COMPARE) {
341
0
  return compare_zonemd(rdata1, rdata2);
342
0
}
343
344
#endif /* RDATA_GENERIC_ZONEMD_63_C */