Coverage Report

Created: 2025-08-26 06:59

/src/bind9/lib/dns/rdata/generic/key_25.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
/* RFC2535 */
15
16
#ifndef RDATA_GENERIC_KEY_25_C
17
#define RDATA_GENERIC_KEY_25_C
18
19
#include <dst/dst.h>
20
21
#define RRTYPE_KEY_ATTRIBUTES \
22
14.4k
  (DNS_RDATATYPEATTR_ATCNAME | DNS_RDATATYPEATTR_ZONECUTAUTH)
23
24
/*
25
 * RFC 2535 section 3.1.2 says that if bits 0-1 of the Flags field are
26
 * both set, it means there is no key information and the RR stops after
27
 * the algorithm octet.  However, this only applies to KEY records, as
28
 * indicated by the specifications of the RR types based on KEY:
29
 *
30
 *     CDNSKEY - RFC 7344
31
 *     DNSKEY - RFC 4034
32
 *     RKEY - draft-reid-dnsext-rkey-00
33
 */
34
static bool
35
18.2k
generic_key_nokey(dns_rdatatype_t type, unsigned int flags) {
36
18.2k
  switch (type) {
37
3.15k
  case dns_rdatatype_cdnskey:
38
9.57k
  case dns_rdatatype_dnskey:
39
11.7k
  case dns_rdatatype_rkey:
40
11.7k
    return false;
41
6.53k
  case dns_rdatatype_key:
42
6.53k
  default:
43
6.53k
    return (flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY;
44
18.2k
  }
45
18.2k
}
46
47
static isc_result_t
48
3.91k
generic_fromtext_key(ARGS_FROMTEXT) {
49
3.91k
  isc_token_t token;
50
3.91k
  dns_secalg_t alg;
51
3.91k
  dns_secproto_t proto;
52
3.91k
  dns_keyflags_t flags;
53
3.91k
  unsigned int used;
54
55
3.91k
  UNUSED(rdclass);
56
3.91k
  UNUSED(origin);
57
3.91k
  UNUSED(options);
58
3.91k
  UNUSED(callbacks);
59
60
  /* flags */
61
3.91k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
62
3.91k
              false));
63
3.89k
  RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
64
3.70k
  if (type == dns_rdatatype_rkey && flags != 0U) {
65
33
    RETTOK(DNS_R_FORMERR);
66
33
  }
67
3.67k
  RETERR(uint16_tobuffer(flags, target));
68
69
  /* protocol */
70
3.67k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
71
3.67k
              false));
72
3.62k
  RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
73
3.51k
  RETERR(mem_tobuffer(target, &proto, 1));
74
75
  /* algorithm */
76
3.51k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
77
3.51k
              false));
78
3.49k
  RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
79
3.47k
  RETERR(mem_tobuffer(target, &alg, 1));
80
81
  /* No Key? */
82
3.47k
  if (generic_key_nokey(type, flags)) {
83
383
    return ISC_R_SUCCESS;
84
383
  }
85
86
  /*
87
   * Save the current used value. It will become the current
88
   * value when we parse the keydata field.
89
   */
90
3.09k
  used = isc_buffer_usedlength(target);
91
92
3.09k
  RETERR(isc_base64_tobuffer(lexer, target, -2));
93
94
3.01k
  if (alg == DNS_KEYALG_PRIVATEDNS || alg == DNS_KEYALG_PRIVATEOID) {
95
167
    isc_buffer_t b;
96
97
    /*
98
     * Set up 'b' so that the key data can be parsed.
99
     */
100
167
    b = *target;
101
167
    b.active = b.used;
102
167
    b.current = used;
103
104
167
    RETERR(check_private(&b, alg));
105
167
  }
106
107
2.98k
  return ISC_R_SUCCESS;
108
3.01k
}
109
110
static isc_result_t
111
6.66k
generic_totext_key(ARGS_TOTEXT) {
112
6.66k
  isc_region_t sr;
113
6.66k
  char buf[sizeof("[key id = 64000]")];
114
6.66k
  unsigned int flags;
115
6.66k
  unsigned char algorithm;
116
6.66k
  char algbuf[DNS_NAME_FORMATSIZE];
117
6.66k
  const char *keyinfo;
118
6.66k
  isc_region_t tmpr;
119
120
6.66k
  REQUIRE(rdata->length != 0);
121
122
6.66k
  dns_rdata_toregion(rdata, &sr);
123
124
  /* flags */
125
6.66k
  flags = uint16_fromregion(&sr);
126
6.66k
  isc_region_consume(&sr, 2);
127
6.66k
  snprintf(buf, sizeof(buf), "%u", flags);
128
6.66k
  RETERR(str_totext(buf, target));
129
6.66k
  RETERR(str_totext(" ", target));
130
6.66k
  if ((flags & DNS_KEYFLAG_KSK) != 0) {
131
2.49k
    if (flags & DNS_KEYFLAG_REVOKE) {
132
681
      keyinfo = "revoked KSK";
133
1.81k
    } else {
134
1.81k
      keyinfo = "KSK";
135
1.81k
    }
136
4.17k
  } else {
137
4.17k
    keyinfo = "ZSK";
138
4.17k
  }
139
140
  /* protocol */
141
6.66k
  snprintf(buf, sizeof(buf), "%u", sr.base[0]);
142
6.66k
  isc_region_consume(&sr, 1);
143
6.66k
  RETERR(str_totext(buf, target));
144
6.66k
  RETERR(str_totext(" ", target));
145
146
  /* algorithm */
147
6.66k
  algorithm = sr.base[0];
148
6.66k
  snprintf(buf, sizeof(buf), "%u", algorithm);
149
6.66k
  isc_region_consume(&sr, 1);
150
6.66k
  RETERR(str_totext(buf, target));
151
152
  /* No Key? */
153
6.66k
  if (generic_key_nokey(rdata->type, flags)) {
154
1.02k
    return ISC_R_SUCCESS;
155
1.02k
  }
156
157
5.64k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
158
5.64k
      algorithm == DNS_KEYALG_PRIVATEDNS)
159
44
  {
160
44
    dns_name_t name;
161
44
    dns_name_init(&name);
162
44
    dns_name_fromregion(&name, &sr);
163
44
    dns_name_format(&name, algbuf, sizeof(algbuf));
164
5.59k
  } else if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
165
5.59k
       algorithm == DNS_KEYALG_PRIVATEOID)
166
24
  {
167
24
    const unsigned char *in = sr.base + 1;
168
24
    ASN1_OBJECT *obj = d2i_ASN1_OBJECT(NULL, &in, *sr.base);
169
24
    INSIST(obj != NULL);
170
24
    int n = i2t_ASN1_OBJECT(algbuf, sizeof(buf), obj);
171
24
    ASN1_OBJECT_free(obj);
172
24
    if (n == -1 || (size_t)n >= sizeof(algbuf)) {
173
0
      dns_secalg_format((dns_secalg_t)algorithm, algbuf,
174
0
            sizeof(algbuf));
175
0
    }
176
5.57k
  } else {
177
5.57k
    dns_secalg_format((dns_secalg_t)algorithm, algbuf,
178
5.57k
          sizeof(algbuf));
179
5.57k
  }
180
181
  /* key */
182
5.64k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
183
117
    RETERR(str_totext(" (", target));
184
117
  }
185
5.64k
  RETERR(str_totext(tctx->linebreak, target));
186
187
5.64k
  if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
188
5.64k
    if (tctx->width == 0) { /* No splitting */
189
0
      RETERR(isc_base64_totext(&sr, 60, "", target));
190
5.64k
    } else {
191
5.64k
      RETERR(isc_base64_totext(&sr, tctx->width - 2,
192
5.64k
             tctx->linebreak, target));
193
5.64k
    }
194
5.64k
  } else {
195
0
    dns_rdata_toregion(rdata, &tmpr);
196
0
    snprintf(buf, sizeof(buf), "[key id = %u]",
197
0
       dst_region_computeid(&tmpr));
198
0
    RETERR(str_totext(buf, target));
199
0
  }
200
201
5.64k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
202
117
    RETERR(str_totext(tctx->linebreak, target));
203
5.52k
  } else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
204
0
    RETERR(str_totext(" ", target));
205
0
  }
206
207
5.64k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
208
117
    RETERR(str_totext(")", target));
209
117
  }
210
211
5.64k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
212
117
    if (rdata->type == dns_rdatatype_dnskey ||
213
117
        rdata->type == dns_rdatatype_cdnskey)
214
71
    {
215
71
      RETERR(str_totext(" ; ", target));
216
71
      RETERR(str_totext(keyinfo, target));
217
71
    }
218
117
    RETERR(str_totext("; alg = ", target));
219
117
    RETERR(str_totext(algbuf, target));
220
117
    RETERR(str_totext(" ; key id = ", target));
221
117
    dns_rdata_toregion(rdata, &tmpr);
222
117
    snprintf(buf, sizeof(buf), "%u", dst_region_computeid(&tmpr));
223
117
    RETERR(str_totext(buf, target));
224
117
  }
225
5.64k
  return ISC_R_SUCCESS;
226
5.64k
}
227
228
static isc_result_t
229
8.23k
generic_fromwire_key(ARGS_FROMWIRE) {
230
8.23k
  unsigned char algorithm;
231
8.23k
  uint16_t flags;
232
8.23k
  isc_region_t sr;
233
234
8.23k
  UNUSED(rdclass);
235
8.23k
  UNUSED(dctx);
236
237
8.23k
  isc_buffer_activeregion(source, &sr);
238
8.23k
  if (sr.length < 4) {
239
27
    return ISC_R_UNEXPECTEDEND;
240
27
  }
241
8.21k
  flags = (sr.base[0] << 8) | sr.base[1];
242
243
8.21k
  if (type == dns_rdatatype_rkey && flags != 0U) {
244
39
    return DNS_R_FORMERR;
245
39
  }
246
247
8.17k
  algorithm = sr.base[3];
248
8.17k
  RETERR(mem_tobuffer(target, sr.base, 4));
249
8.10k
  isc_region_consume(&sr, 4);
250
8.10k
  isc_buffer_forward(source, 4);
251
252
8.10k
  if (generic_key_nokey(type, flags)) {
253
1.02k
    return ISC_R_SUCCESS;
254
1.02k
  }
255
7.08k
  if (sr.length == 0) {
256
16
    return ISC_R_UNEXPECTEDEND;
257
16
  }
258
259
7.06k
  if (algorithm == DNS_KEYALG_PRIVATEDNS ||
260
7.06k
      algorithm == DNS_KEYALG_PRIVATEOID)
261
685
  {
262
685
    isc_buffer_t b = *source;
263
685
    RETERR(check_private(&b, algorithm));
264
685
  }
265
266
6.95k
  isc_buffer_activeregion(source, &sr);
267
6.95k
  isc_buffer_forward(source, sr.length);
268
6.95k
  return mem_tobuffer(target, sr.base, sr.length);
269
7.06k
}
270
271
static isc_result_t
272
1.89k
fromtext_key(ARGS_FROMTEXT) {
273
1.89k
  REQUIRE(type == dns_rdatatype_key);
274
275
1.89k
  return generic_fromtext_key(CALL_FROMTEXT);
276
1.89k
}
277
278
static isc_result_t
279
2.27k
totext_key(ARGS_TOTEXT) {
280
2.27k
  REQUIRE(rdata != NULL);
281
2.27k
  REQUIRE(rdata->type == dns_rdatatype_key);
282
283
2.27k
  return generic_totext_key(CALL_TOTEXT);
284
2.27k
}
285
286
static isc_result_t
287
2.59k
fromwire_key(ARGS_FROMWIRE) {
288
2.59k
  REQUIRE(type == dns_rdatatype_key);
289
290
2.59k
  return generic_fromwire_key(CALL_FROMWIRE);
291
2.59k
}
292
293
static isc_result_t
294
1.18k
towire_key(ARGS_TOWIRE) {
295
1.18k
  isc_region_t sr;
296
297
1.18k
  REQUIRE(rdata != NULL);
298
1.18k
  REQUIRE(rdata->type == dns_rdatatype_key);
299
1.18k
  REQUIRE(rdata->length != 0);
300
301
1.18k
  UNUSED(cctx);
302
303
1.18k
  dns_rdata_toregion(rdata, &sr);
304
1.18k
  return mem_tobuffer(target, sr.base, sr.length);
305
1.18k
}
306
307
static int
308
2.87k
compare_key(ARGS_COMPARE) {
309
2.87k
  isc_region_t r1;
310
2.87k
  isc_region_t r2;
311
312
2.87k
  REQUIRE(rdata1 != NULL);
313
2.87k
  REQUIRE(rdata2 != NULL);
314
2.87k
  REQUIRE(rdata1->type == rdata2->type);
315
2.87k
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
316
2.87k
  REQUIRE(rdata1->type == dns_rdatatype_key);
317
2.87k
  REQUIRE(rdata1->length != 0);
318
2.87k
  REQUIRE(rdata2->length != 0);
319
320
2.87k
  dns_rdata_toregion(rdata1, &r1);
321
2.87k
  dns_rdata_toregion(rdata2, &r2);
322
2.87k
  return isc_region_compare(&r1, &r2);
323
2.87k
}
324
325
static isc_result_t
326
0
generic_fromstruct_key(ARGS_FROMSTRUCT) {
327
0
  dns_rdata_key_t *key = source;
328
329
0
  REQUIRE(key != NULL);
330
0
  REQUIRE(key->common.rdtype == type);
331
0
  REQUIRE(key->common.rdclass == rdclass);
332
333
0
  UNUSED(type);
334
0
  UNUSED(rdclass);
335
336
0
  if (type == dns_rdatatype_rkey) {
337
0
    INSIST(key->flags == 0U);
338
0
  }
339
340
  /* Flags */
341
0
  RETERR(uint16_tobuffer(key->flags, target));
342
343
  /* Protocol */
344
0
  RETERR(uint8_tobuffer(key->protocol, target));
345
346
  /* Algorithm */
347
0
  RETERR(uint8_tobuffer(key->algorithm, target));
348
349
  /* Data */
350
0
  return mem_tobuffer(target, key->data, key->datalen);
351
0
}
352
353
static isc_result_t
354
218
generic_tostruct_key(ARGS_TOSTRUCT) {
355
218
  dns_rdata_key_t *key = target;
356
218
  isc_region_t sr;
357
358
218
  REQUIRE(key != NULL);
359
218
  REQUIRE(rdata->length >= 4U);
360
361
218
  REQUIRE(key != NULL);
362
218
  REQUIRE(key->common.rdclass == rdata->rdclass);
363
218
  REQUIRE(key->common.rdtype == rdata->type);
364
365
218
  dns_rdata_toregion(rdata, &sr);
366
367
  /* Flags */
368
218
  key->flags = uint16_fromregion(&sr);
369
218
  isc_region_consume(&sr, 2);
370
371
  /* Protocol */
372
218
  key->protocol = uint8_fromregion(&sr);
373
218
  isc_region_consume(&sr, 1);
374
375
  /* Algorithm */
376
218
  key->algorithm = uint8_fromregion(&sr);
377
218
  isc_region_consume(&sr, 1);
378
379
  /* Data */
380
218
  key->datalen = sr.length;
381
218
  key->data = mem_maybedup(mctx, sr.base, key->datalen);
382
218
  key->mctx = mctx;
383
218
  return ISC_R_SUCCESS;
384
218
}
385
386
static void
387
0
generic_freestruct_key(ARGS_FREESTRUCT) {
388
0
  dns_rdata_key_t *key = (dns_rdata_key_t *)source;
389
390
0
  REQUIRE(key != NULL);
391
392
0
  if (key->mctx == NULL) {
393
0
    return;
394
0
  }
395
396
0
  if (key->data != NULL) {
397
0
    isc_mem_free(key->mctx, key->data);
398
0
  }
399
0
  key->mctx = NULL;
400
0
}
401
402
static isc_result_t
403
0
fromstruct_key(ARGS_FROMSTRUCT) {
404
0
  REQUIRE(type == dns_rdatatype_key);
405
406
0
  return generic_fromstruct_key(CALL_FROMSTRUCT);
407
0
}
408
409
static isc_result_t
410
121
tostruct_key(ARGS_TOSTRUCT) {
411
121
  dns_rdata_key_t *key = target;
412
413
121
  REQUIRE(key != NULL);
414
121
  REQUIRE(rdata != NULL);
415
121
  REQUIRE(rdata->type == dns_rdatatype_key);
416
417
121
  DNS_RDATACOMMON_INIT(key, rdata->type, rdata->rdclass);
418
419
121
  return generic_tostruct_key(CALL_TOSTRUCT);
420
121
}
421
422
static void
423
0
freestruct_key(ARGS_FREESTRUCT) {
424
0
  dns_rdata_key_t *key = (dns_rdata_key_t *)source;
425
426
0
  REQUIRE(key != NULL);
427
0
  REQUIRE(key->common.rdtype == dns_rdatatype_key);
428
429
0
  generic_freestruct_key(source);
430
0
}
431
432
static isc_result_t
433
0
additionaldata_key(ARGS_ADDLDATA) {
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(add);
440
0
  UNUSED(arg);
441
442
0
  return ISC_R_SUCCESS;
443
0
}
444
445
static isc_result_t
446
0
digest_key(ARGS_DIGEST) {
447
0
  isc_region_t r;
448
449
0
  REQUIRE(rdata != NULL);
450
0
  REQUIRE(rdata->type == dns_rdatatype_key);
451
452
0
  dns_rdata_toregion(rdata, &r);
453
454
0
  return (digest)(arg, &r);
455
0
}
456
457
static bool
458
0
checkowner_key(ARGS_CHECKOWNER) {
459
0
  REQUIRE(type == dns_rdatatype_key);
460
461
0
  UNUSED(name);
462
0
  UNUSED(type);
463
0
  UNUSED(rdclass);
464
0
  UNUSED(wildcard);
465
466
0
  return true;
467
0
}
468
469
static bool
470
0
checknames_key(ARGS_CHECKNAMES) {
471
0
  REQUIRE(rdata != NULL);
472
0
  REQUIRE(rdata->type == dns_rdatatype_key);
473
474
0
  UNUSED(rdata);
475
0
  UNUSED(owner);
476
0
  UNUSED(bad);
477
478
0
  return true;
479
0
}
480
481
static int
482
0
casecompare_key(ARGS_COMPARE) {
483
0
  return compare_key(rdata1, rdata2);
484
0
}
485
486
#endif /* RDATA_GENERIC_KEY_25_C */