Coverage Report

Created: 2026-09-01 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/rdata/generic/key_25.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
/* RFC2535 */
15
16
#ifndef RDATA_GENERIC_KEY_25_C
17
#define RDATA_GENERIC_KEY_25_C
18
19
#include <dst/dst.h>
20
21
13.3k
#define RRTYPE_KEY_ATTRIBUTES (0)
22
23
static isc_result_t
24
3.60k
generic_fromtext_key(ARGS_FROMTEXT) {
25
3.60k
  isc_token_t token;
26
3.60k
  dns_secalg_t alg;
27
3.60k
  dns_secproto_t proto;
28
3.60k
  dns_keyflags_t flags;
29
3.60k
  unsigned int used;
30
31
3.60k
  UNUSED(rdclass);
32
3.60k
  UNUSED(origin);
33
3.60k
  UNUSED(options);
34
3.60k
  UNUSED(callbacks);
35
36
  /* flags */
37
3.60k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
38
3.60k
              false));
39
3.58k
  RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
40
3.45k
  if (type == dns_rdatatype_rkey && flags != 0U) {
41
14
    RETTOK(DNS_R_FORMERR);
42
14
  }
43
3.44k
  RETERR(uint16_tobuffer(flags, target));
44
45
  /* protocol */
46
3.44k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
47
3.44k
              false));
48
3.40k
  RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
49
3.25k
  RETERR(mem_tobuffer(target, &proto, 1));
50
51
  /* algorithm */
52
3.25k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
53
3.25k
              false));
54
3.24k
  RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
55
3.23k
  RETERR(mem_tobuffer(target, &alg, 1));
56
57
  /*
58
   * Save the current used value. It will become the current
59
   * value when we parse the keydata field.
60
   */
61
3.23k
  used = isc_buffer_usedlength(target);
62
63
3.23k
  RETERR(isc_base64_tobuffer(lexer, target, isc_one_or_more));
64
65
3.21k
  if (alg == DNS_KEYALG_PRIVATEDNS || alg == DNS_KEYALG_PRIVATEOID) {
66
222
    isc_buffer_t b;
67
68
    /*
69
     * Set up 'b' so that the key data can be parsed.
70
     */
71
222
    b = *target;
72
222
    b.active = b.used;
73
222
    b.current = used;
74
75
222
    RETERR(check_private(&b, alg));
76
179
  }
77
78
3.16k
  return ISC_R_SUCCESS;
79
3.21k
}
80
81
static isc_result_t
82
5.65k
generic_totext_key(ARGS_TOTEXT) {
83
5.65k
  isc_region_t sr;
84
5.65k
  char buf[sizeof("[key id = 64000]")];
85
5.65k
  unsigned int flags;
86
5.65k
  unsigned char algorithm;
87
5.65k
  char algbuf[DNS_NAME_FORMATSIZE];
88
5.65k
  const char *keyinfo;
89
5.65k
  isc_region_t tmpr;
90
91
5.65k
  REQUIRE(rdata->length != 0);
92
93
5.65k
  dns_rdata_toregion(rdata, &sr);
94
95
  /* flags */
96
5.65k
  flags = uint16_fromregion(&sr);
97
5.65k
  isc_region_consume(&sr, 2);
98
5.65k
  snprintf(buf, sizeof(buf), "%u", flags);
99
5.65k
  RETERR(str_totext(buf, target));
100
5.65k
  RETERR(str_totext(" ", target));
101
5.65k
  if ((flags & DNS_KEYFLAG_KSK) != 0) {
102
2.04k
    if (flags & DNS_KEYFLAG_REVOKE) {
103
731
      keyinfo = "revoked KSK";
104
1.30k
    } else {
105
1.30k
      keyinfo = "KSK";
106
1.30k
    }
107
3.61k
  } else {
108
3.61k
    keyinfo = "ZSK";
109
3.61k
  }
110
111
  /* protocol */
112
5.65k
  snprintf(buf, sizeof(buf), "%u", sr.base[0]);
113
5.65k
  isc_region_consume(&sr, 1);
114
5.65k
  RETERR(str_totext(buf, target));
115
5.65k
  RETERR(str_totext(" ", target));
116
117
  /* algorithm */
118
5.65k
  algorithm = sr.base[0];
119
5.65k
  snprintf(buf, sizeof(buf), "%u", algorithm);
120
5.65k
  isc_region_consume(&sr, 1);
121
5.65k
  RETERR(str_totext(buf, target));
122
123
5.65k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
124
144
      algorithm == DNS_KEYALG_PRIVATEDNS)
125
53
  {
126
53
    dns_name_t name;
127
53
    dns_name_init(&name);
128
53
    dns_name_fromregion(&name, &sr);
129
53
    dns_name_format(&name, algbuf, sizeof(algbuf));
130
5.59k
  } else if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
131
91
       algorithm == DNS_KEYALG_PRIVATEOID)
132
34
  {
133
34
    const unsigned char *in = sr.base + 1;
134
34
    ASN1_OBJECT *obj = d2i_ASN1_OBJECT(NULL, &in, *sr.base);
135
34
    INSIST(obj != NULL);
136
34
    int n = i2t_ASN1_OBJECT(algbuf, sizeof(algbuf), obj);
137
34
    ASN1_OBJECT_free(obj);
138
34
    if (n == -1 || (size_t)n >= sizeof(algbuf)) {
139
0
      dns_secalg_format((dns_secalg_t)algorithm, algbuf,
140
0
            sizeof(algbuf));
141
0
    }
142
5.56k
  } else {
143
5.56k
    dns_secalg_format((dns_secalg_t)algorithm, algbuf,
144
5.56k
          sizeof(algbuf));
145
5.56k
  }
146
147
  /* key */
148
5.65k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
149
144
    RETERR(str_totext(" (", target));
150
144
  }
151
5.65k
  RETERR(str_totext(tctx->linebreak, target));
152
153
5.65k
  if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
154
5.65k
    if (tctx->width == 0) { /* No splitting */
155
0
      RETERR(isc_base64_totext(&sr, 60, "", target));
156
5.65k
    } else {
157
5.65k
      RETERR(isc_base64_totext(&sr, tctx->width - 2,
158
5.65k
             tctx->linebreak, target));
159
5.65k
    }
160
5.65k
  } else {
161
0
    dns_rdata_toregion(rdata, &tmpr);
162
0
    snprintf(buf, sizeof(buf), "[key id = %u]",
163
0
       dst_region_computeid(&tmpr));
164
0
    RETERR(str_totext(buf, target));
165
0
  }
166
167
5.65k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
168
144
    RETERR(str_totext(tctx->linebreak, target));
169
5.50k
  } else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
170
0
    RETERR(str_totext(" ", target));
171
0
  }
172
173
5.65k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
174
144
    RETERR(str_totext(")", target));
175
144
  }
176
177
5.65k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
178
144
    if (rdata->type == dns_rdatatype_dnskey ||
179
118
        rdata->type == dns_rdatatype_cdnskey)
180
67
    {
181
67
      RETERR(str_totext(" ; ", target));
182
67
      RETERR(str_totext(keyinfo, target));
183
67
    }
184
144
    RETERR(str_totext("; alg = ", target));
185
144
    RETERR(str_totext(algbuf, target));
186
144
    RETERR(str_totext(" ; key id = ", target));
187
144
    dns_rdata_toregion(rdata, &tmpr);
188
144
    snprintf(buf, sizeof(buf), "%u", dst_region_computeid(&tmpr));
189
144
    RETERR(str_totext(buf, target));
190
144
  }
191
5.65k
  return ISC_R_SUCCESS;
192
5.65k
}
193
194
static isc_result_t
195
7.91k
generic_fromwire_key(ARGS_FROMWIRE) {
196
7.91k
  unsigned char algorithm;
197
7.91k
  uint16_t flags;
198
7.91k
  isc_region_t sr;
199
200
7.91k
  UNUSED(rdclass);
201
7.91k
  UNUSED(dctx);
202
203
7.91k
  isc_buffer_activeregion(source, &sr);
204
7.91k
  if (sr.length < 4) {
205
46
    return ISC_R_UNEXPECTEDEND;
206
46
  }
207
7.86k
  flags = (sr.base[0] << 8) | sr.base[1];
208
209
7.86k
  if (type == dns_rdatatype_rkey && flags != 0U) {
210
18
    return DNS_R_FORMERR;
211
18
  }
212
213
7.84k
  algorithm = sr.base[3];
214
7.84k
  RETERR(mem_tobuffer(target, sr.base, 4));
215
7.77k
  isc_region_consume(&sr, 4);
216
7.77k
  isc_buffer_forward(source, 4);
217
218
7.77k
  if (sr.length == 0) {
219
15
    return ISC_R_UNEXPECTEDEND;
220
15
  }
221
222
7.75k
  if (algorithm == DNS_KEYALG_PRIVATEDNS ||
223
7.45k
      algorithm == DNS_KEYALG_PRIVATEOID)
224
453
  {
225
453
    isc_buffer_t b = *source;
226
453
    RETERR(check_private(&b, algorithm));
227
413
  }
228
229
7.71k
  isc_buffer_activeregion(source, &sr);
230
7.71k
  isc_buffer_forward(source, sr.length);
231
7.71k
  return mem_tobuffer(target, sr.base, sr.length);
232
7.75k
}
233
234
static isc_result_t
235
1.69k
fromtext_key(ARGS_FROMTEXT) {
236
1.69k
  REQUIRE(type == dns_rdatatype_key);
237
238
1.69k
  return generic_fromtext_key(CALL_FROMTEXT);
239
1.69k
}
240
241
static isc_result_t
242
1.87k
totext_key(ARGS_TOTEXT) {
243
1.87k
  REQUIRE(rdata != NULL);
244
1.87k
  REQUIRE(rdata->type == dns_rdatatype_key);
245
246
1.87k
  return generic_totext_key(CALL_TOTEXT);
247
1.87k
}
248
249
static isc_result_t
250
2.14k
fromwire_key(ARGS_FROMWIRE) {
251
2.14k
  REQUIRE(type == dns_rdatatype_key);
252
253
2.14k
  return generic_fromwire_key(CALL_FROMWIRE);
254
2.14k
}
255
256
static isc_result_t
257
944
towire_key(ARGS_TOWIRE) {
258
944
  isc_region_t sr;
259
260
944
  REQUIRE(rdata != NULL);
261
944
  REQUIRE(rdata->type == dns_rdatatype_key);
262
944
  REQUIRE(rdata->length != 0);
263
264
944
  UNUSED(cctx);
265
266
944
  dns_rdata_toregion(rdata, &sr);
267
944
  return mem_tobuffer(target, sr.base, sr.length);
268
944
}
269
270
static int
271
180k
compare_key(ARGS_COMPARE) {
272
180k
  isc_region_t r1;
273
180k
  isc_region_t r2;
274
275
180k
  REQUIRE(rdata1 != NULL);
276
180k
  REQUIRE(rdata2 != NULL);
277
180k
  REQUIRE(rdata1->type == rdata2->type);
278
180k
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
279
180k
  REQUIRE(rdata1->type == dns_rdatatype_key);
280
180k
  REQUIRE(rdata1->length != 0);
281
180k
  REQUIRE(rdata2->length != 0);
282
283
180k
  dns_rdata_toregion(rdata1, &r1);
284
180k
  dns_rdata_toregion(rdata2, &r2);
285
180k
  return isc_region_compare(&r1, &r2);
286
180k
}
287
288
static isc_result_t
289
0
generic_fromstruct_key(ARGS_FROMSTRUCT) {
290
0
  dns_rdata_key_t *key = source;
291
292
0
  REQUIRE(key != NULL);
293
0
  REQUIRE(key->common.rdtype == type);
294
0
  REQUIRE(key->common.rdclass == rdclass);
295
296
0
  UNUSED(type);
297
0
  UNUSED(rdclass);
298
299
0
  if (type == dns_rdatatype_rkey) {
300
0
    INSIST(key->flags == 0U);
301
0
  }
302
303
  /* Flags */
304
0
  RETERR(uint16_tobuffer(key->flags, target));
305
306
  /* Protocol */
307
0
  RETERR(uint8_tobuffer(key->protocol, target));
308
309
  /* Algorithm */
310
0
  RETERR(uint8_tobuffer(key->algorithm, target));
311
312
  /* Data */
313
0
  return mem_tobuffer(target, key->data, key->datalen);
314
0
}
315
316
static isc_result_t
317
229
generic_tostruct_key(ARGS_TOSTRUCT) {
318
229
  dns_rdata_key_t *key = target;
319
229
  isc_region_t sr;
320
321
229
  REQUIRE(key != NULL);
322
229
  REQUIRE(rdata->length >= 4U);
323
324
229
  REQUIRE(key != NULL);
325
229
  REQUIRE(key->common.rdclass == rdata->rdclass);
326
229
  REQUIRE(key->common.rdtype == rdata->type);
327
328
229
  dns_rdata_toregion(rdata, &sr);
329
330
  /* Flags */
331
229
  key->flags = uint16_fromregion(&sr);
332
229
  isc_region_consume(&sr, 2);
333
334
  /* Protocol */
335
229
  key->protocol = uint8_fromregion(&sr);
336
229
  isc_region_consume(&sr, 1);
337
338
  /* Algorithm */
339
229
  key->algorithm = uint8_fromregion(&sr);
340
229
  isc_region_consume(&sr, 1);
341
342
  /* Data */
343
229
  key->datalen = sr.length;
344
229
  key->data = mem_maybedup(mctx, sr.base, key->datalen);
345
229
  key->mctx = mctx;
346
229
  return ISC_R_SUCCESS;
347
229
}
348
349
static void
350
0
generic_freestruct_key(ARGS_FREESTRUCT) {
351
0
  dns_rdata_key_t *key = (dns_rdata_key_t *)source;
352
353
0
  REQUIRE(key != NULL);
354
355
0
  if (key->mctx == NULL) {
356
0
    return;
357
0
  }
358
359
0
  if (key->data != NULL) {
360
0
    isc_mem_free(key->mctx, key->data);
361
0
  }
362
0
  key->mctx = NULL;
363
0
}
364
365
static isc_result_t
366
0
fromstruct_key(ARGS_FROMSTRUCT) {
367
0
  REQUIRE(type == dns_rdatatype_key);
368
369
0
  return generic_fromstruct_key(CALL_FROMSTRUCT);
370
0
}
371
372
static isc_result_t
373
126
tostruct_key(ARGS_TOSTRUCT) {
374
126
  dns_rdata_key_t *key = target;
375
376
126
  REQUIRE(key != NULL);
377
126
  REQUIRE(rdata != NULL);
378
126
  REQUIRE(rdata->type == dns_rdatatype_key);
379
380
126
  DNS_RDATACOMMON_INIT(key, rdata->type, rdata->rdclass);
381
382
126
  return generic_tostruct_key(CALL_TOSTRUCT);
383
126
}
384
385
static void
386
0
freestruct_key(ARGS_FREESTRUCT) {
387
0
  dns_rdata_key_t *key = (dns_rdata_key_t *)source;
388
389
0
  REQUIRE(key != NULL);
390
0
  REQUIRE(key->common.rdtype == dns_rdatatype_key);
391
392
0
  generic_freestruct_key(source);
393
0
}
394
395
static isc_result_t
396
0
additionaldata_key(ARGS_ADDLDATA) {
397
0
  REQUIRE(rdata != NULL);
398
0
  REQUIRE(rdata->type == dns_rdatatype_key);
399
400
0
  UNUSED(rdata);
401
0
  UNUSED(owner);
402
0
  UNUSED(add);
403
0
  UNUSED(arg);
404
405
0
  return ISC_R_SUCCESS;
406
0
}
407
408
static isc_result_t
409
0
digest_key(ARGS_DIGEST) {
410
0
  isc_region_t r;
411
412
0
  REQUIRE(rdata != NULL);
413
0
  REQUIRE(rdata->type == dns_rdatatype_key);
414
415
0
  dns_rdata_toregion(rdata, &r);
416
417
0
  return (digest)(arg, &r);
418
0
}
419
420
static bool
421
0
checkowner_key(ARGS_CHECKOWNER) {
422
0
  REQUIRE(type == dns_rdatatype_key);
423
424
0
  UNUSED(name);
425
0
  UNUSED(type);
426
0
  UNUSED(rdclass);
427
0
  UNUSED(wildcard);
428
429
0
  return true;
430
0
}
431
432
static bool
433
0
checknames_key(ARGS_CHECKNAMES) {
434
0
  REQUIRE(rdata != NULL);
435
0
  REQUIRE(rdata->type == dns_rdatatype_key);
436
437
0
  UNUSED(rdata);
438
0
  UNUSED(owner);
439
0
  UNUSED(bad);
440
441
0
  return true;
442
0
}
443
444
static int
445
0
casecompare_key(ARGS_COMPARE) {
446
0
  return compare_key(rdata1, rdata2);
447
0
}
448
449
#endif /* RDATA_GENERIC_KEY_25_C */