Coverage Report

Created: 2026-03-07 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/kasp.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
/*! \file */
15
16
#include <string.h>
17
18
#include <isc/assertions.h>
19
#include <isc/buffer.h>
20
#include <isc/file.h>
21
#include <isc/hex.h>
22
#include <isc/log.h>
23
#include <isc/mem.h>
24
#include <isc/util.h>
25
26
#include <dns/kasp.h>
27
#include <dns/keyvalues.h>
28
29
#include <dst/dst.h>
30
31
/* Default TTLsig (maximum zone ttl) */
32
0
#define DEFAULT_TTLSIG 604800 /* one week */
33
34
void
35
0
dns_kasp_create(isc_mem_t *mctx, const char *name, dns_kasp_t **kaspp) {
36
0
  dns_kasp_t *kasp;
37
0
  dns_kasp_t k = {
38
0
    .magic = DNS_KASP_MAGIC,
39
0
    .digests = ISC_LIST_INITIALIZER,
40
0
    .keys = ISC_LIST_INITIALIZER,
41
0
    .link = ISC_LINK_INITIALIZER,
42
0
  };
43
44
0
  REQUIRE(name != NULL);
45
0
  REQUIRE(kaspp != NULL && *kaspp == NULL);
46
47
0
  kasp = isc_mem_get(mctx, sizeof(*kasp));
48
0
  *kasp = k;
49
50
0
  kasp->mctx = NULL;
51
0
  isc_mem_attach(mctx, &kasp->mctx);
52
0
  kasp->name = isc_mem_strdup(mctx, name);
53
0
  isc_mutex_init(&kasp->lock);
54
0
  isc_refcount_init(&kasp->references, 1);
55
56
0
  *kaspp = kasp;
57
0
}
58
59
static void
60
0
destroy(dns_kasp_t *kasp) {
61
0
  REQUIRE(!ISC_LINK_LINKED(kasp, link));
62
63
0
  ISC_LIST_FOREACH(kasp->keys, key, link) {
64
0
    ISC_LIST_UNLINK(kasp->keys, key, link);
65
0
    dns_kasp_key_destroy(key);
66
0
  }
67
0
  INSIST(ISC_LIST_EMPTY(kasp->keys));
68
69
0
  ISC_LIST_FOREACH(kasp->digests, digest, link) {
70
0
    ISC_LIST_UNLINK(kasp->digests, digest, link);
71
0
    isc_mem_put(kasp->mctx, digest, sizeof(*digest));
72
0
  }
73
0
  INSIST(ISC_LIST_EMPTY(kasp->digests));
74
75
0
  isc_mutex_destroy(&kasp->lock);
76
0
  isc_mem_free(kasp->mctx, kasp->name);
77
0
  isc_mem_putanddetach(&kasp->mctx, kasp, sizeof(*kasp));
78
0
}
79
80
#if DNS_KASP_TRACE
81
ISC_REFCOUNT_TRACE_IMPL(dns_kasp, destroy);
82
#else
83
0
ISC_REFCOUNT_IMPL(dns_kasp, destroy);
Unexecuted instantiation: dns_kasp_ref
Unexecuted instantiation: dns_kasp_unref
Unexecuted instantiation: dns_kasp_detach
84
0
#endif
85
0
86
0
const char *
87
0
dns_kasp_getname(dns_kasp_t *kasp) {
88
0
  REQUIRE(DNS_KASP_VALID(kasp));
89
90
0
  return kasp->name;
91
0
}
92
93
void
94
0
dns_kasp_freeze(dns_kasp_t *kasp) {
95
0
  REQUIRE(DNS_KASP_VALID(kasp));
96
0
  REQUIRE(!kasp->frozen);
97
98
0
  kasp->frozen = true;
99
0
}
100
101
void
102
0
dns_kasp_thaw(dns_kasp_t *kasp) {
103
0
  REQUIRE(DNS_KASP_VALID(kasp));
104
0
  REQUIRE(kasp->frozen);
105
106
0
  kasp->frozen = false;
107
0
}
108
109
uint32_t
110
0
dns_kasp_signdelay(dns_kasp_t *kasp) {
111
0
  REQUIRE(DNS_KASP_VALID(kasp));
112
0
  REQUIRE(kasp->frozen);
113
114
0
  return kasp->signatures_validity - kasp->signatures_refresh;
115
0
}
116
117
uint32_t
118
0
dns_kasp_sigjitter(dns_kasp_t *kasp) {
119
0
  REQUIRE(DNS_KASP_VALID(kasp));
120
0
  REQUIRE(kasp->frozen);
121
122
0
  return kasp->signatures_jitter;
123
0
}
124
125
void
126
0
dns_kasp_setsigjitter(dns_kasp_t *kasp, uint32_t value) {
127
0
  REQUIRE(DNS_KASP_VALID(kasp));
128
0
  REQUIRE(!kasp->frozen);
129
130
0
  kasp->signatures_jitter = value;
131
0
}
132
133
uint32_t
134
0
dns_kasp_sigrefresh(dns_kasp_t *kasp) {
135
0
  REQUIRE(DNS_KASP_VALID(kasp));
136
0
  REQUIRE(kasp->frozen);
137
138
0
  return kasp->signatures_refresh;
139
0
}
140
141
void
142
0
dns_kasp_setsigrefresh(dns_kasp_t *kasp, uint32_t value) {
143
0
  REQUIRE(DNS_KASP_VALID(kasp));
144
0
  REQUIRE(!kasp->frozen);
145
146
0
  kasp->signatures_refresh = value;
147
0
}
148
149
uint32_t
150
0
dns_kasp_sigvalidity(dns_kasp_t *kasp) {
151
0
  REQUIRE(DNS_KASP_VALID(kasp));
152
0
  REQUIRE(kasp->frozen);
153
154
0
  return kasp->signatures_validity;
155
0
}
156
157
void
158
0
dns_kasp_setsigvalidity(dns_kasp_t *kasp, uint32_t value) {
159
0
  REQUIRE(DNS_KASP_VALID(kasp));
160
0
  REQUIRE(!kasp->frozen);
161
162
0
  kasp->signatures_validity = value;
163
0
}
164
165
uint32_t
166
0
dns_kasp_sigvalidity_dnskey(dns_kasp_t *kasp) {
167
0
  REQUIRE(DNS_KASP_VALID(kasp));
168
0
  REQUIRE(kasp->frozen);
169
170
0
  return kasp->signatures_validity_dnskey;
171
0
}
172
173
void
174
0
dns_kasp_setsigvalidity_dnskey(dns_kasp_t *kasp, uint32_t value) {
175
0
  REQUIRE(DNS_KASP_VALID(kasp));
176
0
  REQUIRE(!kasp->frozen);
177
178
0
  kasp->signatures_validity_dnskey = value;
179
0
}
180
181
dns_ttl_t
182
0
dns_kasp_dnskeyttl(dns_kasp_t *kasp) {
183
0
  REQUIRE(DNS_KASP_VALID(kasp));
184
0
  REQUIRE(kasp->frozen);
185
186
0
  return kasp->dnskey_ttl;
187
0
}
188
189
void
190
0
dns_kasp_setdnskeyttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
191
0
  REQUIRE(DNS_KASP_VALID(kasp));
192
0
  REQUIRE(!kasp->frozen);
193
194
0
  kasp->dnskey_ttl = ttl;
195
0
}
196
197
uint32_t
198
0
dns_kasp_purgekeys(dns_kasp_t *kasp) {
199
0
  REQUIRE(DNS_KASP_VALID(kasp));
200
0
  REQUIRE(kasp->frozen);
201
202
0
  return kasp->purge_keys;
203
0
}
204
205
void
206
0
dns_kasp_setpurgekeys(dns_kasp_t *kasp, uint32_t value) {
207
0
  REQUIRE(DNS_KASP_VALID(kasp));
208
0
  REQUIRE(!kasp->frozen);
209
210
0
  kasp->purge_keys = value;
211
0
}
212
213
uint32_t
214
0
dns_kasp_publishsafety(dns_kasp_t *kasp) {
215
0
  REQUIRE(DNS_KASP_VALID(kasp));
216
0
  REQUIRE(kasp->frozen);
217
218
0
  return kasp->publish_safety;
219
0
}
220
221
void
222
0
dns_kasp_setpublishsafety(dns_kasp_t *kasp, uint32_t value) {
223
0
  REQUIRE(DNS_KASP_VALID(kasp));
224
0
  REQUIRE(!kasp->frozen);
225
226
0
  kasp->publish_safety = value;
227
0
}
228
229
uint32_t
230
0
dns_kasp_retiresafety(dns_kasp_t *kasp) {
231
0
  REQUIRE(DNS_KASP_VALID(kasp));
232
0
  REQUIRE(kasp->frozen);
233
234
0
  return kasp->retire_safety;
235
0
}
236
237
void
238
0
dns_kasp_setretiresafety(dns_kasp_t *kasp, uint32_t value) {
239
0
  REQUIRE(DNS_KASP_VALID(kasp));
240
0
  REQUIRE(!kasp->frozen);
241
242
0
  kasp->retire_safety = value;
243
0
}
244
245
bool
246
0
dns_kasp_inlinesigning(dns_kasp_t *kasp) {
247
0
  REQUIRE(DNS_KASP_VALID(kasp));
248
0
  REQUIRE(kasp->frozen);
249
250
0
  return kasp->inline_signing;
251
0
}
252
253
void
254
0
dns_kasp_setinlinesigning(dns_kasp_t *kasp, bool value) {
255
0
  REQUIRE(DNS_KASP_VALID(kasp));
256
0
  REQUIRE(!kasp->frozen);
257
258
0
  kasp->inline_signing = value;
259
0
}
260
261
bool
262
0
dns_kasp_manualmode(dns_kasp_t *kasp) {
263
0
  REQUIRE(DNS_KASP_VALID(kasp));
264
0
  REQUIRE(kasp->frozen);
265
266
0
  return kasp->manual_mode;
267
0
}
268
269
void
270
0
dns_kasp_setmanualmode(dns_kasp_t *kasp, bool value) {
271
0
  REQUIRE(DNS_KASP_VALID(kasp));
272
0
  REQUIRE(!kasp->frozen);
273
274
0
  kasp->manual_mode = value;
275
0
}
276
277
dns_ttl_t
278
0
dns_kasp_zonemaxttl(dns_kasp_t *kasp, bool fallback) {
279
0
  REQUIRE(DNS_KASP_VALID(kasp));
280
0
  REQUIRE(kasp->frozen);
281
282
0
  if (kasp->zone_max_ttl == 0 && fallback) {
283
0
    return DEFAULT_TTLSIG;
284
0
  }
285
0
  return kasp->zone_max_ttl;
286
0
}
287
288
void
289
0
dns_kasp_setzonemaxttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
290
0
  REQUIRE(DNS_KASP_VALID(kasp));
291
0
  REQUIRE(!kasp->frozen);
292
293
0
  kasp->zone_max_ttl = ttl;
294
0
}
295
296
uint32_t
297
0
dns_kasp_zonepropagationdelay(dns_kasp_t *kasp) {
298
0
  REQUIRE(DNS_KASP_VALID(kasp));
299
0
  REQUIRE(kasp->frozen);
300
301
0
  return kasp->zone_propagation_delay;
302
0
}
303
304
void
305
0
dns_kasp_setzonepropagationdelay(dns_kasp_t *kasp, uint32_t value) {
306
0
  REQUIRE(DNS_KASP_VALID(kasp));
307
0
  REQUIRE(!kasp->frozen);
308
309
0
  kasp->zone_propagation_delay = value;
310
0
}
311
312
dns_ttl_t
313
0
dns_kasp_dsttl(dns_kasp_t *kasp) {
314
0
  REQUIRE(DNS_KASP_VALID(kasp));
315
0
  REQUIRE(kasp->frozen);
316
317
0
  return kasp->parent_ds_ttl;
318
0
}
319
320
void
321
0
dns_kasp_setdsttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
322
0
  REQUIRE(DNS_KASP_VALID(kasp));
323
0
  REQUIRE(!kasp->frozen);
324
325
0
  kasp->parent_ds_ttl = ttl;
326
0
}
327
328
uint32_t
329
0
dns_kasp_parentpropagationdelay(dns_kasp_t *kasp) {
330
0
  REQUIRE(DNS_KASP_VALID(kasp));
331
0
  REQUIRE(kasp->frozen);
332
333
0
  return kasp->parent_propagation_delay;
334
0
}
335
336
void
337
0
dns_kasp_setparentpropagationdelay(dns_kasp_t *kasp, uint32_t value) {
338
0
  REQUIRE(DNS_KASP_VALID(kasp));
339
0
  REQUIRE(!kasp->frozen);
340
341
0
  kasp->parent_propagation_delay = value;
342
0
}
343
344
isc_result_t
345
0
dns_kasplist_find(dns_kasplist_t *list, const char *name, dns_kasp_t **kaspp) {
346
0
  REQUIRE(kaspp != NULL && *kaspp == NULL);
347
348
0
  if (list == NULL) {
349
0
    return ISC_R_NOTFOUND;
350
0
  }
351
352
0
  ISC_LIST_FOREACH(*list, kasp, link) {
353
0
    if (strcmp(kasp->name, name) == 0) {
354
0
      dns_kasp_attach(kasp, kaspp);
355
0
      return ISC_R_SUCCESS;
356
0
    }
357
0
  }
358
359
0
  return ISC_R_NOTFOUND;
360
0
}
361
362
dns_kasp_keylist_t
363
0
dns_kasp_keys(dns_kasp_t *kasp) {
364
0
  REQUIRE(DNS_KASP_VALID(kasp));
365
0
  REQUIRE(kasp->frozen);
366
367
0
  return kasp->keys;
368
0
}
369
370
bool
371
0
dns_kasp_keylist_empty(dns_kasp_t *kasp) {
372
0
  REQUIRE(DNS_KASP_VALID(kasp));
373
374
0
  return ISC_LIST_EMPTY(kasp->keys);
375
0
}
376
377
void
378
0
dns_kasp_addkey(dns_kasp_t *kasp, dns_kasp_key_t *key) {
379
0
  REQUIRE(DNS_KASP_VALID(kasp));
380
0
  REQUIRE(!kasp->frozen);
381
0
  REQUIRE(key != NULL);
382
383
0
  ISC_LIST_APPEND(kasp->keys, key, link);
384
0
}
385
386
void
387
0
dns_kasp_key_create(dns_kasp_t *kasp, dns_kasp_key_t **keyp) {
388
0
  dns_kasp_key_t *key = NULL;
389
0
  dns_kasp_key_t k = { .tag_max = 0xffff, .length = -1 };
390
391
0
  REQUIRE(DNS_KASP_VALID(kasp));
392
0
  REQUIRE(keyp != NULL && *keyp == NULL);
393
394
0
  key = isc_mem_get(kasp->mctx, sizeof(*key));
395
0
  *key = k;
396
397
0
  key->mctx = NULL;
398
0
  isc_mem_attach(kasp->mctx, &key->mctx);
399
400
0
  ISC_LINK_INIT(key, link);
401
402
0
  *keyp = key;
403
0
}
404
405
void
406
0
dns_kasp_key_destroy(dns_kasp_key_t *key) {
407
0
  REQUIRE(key != NULL);
408
409
0
  if (key->keystore != NULL) {
410
0
    dns_keystore_detach(&key->keystore);
411
0
  }
412
0
  isc_mem_putanddetach(&key->mctx, key, sizeof(*key));
413
0
}
414
415
uint32_t
416
0
dns_kasp_key_algorithm(dns_kasp_key_t *key) {
417
0
  REQUIRE(key != NULL);
418
419
0
  return key->algorithm;
420
0
}
421
422
unsigned int
423
0
dns_kasp_key_size(dns_kasp_key_t *key) {
424
0
  unsigned int size = 0;
425
0
  unsigned int min = 0;
426
427
0
  REQUIRE(key != NULL);
428
429
0
  switch (key->algorithm) {
430
0
  case DST_ALG_RSASHA1:
431
0
  case DST_ALG_NSEC3RSASHA1:
432
0
  case DST_ALG_RSASHA256:
433
0
  case DST_ALG_RSASHA512:
434
0
  case DST_ALG_RSASHA256PRIVATEOID:
435
0
  case DST_ALG_RSASHA512PRIVATEOID:
436
0
    min = (key->algorithm == DST_ALG_RSASHA512) ? 1024 : 512;
437
0
    if (key->length > -1) {
438
0
      size = (unsigned int)key->length;
439
0
      if (size < min) {
440
0
        size = min;
441
0
      }
442
0
      if (size > 4096) {
443
0
        size = 4096;
444
0
      }
445
0
    } else {
446
0
      size = 2048;
447
0
    }
448
0
    break;
449
0
  case DST_ALG_ECDSA256:
450
0
    size = 256;
451
0
    break;
452
0
  case DST_ALG_ECDSA384:
453
0
    size = 384;
454
0
    break;
455
0
  case DST_ALG_ED25519:
456
0
    size = 256;
457
0
    break;
458
0
  case DST_ALG_ED448:
459
0
    size = 456;
460
0
    break;
461
0
  default:
462
    /* unsupported */
463
0
    break;
464
0
  }
465
0
  return size;
466
0
}
467
468
uint32_t
469
0
dns_kasp_key_lifetime(dns_kasp_key_t *key) {
470
0
  REQUIRE(key != NULL);
471
472
0
  return key->lifetime;
473
0
}
474
475
dns_keystore_t *
476
0
dns_kasp_key_keystore(dns_kasp_key_t *key) {
477
0
  REQUIRE(key != NULL);
478
479
0
  return key->keystore;
480
0
}
481
482
bool
483
0
dns_kasp_key_ksk(dns_kasp_key_t *key) {
484
0
  REQUIRE(key != NULL);
485
486
0
  return key->role & DNS_KASP_KEY_ROLE_KSK;
487
0
}
488
489
bool
490
0
dns_kasp_key_zsk(dns_kasp_key_t *key) {
491
0
  REQUIRE(key != NULL);
492
493
0
  return key->role & DNS_KASP_KEY_ROLE_ZSK;
494
0
}
495
496
uint16_t
497
0
dns_kasp_key_tagmin(dns_kasp_key_t *key) {
498
0
  REQUIRE(key != NULL);
499
0
  return key->tag_min;
500
0
}
501
502
uint16_t
503
0
dns_kasp_key_tagmax(dns_kasp_key_t *key) {
504
0
  REQUIRE(key != NULL);
505
0
  return key->tag_min;
506
0
}
507
508
bool
509
0
dns_kasp_key_match(dns_kasp_key_t *key, dns_dnsseckey_t *dkey) {
510
0
  isc_result_t result;
511
0
  bool role = false;
512
513
0
  REQUIRE(key != NULL);
514
0
  REQUIRE(dkey != NULL);
515
516
  /* Matching algorithms? */
517
0
  if (dst_key_alg(dkey->key) != dns_kasp_key_algorithm(key)) {
518
0
    return false;
519
0
  }
520
  /* Matching length? */
521
0
  if (dst_key_size(dkey->key) != dns_kasp_key_size(key)) {
522
0
    return false;
523
0
  }
524
  /* Matching role? */
525
0
  result = dst_key_getbool(dkey->key, DST_BOOL_KSK, &role);
526
0
  if (result != ISC_R_SUCCESS || role != dns_kasp_key_ksk(key)) {
527
0
    return false;
528
0
  }
529
0
  result = dst_key_getbool(dkey->key, DST_BOOL_ZSK, &role);
530
0
  if (result != ISC_R_SUCCESS || role != dns_kasp_key_zsk(key)) {
531
0
    return false;
532
0
  }
533
  /* Valid key tag range? */
534
0
  uint16_t id = dst_key_id(dkey->key);
535
0
  uint16_t rid = dst_key_rid(dkey->key);
536
0
  if (id < key->tag_min || id > key->tag_max) {
537
0
    return false;
538
0
  }
539
0
  if (rid < key->tag_min || rid > key->tag_max) {
540
0
    return false;
541
0
  }
542
543
  /* Found a match. */
544
0
  return true;
545
0
}
546
547
void
548
0
dns_kasp_key_format(dns_kasp_key_t *key, char *cp, unsigned int size) {
549
0
  REQUIRE(key != NULL);
550
0
  REQUIRE(cp != NULL);
551
552
0
  char algstr[DNS_NAME_FORMATSIZE];
553
0
  bool csk = dns_kasp_key_ksk(key) && dns_kasp_key_zsk(key);
554
0
  const char *rolestr = (csk ? "csk"
555
0
           : (dns_kasp_key_ksk(key) ? "ksk" : "zsk"));
556
557
0
  dst_algorithm_format(key->algorithm, algstr, sizeof(algstr));
558
0
  snprintf(cp, size, "%s algorithm:%s length:%u tag-range:%u-%u", rolestr,
559
0
     algstr, dns_kasp_key_size(key), key->tag_min, key->tag_max);
560
0
}
561
562
uint8_t
563
0
dns_kasp_nsec3iter(dns_kasp_t *kasp) {
564
0
  REQUIRE(kasp != NULL);
565
0
  REQUIRE(kasp->frozen);
566
0
  REQUIRE(kasp->nsec3);
567
568
0
  return kasp->nsec3param.iterations;
569
0
}
570
571
uint8_t
572
0
dns_kasp_nsec3flags(dns_kasp_t *kasp) {
573
0
  REQUIRE(kasp != NULL);
574
0
  REQUIRE(kasp->frozen);
575
0
  REQUIRE(kasp->nsec3);
576
577
0
  if (kasp->nsec3param.optout) {
578
0
    return 0x01;
579
0
  }
580
0
  return 0x00;
581
0
}
582
583
uint8_t
584
0
dns_kasp_nsec3saltlen(dns_kasp_t *kasp) {
585
0
  REQUIRE(kasp != NULL);
586
0
  REQUIRE(kasp->frozen);
587
0
  REQUIRE(kasp->nsec3);
588
589
0
  return kasp->nsec3param.saltlen;
590
0
}
591
592
bool
593
0
dns_kasp_nsec3(dns_kasp_t *kasp) {
594
0
  REQUIRE(kasp != NULL);
595
0
  REQUIRE(kasp->frozen);
596
597
0
  return kasp->nsec3;
598
0
}
599
600
void
601
0
dns_kasp_setnsec3(dns_kasp_t *kasp, bool nsec3) {
602
0
  REQUIRE(kasp != NULL);
603
0
  REQUIRE(!kasp->frozen);
604
605
0
  kasp->nsec3 = nsec3;
606
0
}
607
608
void
609
dns_kasp_setnsec3param(dns_kasp_t *kasp, uint8_t iter, bool optout,
610
0
           uint8_t saltlen) {
611
0
  REQUIRE(kasp != NULL);
612
0
  REQUIRE(!kasp->frozen);
613
0
  REQUIRE(kasp->nsec3);
614
615
0
  kasp->nsec3param.iterations = iter;
616
0
  kasp->nsec3param.optout = optout;
617
0
  kasp->nsec3param.saltlen = saltlen;
618
0
}
619
620
bool
621
0
dns_kasp_offlineksk(dns_kasp_t *kasp) {
622
0
  REQUIRE(kasp != NULL);
623
0
  REQUIRE(kasp->frozen);
624
625
0
  return kasp->offlineksk;
626
0
}
627
628
void
629
0
dns_kasp_setofflineksk(dns_kasp_t *kasp, bool offlineksk) {
630
0
  REQUIRE(kasp != NULL);
631
0
  REQUIRE(!kasp->frozen);
632
633
0
  kasp->offlineksk = offlineksk;
634
0
}
635
636
bool
637
0
dns_kasp_cdnskey(dns_kasp_t *kasp) {
638
0
  REQUIRE(kasp != NULL);
639
0
  REQUIRE(kasp->frozen);
640
641
0
  return kasp->cdnskey;
642
0
}
643
644
void
645
0
dns_kasp_setcdnskey(dns_kasp_t *kasp, bool cdnskey) {
646
0
  REQUIRE(kasp != NULL);
647
0
  REQUIRE(!kasp->frozen);
648
649
0
  kasp->cdnskey = cdnskey;
650
0
}
651
652
dns_kasp_digestlist_t
653
0
dns_kasp_digests(dns_kasp_t *kasp) {
654
0
  REQUIRE(DNS_KASP_VALID(kasp));
655
0
  REQUIRE(kasp->frozen);
656
657
0
  return kasp->digests;
658
0
}
659
660
void
661
0
dns_kasp_adddigest(dns_kasp_t *kasp, dns_dsdigest_t alg) {
662
0
  dns_kasp_digest_t *digest;
663
664
0
  REQUIRE(DNS_KASP_VALID(kasp));
665
0
  REQUIRE(!kasp->frozen);
666
667
  /* Suppress unsupported algorithms */
668
0
  if (!dst_ds_digest_supported(alg)) {
669
0
    return;
670
0
  }
671
672
  /* Suppress duplicates */
673
0
  ISC_LIST_FOREACH(kasp->digests, d, link) {
674
0
    if (d->digest == alg) {
675
0
      return;
676
0
    }
677
0
  }
678
679
0
  digest = isc_mem_get(kasp->mctx, sizeof(*digest));
680
0
  digest->digest = alg;
681
0
  ISC_LINK_INIT(digest, link);
682
  ISC_LIST_APPEND(kasp->digests, digest, link);
683
0
}