Coverage Report

Created: 2026-01-17 06:14

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
#define RRTYPE_KEY_ATTRIBUTES \
22
145k
  (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
86.8k
generic_key_nokey(dns_rdatatype_t type, unsigned int flags) {
36
86.8k
  switch (type) {
37
5.45k
  case dns_rdatatype_cdnskey:
38
12.4k
  case dns_rdatatype_dnskey:
39
15.3k
  case dns_rdatatype_rkey:
40
15.3k
    return false;
41
71.5k
  case dns_rdatatype_key:
42
71.5k
  default:
43
71.5k
    return (flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY;
44
86.8k
  }
45
86.8k
}
46
47
static isc_result_t
48
3.07k
generic_fromtext_key(ARGS_FROMTEXT) {
49
3.07k
  isc_token_t token;
50
3.07k
  dns_secalg_t alg;
51
3.07k
  dns_secproto_t proto;
52
3.07k
  dns_keyflags_t flags;
53
3.07k
  unsigned int used;
54
55
3.07k
  UNUSED(rdclass);
56
3.07k
  UNUSED(origin);
57
3.07k
  UNUSED(options);
58
3.07k
  UNUSED(callbacks);
59
60
  /* flags */
61
3.07k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
62
3.07k
              false));
63
3.05k
  RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
64
2.95k
  if (type == dns_rdatatype_rkey && flags != 0U) {
65
35
    RETTOK(DNS_R_FORMERR);
66
35
  }
67
2.92k
  RETERR(uint16_tobuffer(flags, target));
68
69
  /* protocol */
70
2.92k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
71
2.92k
              false));
72
2.87k
  RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
73
2.75k
  RETERR(mem_tobuffer(target, &proto, 1));
74
75
  /* algorithm */
76
2.75k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
77
2.75k
              false));
78
2.74k
  RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
79
2.73k
  RETERR(mem_tobuffer(target, &alg, 1));
80
81
  /* No Key? */
82
2.73k
  if (generic_key_nokey(type, flags)) {
83
276
    return ISC_R_SUCCESS;
84
276
  }
85
86
  /*
87
   * Save the current used value. It will become the current
88
   * value when we parse the keydata field.
89
   */
90
2.45k
  used = isc_buffer_usedlength(target);
91
92
2.45k
  RETERR(isc_base64_tobuffer(lexer, target, -2));
93
94
2.39k
  if (alg == DNS_KEYALG_PRIVATEDNS || alg == DNS_KEYALG_PRIVATEOID) {
95
179
    isc_buffer_t b;
96
97
    /*
98
     * Set up 'b' so that the key data can be parsed.
99
     */
100
179
    b = *target;
101
179
    b.active = b.used;
102
179
    b.current = used;
103
104
179
    RETERR(check_private(&b, alg));
105
161
  }
106
107
2.37k
  return ISC_R_SUCCESS;
108
2.39k
}
109
110
static isc_result_t
111
6.67k
generic_totext_key(ARGS_TOTEXT) {
112
6.67k
  isc_region_t sr;
113
6.67k
  char buf[sizeof("[key id = 64000]")];
114
6.67k
  unsigned int flags;
115
6.67k
  unsigned char algorithm;
116
6.67k
  char algbuf[DNS_NAME_FORMATSIZE];
117
6.67k
  const char *keyinfo;
118
6.67k
  isc_region_t tmpr;
119
120
6.67k
  REQUIRE(rdata->length != 0);
121
122
6.67k
  dns_rdata_toregion(rdata, &sr);
123
124
  /* flags */
125
6.67k
  flags = uint16_fromregion(&sr);
126
6.67k
  isc_region_consume(&sr, 2);
127
6.67k
  snprintf(buf, sizeof(buf), "%u", flags);
128
6.67k
  RETERR(str_totext(buf, target));
129
6.67k
  RETERR(str_totext(" ", target));
130
6.67k
  if ((flags & DNS_KEYFLAG_KSK) != 0) {
131
2.47k
    if (flags & DNS_KEYFLAG_REVOKE) {
132
681
      keyinfo = "revoked KSK";
133
1.79k
    } else {
134
1.79k
      keyinfo = "KSK";
135
1.79k
    }
136
4.20k
  } else {
137
4.20k
    keyinfo = "ZSK";
138
4.20k
  }
139
140
  /* protocol */
141
6.67k
  snprintf(buf, sizeof(buf), "%u", sr.base[0]);
142
6.67k
  isc_region_consume(&sr, 1);
143
6.67k
  RETERR(str_totext(buf, target));
144
6.67k
  RETERR(str_totext(" ", target));
145
146
  /* algorithm */
147
6.67k
  algorithm = sr.base[0];
148
6.67k
  snprintf(buf, sizeof(buf), "%u", algorithm);
149
6.67k
  isc_region_consume(&sr, 1);
150
6.67k
  RETERR(str_totext(buf, target));
151
152
  /* No Key? */
153
6.67k
  if (generic_key_nokey(rdata->type, flags)) {
154
1.12k
    return ISC_R_SUCCESS;
155
1.12k
  }
156
157
5.55k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
158
121
      algorithm == DNS_KEYALG_PRIVATEDNS)
159
55
  {
160
55
    dns_name_t name;
161
55
    dns_name_init(&name);
162
55
    dns_name_fromregion(&name, &sr);
163
55
    dns_name_format(&name, algbuf, sizeof(algbuf));
164
5.50k
  } else if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
165
66
       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.47k
  } else {
177
5.47k
    dns_secalg_format((dns_secalg_t)algorithm, algbuf,
178
5.47k
          sizeof(algbuf));
179
5.47k
  }
180
181
  /* key */
182
5.55k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
183
121
    RETERR(str_totext(" (", target));
184
121
  }
185
5.55k
  RETERR(str_totext(tctx->linebreak, target));
186
187
5.55k
  if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
188
5.55k
    if (tctx->width == 0) { /* No splitting */
189
0
      RETERR(isc_base64_totext(&sr, 60, "", target));
190
5.55k
    } else {
191
5.55k
      RETERR(isc_base64_totext(&sr, tctx->width - 2,
192
5.55k
             tctx->linebreak, target));
193
5.55k
    }
194
5.55k
  } 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.55k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
202
121
    RETERR(str_totext(tctx->linebreak, target));
203
5.43k
  } else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
204
0
    RETERR(str_totext(" ", target));
205
0
  }
206
207
5.55k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
208
121
    RETERR(str_totext(")", target));
209
121
  }
210
211
5.55k
  if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
212
121
    if (rdata->type == dns_rdatatype_dnskey ||
213
101
        rdata->type == dns_rdatatype_cdnskey)
214
61
    {
215
61
      RETERR(str_totext(" ; ", target));
216
61
      RETERR(str_totext(keyinfo, target));
217
61
    }
218
121
    RETERR(str_totext("; alg = ", target));
219
121
    RETERR(str_totext(algbuf, target));
220
121
    RETERR(str_totext(" ; key id = ", target));
221
121
    dns_rdata_toregion(rdata, &tmpr);
222
121
    snprintf(buf, sizeof(buf), "%u", dst_region_computeid(&tmpr));
223
121
    RETERR(str_totext(buf, target));
224
121
  }
225
5.55k
  return ISC_R_SUCCESS;
226
5.55k
}
227
228
static isc_result_t
229
77.5k
generic_fromwire_key(ARGS_FROMWIRE) {
230
77.5k
  unsigned char algorithm;
231
77.5k
  uint16_t flags;
232
77.5k
  isc_region_t sr;
233
234
77.5k
  UNUSED(rdclass);
235
77.5k
  UNUSED(dctx);
236
237
77.5k
  isc_buffer_activeregion(source, &sr);
238
77.5k
  if (sr.length < 4) {
239
32
    return ISC_R_UNEXPECTEDEND;
240
32
  }
241
77.5k
  flags = (sr.base[0] << 8) | sr.base[1];
242
243
77.5k
  if (type == dns_rdatatype_rkey && flags != 0U) {
244
14
    return DNS_R_FORMERR;
245
14
  }
246
247
77.4k
  algorithm = sr.base[3];
248
77.4k
  RETERR(mem_tobuffer(target, sr.base, 4));
249
77.4k
  isc_region_consume(&sr, 4);
250
77.4k
  isc_buffer_forward(source, 4);
251
252
77.4k
  if (generic_key_nokey(type, flags)) {
253
1.11k
    return ISC_R_SUCCESS;
254
1.11k
  }
255
76.3k
  if (sr.length == 0) {
256
19
    return ISC_R_UNEXPECTEDEND;
257
19
  }
258
259
76.2k
  if (algorithm == DNS_KEYALG_PRIVATEDNS ||
260
75.7k
      algorithm == DNS_KEYALG_PRIVATEOID)
261
677
  {
262
677
    isc_buffer_t b = *source;
263
677
    RETERR(check_private(&b, algorithm));
264
567
  }
265
266
76.1k
  isc_buffer_activeregion(source, &sr);
267
76.1k
  isc_buffer_forward(source, sr.length);
268
76.1k
  return mem_tobuffer(target, sr.base, sr.length);
269
76.2k
}
270
271
static isc_result_t
272
1.16k
fromtext_key(ARGS_FROMTEXT) {
273
1.16k
  REQUIRE(type == dns_rdatatype_key);
274
275
1.16k
  return generic_fromtext_key(CALL_FROMTEXT);
276
1.16k
}
277
278
static isc_result_t
279
2.14k
totext_key(ARGS_TOTEXT) {
280
2.14k
  REQUIRE(rdata != NULL);
281
2.14k
  REQUIRE(rdata->type == dns_rdatatype_key);
282
283
2.14k
  return generic_totext_key(CALL_TOTEXT);
284
2.14k
}
285
286
static isc_result_t
287
68.3k
fromwire_key(ARGS_FROMWIRE) {
288
68.3k
  REQUIRE(type == dns_rdatatype_key);
289
290
68.3k
  return generic_fromwire_key(CALL_FROMWIRE);
291
68.3k
}
292
293
static isc_result_t
294
1.09k
towire_key(ARGS_TOWIRE) {
295
1.09k
  isc_region_t sr;
296
297
1.09k
  REQUIRE(rdata != NULL);
298
1.09k
  REQUIRE(rdata->type == dns_rdatatype_key);
299
1.09k
  REQUIRE(rdata->length != 0);
300
301
1.09k
  UNUSED(cctx);
302
303
1.09k
  dns_rdata_toregion(rdata, &sr);
304
1.09k
  return mem_tobuffer(target, sr.base, sr.length);
305
1.09k
}
306
307
static int
308
2.18k
compare_key(ARGS_COMPARE) {
309
2.18k
  isc_region_t r1;
310
2.18k
  isc_region_t r2;
311
312
2.18k
  REQUIRE(rdata1 != NULL);
313
2.18k
  REQUIRE(rdata2 != NULL);
314
2.18k
  REQUIRE(rdata1->type == rdata2->type);
315
2.18k
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
316
2.18k
  REQUIRE(rdata1->type == dns_rdatatype_key);
317
2.18k
  REQUIRE(rdata1->length != 0);
318
2.18k
  REQUIRE(rdata2->length != 0);
319
320
2.18k
  dns_rdata_toregion(rdata1, &r1);
321
2.18k
  dns_rdata_toregion(rdata2, &r2);
322
2.18k
  return isc_region_compare(&r1, &r2);
323
2.18k
}
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
215
generic_tostruct_key(ARGS_TOSTRUCT) {
355
215
  dns_rdata_key_t *key = target;
356
215
  isc_region_t sr;
357
358
215
  REQUIRE(key != NULL);
359
215
  REQUIRE(rdata->length >= 4U);
360
361
215
  REQUIRE(key != NULL);
362
215
  REQUIRE(key->common.rdclass == rdata->rdclass);
363
215
  REQUIRE(key->common.rdtype == rdata->type);
364
365
215
  dns_rdata_toregion(rdata, &sr);
366
367
  /* Flags */
368
215
  key->flags = uint16_fromregion(&sr);
369
215
  isc_region_consume(&sr, 2);
370
371
  /* Protocol */
372
215
  key->protocol = uint8_fromregion(&sr);
373
215
  isc_region_consume(&sr, 1);
374
375
  /* Algorithm */
376
215
  key->algorithm = uint8_fromregion(&sr);
377
215
  isc_region_consume(&sr, 1);
378
379
  /* Data */
380
215
  key->datalen = sr.length;
381
215
  key->data = mem_maybedup(mctx, sr.base, key->datalen);
382
215
  key->mctx = mctx;
383
215
  return ISC_R_SUCCESS;
384
215
}
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
122
tostruct_key(ARGS_TOSTRUCT) {
411
122
  dns_rdata_key_t *key = target;
412
413
122
  REQUIRE(key != NULL);
414
122
  REQUIRE(rdata != NULL);
415
122
  REQUIRE(rdata->type == dns_rdatatype_key);
416
417
122
  DNS_RDATACOMMON_INIT(key, rdata->type, rdata->rdclass);
418
419
122
  return generic_tostruct_key(CALL_TOSTRUCT);
420
122
}
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 */