Coverage Report

Created: 2025-11-24 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/keymgr.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 <inttypes.h>
17
#include <stdbool.h>
18
#include <stdlib.h>
19
#include <unistd.h>
20
21
#include <isc/buffer.h>
22
#include <isc/dir.h>
23
#include <isc/log.h>
24
#include <isc/mem.h>
25
#include <isc/result.h>
26
#include <isc/string.h>
27
#include <isc/time.h>
28
#include <isc/util.h>
29
30
#include <dns/dnssec.h>
31
#include <dns/kasp.h>
32
#include <dns/keymgr.h>
33
#include <dns/keyvalues.h>
34
35
#include <dst/dst.h>
36
37
#define RETERR(x)                            \
38
0
  do {                                 \
39
0
    result = (x);                \
40
0
    if (result != ISC_R_SUCCESS) \
41
0
      goto failure;        \
42
0
  } while (0)
43
44
/*
45
 * Set key state to `target` state and change last changed
46
 * to `time`, only if key state has not been set before.
47
 */
48
#define INITIALIZE_STATE(key, state, timing, target, time)                     \
49
0
  do {                                                                   \
50
0
    dst_key_state_t s;                                             \
51
0
    char keystr[DST_KEY_FORMATSIZE];                               \
52
0
    if (dst_key_getstate((key), (state), &s) == ISC_R_NOTFOUND) {  \
53
0
      dst_key_setstate((key), (state), (target));            \
54
0
      dst_key_settime((key), (timing), time);                \
55
0
                                                                               \
56
0
      if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {              \
57
0
        dst_key_format((key), keystr, sizeof(keystr)); \
58
0
        isc_log_write(                                 \
59
0
          DNS_LOGCATEGORY_DNSSEC,                \
60
0
          DNS_LOGMODULE_DNSSEC,                  \
61
0
          ISC_LOG_DEBUG(3),                      \
62
0
          "keymgr: DNSKEY %s (%s) initialize "   \
63
0
          "%s state to %s (policy %s)",          \
64
0
          keystr, keymgr_keyrole(key),           \
65
0
          keystatetags[state],                   \
66
0
          keystatestrings[target],               \
67
0
          dns_kasp_getname(kasp));               \
68
0
      }                                                      \
69
0
    }                                                              \
70
0
  } while (0)
71
72
/* Shorter keywords for better readability. */
73
0
#define HIDDEN      DST_KEY_STATE_HIDDEN
74
0
#define RUMOURED    DST_KEY_STATE_RUMOURED
75
0
#define OMNIPRESENT DST_KEY_STATE_OMNIPRESENT
76
0
#define UNRETENTIVE DST_KEY_STATE_UNRETENTIVE
77
0
#define NA      DST_KEY_STATE_NA
78
79
/* Quickly get key state timing metadata. */
80
static int keystatetimes[] = { DST_TIME_DNSKEY, DST_TIME_ZRRSIG,
81
             DST_TIME_KRRSIG, DST_TIME_DS };
82
0
#define NUM_KEYSTATES (int)ARRAY_SIZE(keystatetimes)
83
84
/* Readable key state types and values. */
85
static const char *keystatetags[NUM_KEYSTATES] = { "DNSKEY", "ZRRSIG", "KRRSIG",
86
               "DS" };
87
static const char *keystatestrings[] = { "HIDDEN", "RUMOURED", "OMNIPRESENT",
88
           "UNRETENTIVE" };
89
90
static void
91
0
log_key_overflow(dst_key_t *key, const char *what) {
92
0
  char keystr[DST_KEY_FORMATSIZE];
93
0
  dst_key_format(key, keystr, sizeof(keystr));
94
0
  isc_log_write(
95
0
    DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
96
0
    "keymgr: DNSKEY %s (%s) calculation overflowed", keystr, what);
97
0
}
98
99
/*
100
 * Print key role.
101
 *
102
 */
103
static const char *
104
0
keymgr_keyrole(dst_key_t *key) {
105
0
  bool ksk = false, zsk = false;
106
0
  isc_result_t ret;
107
0
  ret = dst_key_getbool(key, DST_BOOL_KSK, &ksk);
108
0
  if (ret != ISC_R_SUCCESS) {
109
0
    return "UNKNOWN";
110
0
  }
111
0
  ret = dst_key_getbool(key, DST_BOOL_ZSK, &zsk);
112
0
  if (ret != ISC_R_SUCCESS) {
113
0
    return "UNKNOWN";
114
0
  }
115
0
  if (ksk && zsk) {
116
0
    return "CSK";
117
0
  } else if (ksk) {
118
0
    return "KSK";
119
0
  } else if (zsk) {
120
0
    return "ZSK";
121
0
  }
122
0
  return "NOSIGN";
123
0
}
124
125
/*
126
 * Set the remove time on key given its retire time.
127
 *
128
 */
129
static void
130
0
keymgr_settime_remove(dns_dnsseckey_t *key, dns_kasp_t *kasp) {
131
0
  isc_stdtime_t retire = 0, remove = 0, ksk_remove = 0, zsk_remove = 0;
132
0
  bool zsk = false, ksk = false;
133
0
  isc_result_t ret;
134
135
0
  REQUIRE(key != NULL);
136
0
  REQUIRE(key->key != NULL);
137
138
0
  ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
139
0
  if (ret != ISC_R_SUCCESS) {
140
0
    return;
141
0
  }
142
143
0
  ret = dst_key_getbool(key->key, DST_BOOL_ZSK, &zsk);
144
0
  if (ret == ISC_R_SUCCESS && zsk) {
145
0
    dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
146
    /* ZSK: Iret = Dsgn + Dprp + TTLsig */
147
0
    zsk_remove =
148
0
      retire + ttlsig + dns_kasp_zonepropagationdelay(kasp) +
149
0
      dns_kasp_retiresafety(kasp) + dns_kasp_signdelay(kasp);
150
0
  }
151
0
  ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk);
152
0
  if (ret == ISC_R_SUCCESS && ksk) {
153
    /* KSK: Iret = DprpP + TTLds */
154
0
    ksk_remove = retire + dns_kasp_dsttl(kasp) +
155
0
           dns_kasp_parentpropagationdelay(kasp) +
156
0
           dns_kasp_retiresafety(kasp);
157
0
  }
158
159
0
  remove = ISC_MAX(ksk_remove, zsk_remove);
160
0
  dst_key_settime(key->key, DST_TIME_DELETE, remove);
161
0
}
162
163
/*
164
 * Set the SyncPublish time (when the DS may be submitted to the parent).
165
 *
166
 */
167
void
168
0
dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first) {
169
0
  isc_stdtime_t published, syncpublish;
170
0
  bool ksk = false;
171
0
  isc_result_t ret;
172
173
0
  REQUIRE(key != NULL);
174
175
0
  ret = dst_key_gettime(key, DST_TIME_PUBLISH, &published);
176
0
  if (ret != ISC_R_SUCCESS) {
177
0
    return;
178
0
  }
179
180
0
  ret = dst_key_getbool(key, DST_BOOL_KSK, &ksk);
181
0
  if (ret != ISC_R_SUCCESS || !ksk) {
182
0
    return;
183
0
  }
184
185
0
  syncpublish = published + dst_key_getttl(key) +
186
0
          dns_kasp_zonepropagationdelay(kasp) +
187
0
          dns_kasp_publishsafety(kasp);
188
0
  if (first) {
189
    /* Also need to wait until the signatures are omnipresent. */
190
0
    isc_stdtime_t zrrsig_present;
191
0
    dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
192
0
    zrrsig_present = published + ttlsig +
193
0
         dns_kasp_zonepropagationdelay(kasp);
194
0
    if (zrrsig_present > syncpublish) {
195
0
      syncpublish = zrrsig_present;
196
0
    }
197
0
  }
198
0
  dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncpublish);
199
200
0
  uint32_t lifetime = 0;
201
0
  ret = dst_key_getnum(key, DST_NUM_LIFETIME, &lifetime);
202
0
  if (ret == ISC_R_SUCCESS && lifetime > 0) {
203
0
    dst_key_settime(key, DST_TIME_SYNCDELETE,
204
0
        syncpublish + lifetime);
205
0
  }
206
0
}
207
208
/*
209
 * Calculate prepublication time of a successor key of 'key'.
210
 * This function can have side effects:
211
 * 1. If there is no active time set, which would be super weird, set it now.
212
 * 2. If there is no published time set, also super weird, set it now.
213
 * 3. If there is no syncpublished time set, set it now.
214
 * 4. If the lifetime is not set, it will be set now.
215
 * 5. If there should be a retire time and it is not set, it will be set now.
216
 * 6. The removed time is adjusted accordingly.
217
 *
218
 * This returns when the successor key needs to be published in the zone.
219
 * A special value of 0 means there is no need for a successor.
220
 *
221
 */
222
static isc_stdtime_t
223
keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
224
0
         uint32_t lifetime, isc_stdtime_t now) {
225
0
  isc_result_t ret;
226
0
  isc_stdtime_t active, retire, pub, prepub;
227
0
  bool zsk = false, ksk = false;
228
229
0
  REQUIRE(key != NULL);
230
0
  REQUIRE(key->key != NULL);
231
232
0
  active = 0;
233
0
  pub = 0;
234
0
  retire = 0;
235
236
  /*
237
   * An active key must have publish and activate timing
238
   * metadata.
239
   */
240
0
  ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
241
0
  if (ret != ISC_R_SUCCESS) {
242
    /* Super weird, but if it happens, set it to now. */
243
0
    dst_key_settime(key->key, DST_TIME_ACTIVATE, now);
244
0
    active = now;
245
0
  }
246
0
  ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub);
247
0
  if (ret != ISC_R_SUCCESS) {
248
    /* Super weird, but if it happens, set it to now. */
249
0
    dst_key_settime(key->key, DST_TIME_PUBLISH, now);
250
0
    pub = now;
251
0
  }
252
253
  /*
254
   * To calculate phase out times ("Retired", "Removed", ...),
255
   * the key lifetime is required.
256
   */
257
0
  uint32_t klifetime = 0;
258
0
  ret = dst_key_getnum(key->key, DST_NUM_LIFETIME, &klifetime);
259
0
  if (ret != ISC_R_SUCCESS) {
260
0
    dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
261
0
    klifetime = lifetime;
262
0
  }
263
264
  /*
265
   * Calculate prepublication time.
266
   */
267
0
  prepub = dst_key_getttl(key->key) + dns_kasp_publishsafety(kasp) +
268
0
     dns_kasp_zonepropagationdelay(kasp);
269
0
  ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk);
270
0
  if (ret == ISC_R_SUCCESS && ksk) {
271
0
    isc_stdtime_t syncpub;
272
273
    /*
274
     * Set PublishCDS if not set.
275
     */
276
0
    ret = dst_key_gettime(key->key, DST_TIME_SYNCPUBLISH, &syncpub);
277
0
    if (ret != ISC_R_SUCCESS) {
278
0
      uint32_t tag;
279
0
      isc_stdtime_t syncpub1, syncpub2;
280
281
0
      syncpub1 = pub + prepub;
282
0
      syncpub2 = 0;
283
0
      ret = dst_key_getnum(key->key, DST_NUM_PREDECESSOR,
284
0
               &tag);
285
0
      if (ret != ISC_R_SUCCESS) {
286
        /*
287
         * No predecessor, wait for zone to be
288
         * completely signed.
289
         */
290
0
        dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp,
291
0
                       true);
292
0
        syncpub2 = pub + ttlsig +
293
0
             dns_kasp_zonepropagationdelay(kasp);
294
0
      }
295
296
0
      syncpub = ISC_MAX(syncpub1, syncpub2);
297
0
      dst_key_settime(key->key, DST_TIME_SYNCPUBLISH,
298
0
          syncpub);
299
0
      if (klifetime > 0) {
300
0
        dst_key_settime(key->key, DST_TIME_SYNCDELETE,
301
0
            syncpub + klifetime);
302
0
      }
303
0
    }
304
0
  }
305
306
  /*
307
   * Not sure what to do when dst_key_getbool() fails here.  Extending
308
   * the prepublication time anyway is arguably the safest thing to do,
309
   * so ignore the result code.
310
   */
311
0
  (void)dst_key_getbool(key->key, DST_BOOL_ZSK, &zsk);
312
313
0
  ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
314
0
  if (ret != ISC_R_SUCCESS) {
315
0
    if (klifetime == 0) {
316
      /*
317
       * No inactive time and no lifetime,
318
       * so no need to start a rollover.
319
       */
320
0
      return 0;
321
0
    }
322
323
0
    if (ckd_add(&retire, active, klifetime)) {
324
0
      log_key_overflow(key->key, "retire");
325
0
      retire = UINT32_MAX;
326
0
    }
327
0
    dst_key_settime(key->key, DST_TIME_INACTIVE, retire);
328
0
  }
329
330
  /*
331
   * Update remove time.
332
   */
333
0
  keymgr_settime_remove(key, kasp);
334
335
  /*
336
   * Publish successor 'prepub' time before the 'retire' time of 'key'.
337
   */
338
0
  if (prepub > retire) {
339
    /* We should have already prepublished the new key. */
340
0
    return now;
341
0
  }
342
0
  return retire - prepub;
343
0
}
344
345
static void
346
keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, uint8_t opts,
347
0
      isc_stdtime_t now) {
348
0
  char keystr[DST_KEY_FORMATSIZE];
349
0
  isc_result_t ret;
350
0
  isc_stdtime_t retire;
351
0
  dst_key_state_t s;
352
0
  bool ksk = false, zsk = false;
353
354
0
  REQUIRE(key != NULL);
355
0
  REQUIRE(key->key != NULL);
356
357
0
  dst_key_format(key->key, keystr, sizeof(keystr));
358
359
0
  ret = dst_key_getstate(key->key, DST_KEY_GOAL, &s);
360
0
  INSIST(ret == ISC_R_SUCCESS);
361
362
0
  if (dns_kasp_manualmode(kasp) &&
363
0
      (opts & DNS_KEYMGRATTR_FORCESTEP) == 0 && s != HIDDEN)
364
0
  {
365
0
    isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
366
0
            ISC_LOG_INFO,
367
0
            "keymgr-manual-mode: block retire DNSKEY "
368
0
            "%s (%s)",
369
0
            keystr, keymgr_keyrole(key->key));
370
0
    return;
371
0
  } else {
372
    /* This key wants to retire and hide in a corner. */
373
0
    isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
374
0
            ISC_LOG_INFO, "keymgr: retire DNSKEY %s (%s)",
375
0
            keystr, keymgr_keyrole(key->key));
376
377
0
    dst_key_setstate(key->key, DST_KEY_GOAL, HIDDEN);
378
0
  }
379
380
  /*
381
   * This key may not have key states set yet. Pretend as if they are
382
   * in the OMNIPRESENT state.
383
   */
384
0
  ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
385
0
  if (ret != ISC_R_SUCCESS || (retire > now)) {
386
0
    dst_key_settime(key->key, DST_TIME_INACTIVE, now);
387
0
  }
388
0
  keymgr_settime_remove(key, kasp);
389
390
0
  if (dst_key_getstate(key->key, DST_KEY_DNSKEY, &s) != ISC_R_SUCCESS) {
391
0
    dst_key_setstate(key->key, DST_KEY_DNSKEY, OMNIPRESENT);
392
0
    dst_key_settime(key->key, DST_TIME_DNSKEY, now);
393
0
  }
394
395
0
  ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk);
396
0
  if (ret == ISC_R_SUCCESS && ksk) {
397
0
    if (dst_key_getstate(key->key, DST_KEY_KRRSIG, &s) !=
398
0
        ISC_R_SUCCESS)
399
0
    {
400
0
      dst_key_setstate(key->key, DST_KEY_KRRSIG, OMNIPRESENT);
401
0
      dst_key_settime(key->key, DST_TIME_KRRSIG, now);
402
0
    }
403
0
    if (dst_key_getstate(key->key, DST_KEY_DS, &s) != ISC_R_SUCCESS)
404
0
    {
405
0
      dst_key_setstate(key->key, DST_KEY_DS, OMNIPRESENT);
406
0
      dst_key_settime(key->key, DST_TIME_DS, now);
407
0
    }
408
0
  }
409
0
  ret = dst_key_getbool(key->key, DST_BOOL_ZSK, &zsk);
410
0
  if (ret == ISC_R_SUCCESS && zsk) {
411
0
    if (dst_key_getstate(key->key, DST_KEY_ZRRSIG, &s) !=
412
0
        ISC_R_SUCCESS)
413
0
    {
414
0
      dst_key_setstate(key->key, DST_KEY_ZRRSIG, OMNIPRESENT);
415
0
      dst_key_settime(key->key, DST_TIME_ZRRSIG, now);
416
0
    }
417
0
  }
418
0
}
419
420
/* Update lifetime and retire and remove time accordingly. */
421
static void
422
keymgr_key_update_lifetime(dns_dnsseckey_t *key, dns_kasp_t *kasp,
423
0
         isc_stdtime_t now, uint32_t lifetime) {
424
0
  uint32_t l;
425
0
  dst_key_state_t g = HIDDEN;
426
0
  isc_result_t r;
427
428
0
  (void)dst_key_getstate(key->key, DST_KEY_GOAL, &g);
429
0
  r = dst_key_getnum(key->key, DST_NUM_LIFETIME, &l);
430
  /* Initialize lifetime. */
431
0
  if (r != ISC_R_SUCCESS) {
432
0
    dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
433
0
    l = lifetime - 1;
434
0
  }
435
  /* Skip keys that are still hidden or already retiring. */
436
0
  if (g != OMNIPRESENT) {
437
0
    return;
438
0
  }
439
  /* Update lifetime and timing metadata. */
440
0
  if (l != lifetime) {
441
0
    dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
442
0
    if (lifetime > 0) {
443
0
      uint32_t a = now;
444
0
      uint32_t inactive;
445
0
      (void)dst_key_gettime(key->key, DST_TIME_ACTIVATE, &a);
446
0
      if (ckd_add(&inactive, a, lifetime)) {
447
0
        log_key_overflow(key->key, "inactive");
448
0
        inactive = UINT32_MAX;
449
0
      }
450
0
      dst_key_settime(key->key, DST_TIME_INACTIVE, inactive);
451
0
      keymgr_settime_remove(key, kasp);
452
0
    } else {
453
0
      dst_key_unsettime(key->key, DST_TIME_INACTIVE);
454
0
      dst_key_unsettime(key->key, DST_TIME_DELETE);
455
0
      dst_key_unsettime(key->key, DST_TIME_SYNCDELETE);
456
0
    }
457
0
  }
458
0
}
459
460
static bool
461
keymgr_keyid_conflict(dst_key_t *newkey, uint16_t min, uint16_t max,
462
0
          dns_dnsseckeylist_t *keys) {
463
0
  uint16_t id = dst_key_id(newkey);
464
0
  uint32_t rid = dst_key_rid(newkey);
465
0
  uint32_t alg = dst_key_alg(newkey);
466
467
0
  if (id < min || id > max) {
468
0
    return true;
469
0
  }
470
0
  if (rid < min || rid > max) {
471
0
    return true;
472
0
  }
473
474
0
  ISC_LIST_FOREACH(*keys, dkey, link) {
475
0
    if (dst_key_alg(dkey->key) != alg) {
476
0
      continue;
477
0
    }
478
0
    if (dst_key_id(dkey->key) == id ||
479
0
        dst_key_rid(dkey->key) == id ||
480
0
        dst_key_id(dkey->key) == rid ||
481
0
        dst_key_rid(dkey->key) == rid)
482
0
    {
483
0
      return true;
484
0
    }
485
0
  }
486
0
  return false;
487
0
}
488
489
/*
490
 * Create a new key for 'origin' given the kasp key configuration 'kkey'.
491
 * This will check for key id collisions with keys in 'keylist'.
492
 * The created key will be stored in 'dst_key'.
493
 *
494
 */
495
static isc_result_t
496
keymgr_createkey(dns_kasp_key_t *kkey, const dns_name_t *origin,
497
     dns_kasp_t *kasp, dns_rdataclass_t rdclass, isc_mem_t *mctx,
498
     const char *keydir, dns_dnsseckeylist_t *keylist,
499
     isc_stdtime_t now, dns_dnsseckeylist_t *newkeys,
500
0
     dst_key_t **dst_key) {
501
0
  isc_result_t result = ISC_R_SUCCESS;
502
0
  bool conflict = false;
503
0
  int flags = DNS_KEYOWNER_ZONE;
504
0
  dst_key_t *newkey = NULL;
505
0
  uint32_t alg = dns_kasp_key_algorithm(kkey);
506
0
  dns_keystore_t *keystore = dns_kasp_key_keystore(kkey);
507
0
  const char *dir = NULL;
508
0
  int size = dns_kasp_key_size(kkey);
509
0
  dns_dnsseckeylist_t keykeys;
510
511
0
  ISC_LIST_INIT(keykeys);
512
513
0
  if (dns_kasp_key_ksk(kkey)) {
514
0
    flags |= DNS_KEYFLAG_KSK;
515
0
  }
516
517
  /*
518
   * We also need to check against K* files for KEYs.
519
   */
520
0
  result = dns_dnssec_findmatchingkeys(origin, NULL, keydir, NULL, now,
521
0
               true, mctx, &keykeys);
522
0
  if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
523
0
    goto failure;
524
0
  }
525
526
0
  do {
527
0
    if (keystore == NULL) {
528
0
      RETERR(dst_key_generate(origin, alg, size, 0, flags,
529
0
            DNS_KEYPROTO_DNSSEC, rdclass,
530
0
            NULL, mctx, &newkey, NULL));
531
0
    } else {
532
0
      RETERR(dns_keystore_keygen(
533
0
        keystore, origin, dns_kasp_getname(kasp),
534
0
        rdclass, mctx, alg, size, flags, &newkey));
535
0
    }
536
537
    /* Key collision? */
538
0
    conflict = keymgr_keyid_conflict(newkey, kkey->tag_min,
539
0
             kkey->tag_max, keylist);
540
0
    if (!conflict) {
541
0
      conflict = keymgr_keyid_conflict(
542
0
        newkey, kkey->tag_min, kkey->tag_max, &keykeys);
543
0
    }
544
0
    if (!conflict) {
545
0
      conflict = keymgr_keyid_conflict(
546
0
        newkey, kkey->tag_min, kkey->tag_max, newkeys);
547
0
    }
548
0
    if (conflict) {
549
      /* Try again. */
550
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
551
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
552
0
              "keymgr: key collision id %d",
553
0
              dst_key_id(newkey));
554
0
      dst_key_free(&newkey);
555
0
    }
556
0
  } while (conflict);
557
558
0
  INSIST(!conflict);
559
0
  dst_key_setnum(newkey, DST_NUM_LIFETIME, dns_kasp_key_lifetime(kkey));
560
0
  dst_key_setbool(newkey, DST_BOOL_KSK, dns_kasp_key_ksk(kkey));
561
0
  dst_key_setbool(newkey, DST_BOOL_ZSK, dns_kasp_key_zsk(kkey));
562
563
0
  dir = dns_keystore_directory(keystore, keydir);
564
0
  if (dir != NULL) {
565
0
    dst_key_setdirectory(newkey, dir);
566
0
  }
567
0
  *dst_key = newkey;
568
0
  result = ISC_R_SUCCESS;
569
570
0
failure:
571
0
  while (!ISC_LIST_EMPTY(keykeys)) {
572
0
    dns_dnsseckey_t *key = ISC_LIST_HEAD(keykeys);
573
0
    ISC_LIST_UNLINK(keykeys, key, link);
574
0
    dns_dnsseckey_destroy(mctx, &key);
575
0
  }
576
0
  return result;
577
0
}
578
579
/*
580
 * Return the desired state for this record 'type'.  The desired state depends
581
 * on whether the key wants to be active, or wants to retire.  This implements
582
 * the edges of our state machine:
583
 *
584
 *            ---->  OMNIPRESENT  ----
585
 *            |                      |
586
 *            |                     \|/
587
 *
588
 *        RUMOURED     <---->   UNRETENTIVE
589
 *
590
 *           /|\                     |
591
 *            |                      |
592
 *            ----     HIDDEN    <----
593
 *
594
 * A key that wants to be active eventually wants to have its record types
595
 * in the OMNIPRESENT state (that is, all resolvers that know about these
596
 * type of records know about these records specifically).
597
 *
598
 * A key that wants to be retired eventually wants to have its record types
599
 * in the HIDDEN state (that is, all resolvers that know about these type
600
 * of records specifically don't know about these records).
601
 *
602
 */
603
static dst_key_state_t
604
0
keymgr_desiredstate(dns_dnsseckey_t *key, dst_key_state_t state) {
605
0
  dst_key_state_t goal;
606
607
0
  if (dst_key_getstate(key->key, DST_KEY_GOAL, &goal) != ISC_R_SUCCESS) {
608
    /* No goal? No movement. */
609
0
    return state;
610
0
  }
611
612
0
  if (goal == HIDDEN) {
613
0
    switch (state) {
614
0
    case RUMOURED:
615
0
    case OMNIPRESENT:
616
0
      return UNRETENTIVE;
617
0
    case HIDDEN:
618
0
    case UNRETENTIVE:
619
0
      return HIDDEN;
620
0
    default:
621
0
      return state;
622
0
    }
623
0
  } else if (goal == OMNIPRESENT) {
624
0
    switch (state) {
625
0
    case RUMOURED:
626
0
    case OMNIPRESENT:
627
0
      return OMNIPRESENT;
628
0
    case HIDDEN:
629
0
    case UNRETENTIVE:
630
0
      return RUMOURED;
631
0
    default:
632
0
      return state;
633
0
    }
634
0
  }
635
636
  /* Unknown goal. */
637
0
  return state;
638
0
}
639
640
/*
641
 * Check if 'key' matches specific 'states'.
642
 * A state in 'states' that is NA matches any state.
643
 * A state in 'states' that is HIDDEN also matches if the state is not set.
644
 * If 'next_state' is set (not NA), we are pretending as if record 'type' of
645
 * 'subject' key already transitioned to the 'next state'.
646
 *
647
 */
648
static bool
649
keymgr_key_match_state(const dst_key_t *key, const dst_key_t *subject, int type,
650
           dst_key_state_t next_state,
651
0
           dst_key_state_t states[NUM_KEYSTATES]) {
652
0
  REQUIRE(key != NULL);
653
654
0
  for (int i = 0; i < NUM_KEYSTATES; i++) {
655
0
    dst_key_state_t state;
656
0
    if (states[i] == NA) {
657
0
      continue;
658
0
    }
659
0
    if (next_state != NA && i == type &&
660
0
        dst_key_alg(key) == dst_key_alg(subject) &&
661
0
        dst_key_id(key) == dst_key_id(subject))
662
0
    {
663
      /* Check next state rather than current state. */
664
0
      state = next_state;
665
0
    } else if (dst_key_getstate(key, i, &state) != ISC_R_SUCCESS) {
666
      /* This is fine only if expected state is HIDDEN. */
667
0
      if (states[i] != HIDDEN) {
668
0
        return false;
669
0
      }
670
0
      continue;
671
0
    }
672
0
    if (state != states[i]) {
673
0
      return false;
674
0
    }
675
0
  }
676
  /* Match. */
677
0
  return true;
678
0
}
679
680
/*
681
 * Key d directly depends on k if d is the direct predecessor of k.
682
 */
683
static bool
684
0
keymgr_direct_dep(dst_key_t *d, dst_key_t *k) {
685
0
  uint32_t s, p;
686
687
0
  if (dst_key_getnum(d, DST_NUM_SUCCESSOR, &s) != ISC_R_SUCCESS) {
688
0
    return false;
689
0
  }
690
0
  if (dst_key_getnum(k, DST_NUM_PREDECESSOR, &p) != ISC_R_SUCCESS) {
691
0
    return false;
692
0
  }
693
0
  return dst_key_id(d) == p && dst_key_id(k) == s;
694
0
}
695
696
/*
697
 * Determine which key (if any) has a dependency on k.
698
 */
699
static bool
700
0
keymgr_dep(dst_key_t *k, dns_dnsseckeylist_t *keyring, uint32_t *dep) {
701
0
  ISC_LIST_FOREACH(*keyring, d, link) {
702
    /*
703
     * Check if k is a direct successor of d, e.g. d depends on k.
704
     */
705
0
    if (keymgr_direct_dep(d->key, k)) {
706
0
      dst_key_state_t hidden[NUM_KEYSTATES] = {
707
0
        HIDDEN, HIDDEN, HIDDEN, HIDDEN
708
0
      };
709
0
      if (keymgr_key_match_state(d->key, k, NA, NA, hidden)) {
710
0
        continue;
711
0
      }
712
713
0
      SET_IF_NOT_NULL(dep, dst_key_id(d->key));
714
0
      return true;
715
0
    }
716
0
  }
717
0
  return false;
718
0
}
719
720
/*
721
 * Check if a 'z' is a successor of 'x'.
722
 * This implements Equation(2) of "Flexible and Robust Key Rollover".
723
 */
724
static bool
725
keymgr_key_is_successor(dst_key_t *x, dst_key_t *z, dst_key_t *key, int type,
726
      dst_key_state_t next_state,
727
0
      dns_dnsseckeylist_t *keyring) {
728
0
  uint32_t dep_x;
729
0
  uint32_t dep_z;
730
731
  /*
732
   * The successor relation requires that the predecessor key must not
733
   * have any other keys relying on it. In other words, there must be
734
   * nothing depending on x.
735
   */
736
0
  if (keymgr_dep(x, keyring, &dep_x)) {
737
0
    return false;
738
0
  }
739
740
  /*
741
   * If there is no keys relying on key z, then z is not a successor.
742
   */
743
0
  if (!keymgr_dep(z, keyring, &dep_z)) {
744
0
    return false;
745
0
  }
746
747
  /*
748
   * x depends on z, thus key z is a direct successor of key x.
749
   */
750
0
  if (dst_key_id(x) == dep_z) {
751
0
    return true;
752
0
  }
753
754
  /*
755
   * It is possible to roll keys faster than the time required to finish
756
   * the rollover procedure. For example, consider the keys x, y, z.
757
   * Key x is currently published and is going to be replaced by y. The
758
   * DNSKEY for x is removed from the zone and at the same moment the
759
   * DNSKEY for y is introduced. Key y is a direct dependency for key x
760
   * and is therefore the successor of x. However, before the new DNSKEY
761
   * has been propagated, key z will replace key y. The DNSKEY for y is
762
   * removed and moves into the same state as key x. Key y now directly
763
   * depends on key z, and key z will be a new successor key for x.
764
   */
765
0
  dst_key_state_t zst[NUM_KEYSTATES] = { NA, NA, NA, NA };
766
0
  for (int i = 0; i < NUM_KEYSTATES; i++) {
767
0
    dst_key_state_t state;
768
0
    if (dst_key_getstate(z, i, &state) != ISC_R_SUCCESS) {
769
0
      continue;
770
0
    }
771
0
    zst[i] = state;
772
0
  }
773
774
0
  ISC_LIST_FOREACH(*keyring, y, link) {
775
0
    if (dst_key_id(y->key) == dst_key_id(z)) {
776
0
      continue;
777
0
    }
778
779
0
    if (dst_key_id(y->key) != dep_z) {
780
0
      continue;
781
0
    }
782
    /*
783
     * This is another key y, that depends on key z. It may be
784
     * part of the successor relation if the key states match
785
     * those of key z.
786
     */
787
788
0
    if (keymgr_key_match_state(y->key, key, type, next_state, zst))
789
0
    {
790
      /*
791
       * If y is a successor of x, then z is also a
792
       * successor of x.
793
       */
794
0
      return keymgr_key_is_successor(x, y->key, key, type,
795
0
                   next_state, keyring);
796
0
    }
797
0
  }
798
799
0
  return false;
800
0
}
801
802
/*
803
 * Check if a key exists in 'keyring' that matches 'states'.
804
 *
805
 * If 'match_algorithms', the key must also match the algorithm of 'key'.
806
 * If 'next_state' is not NA, we are actually looking for a key as if
807
 *   'key' already transitioned to the next state.
808
 * If 'check_successor', we also want to make sure there is a successor
809
 *   relationship with the found key that matches 'states2'.
810
 */
811
static bool
812
keymgr_key_exists_with_state(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
813
           int type, dst_key_state_t next_state,
814
           dst_key_state_t states[NUM_KEYSTATES],
815
           dst_key_state_t states2[NUM_KEYSTATES],
816
0
           bool check_successor, bool match_algorithms) {
817
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
818
0
    if (match_algorithms &&
819
0
        (dst_key_alg(dkey->key) != dst_key_alg(key->key)))
820
0
    {
821
0
      continue;
822
0
    }
823
824
0
    if (!keymgr_key_match_state(dkey->key, key->key, type,
825
0
              next_state, states))
826
0
    {
827
0
      continue;
828
0
    }
829
830
    /* Found a match. */
831
0
    if (!check_successor) {
832
0
      return true;
833
0
    }
834
835
    /*
836
     * We have to make sure that the key we are checking, also
837
     * has a successor relationship with another key.
838
     */
839
0
    ISC_LIST_FOREACH(*keyring, skey, link) {
840
0
      if (skey == dkey) {
841
0
        continue;
842
0
      }
843
844
0
      if (!keymgr_key_match_state(skey->key, key->key, type,
845
0
                next_state, states2))
846
0
      {
847
0
        continue;
848
0
      }
849
850
      /*
851
       * Found a possible successor, check.
852
       */
853
0
      if (keymgr_key_is_successor(dkey->key, skey->key,
854
0
                key->key, type, next_state,
855
0
                keyring))
856
0
      {
857
0
        return true;
858
0
      }
859
0
    }
860
0
  }
861
  /* No match. */
862
0
  return false;
863
0
}
864
865
/*
866
 * Check if a key has a successor.
867
 */
868
static bool
869
keymgr_key_has_successor(dns_dnsseckey_t *predecessor,
870
0
       dns_dnsseckeylist_t *keyring) {
871
0
  ISC_LIST_FOREACH(*keyring, successor, link) {
872
0
    if (keymgr_direct_dep(predecessor->key, successor->key)) {
873
0
      return true;
874
0
    }
875
0
  }
876
0
  return false;
877
0
}
878
879
/*
880
 * Check if all keys have their DS hidden.  If not, then there must be at
881
 * least one key with an OMNIPRESENT DNSKEY.
882
 *
883
 * If 'next_state' is not NA, we are actually looking for a key as if
884
 *   'key' already transitioned to the next state.
885
 * If 'match_algorithms', only consider keys with same algorithm of 'key'.
886
 *
887
 */
888
static bool
889
keymgr_ds_hidden_or_chained(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
890
          int type, dst_key_state_t next_state,
891
0
          bool match_algorithms, bool must_be_hidden) {
892
  /* (3e) */
893
0
  dst_key_state_t dnskey_chained[NUM_KEYSTATES] = { OMNIPRESENT, NA,
894
0
                OMNIPRESENT, NA };
895
0
  dst_key_state_t ds_hidden[NUM_KEYSTATES] = { NA, NA, NA, HIDDEN };
896
  /* successor n/a */
897
0
  dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA };
898
899
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
900
0
    if (match_algorithms &&
901
0
        (dst_key_alg(dkey->key) != dst_key_alg(key->key)))
902
0
    {
903
0
      continue;
904
0
    }
905
906
0
    if (keymgr_key_match_state(dkey->key, key->key, type,
907
0
             next_state, ds_hidden))
908
0
    {
909
      /* This key has its DS hidden. */
910
0
      continue;
911
0
    }
912
913
0
    if (must_be_hidden) {
914
0
      return false;
915
0
    }
916
917
    /*
918
     * This key does not have its DS hidden. There must be at
919
     * least one key with the same algorithm that provides a
920
     * chain of trust (can be this key).
921
     */
922
0
    if (keymgr_key_match_state(dkey->key, key->key, type,
923
0
             next_state, dnskey_chained))
924
0
    {
925
      /* This DNSKEY and KRRSIG are OMNIPRESENT. */
926
0
      continue;
927
0
    }
928
929
    /*
930
     * Perhaps another key provides a chain of trust.
931
     */
932
0
    dnskey_chained[DST_KEY_DS] = OMNIPRESENT;
933
0
    if (!keymgr_key_exists_with_state(keyring, key, type,
934
0
              next_state, dnskey_chained,
935
0
              na, false, match_algorithms))
936
0
    {
937
      /* There is no chain of trust. */
938
0
      return false;
939
0
    }
940
0
  }
941
  /* All good. */
942
0
  return true;
943
0
}
944
945
/*
946
 * Check if all keys have their DNSKEY hidden.  If not, then there must be at
947
 * least one key with an OMNIPRESENT ZRRSIG.
948
 *
949
 * If 'next_state' is not NA, we are actually looking for a key as if
950
 *   'key' already transitioned to the next state.
951
 * If 'match_algorithms', only consider keys with same algorithm of 'key'.
952
 *
953
 */
954
static bool
955
keymgr_dnskey_hidden_or_chained(dns_dnsseckeylist_t *keyring,
956
        dns_dnsseckey_t *key, int type,
957
        dst_key_state_t next_state,
958
0
        bool match_algorithms) {
959
  /* (3i) */
960
0
  dst_key_state_t rrsig_chained[NUM_KEYSTATES] = { OMNIPRESENT,
961
0
               OMNIPRESENT, NA, NA };
962
0
  dst_key_state_t dnskey_hidden[NUM_KEYSTATES] = { HIDDEN, NA, NA, NA };
963
  /* successor n/a */
964
0
  dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA };
965
966
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
967
0
    if (match_algorithms &&
968
0
        (dst_key_alg(dkey->key) != dst_key_alg(key->key)))
969
0
    {
970
0
      continue;
971
0
    }
972
973
0
    if (keymgr_key_match_state(dkey->key, key->key, type,
974
0
             next_state, dnskey_hidden))
975
0
    {
976
      /* This key has its DNSKEY hidden. */
977
0
      continue;
978
0
    }
979
980
    /*
981
     * This key does not have its DNSKEY hidden. There must be at
982
     * least one key with the same algorithm that has its RRSIG
983
     * records OMNIPRESENT.
984
     */
985
0
    (void)dst_key_getstate(dkey->key, DST_KEY_DNSKEY,
986
0
               &rrsig_chained[DST_KEY_DNSKEY]);
987
0
    if (!keymgr_key_exists_with_state(keyring, key, type,
988
0
              next_state, rrsig_chained, na,
989
0
              false, match_algorithms))
990
0
    {
991
      /* There is no chain of trust. */
992
0
      return false;
993
0
    }
994
0
  }
995
  /* All good. */
996
0
  return true;
997
0
}
998
999
/*
1000
 * Check for existence of DS.
1001
 *
1002
 */
1003
static bool
1004
keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
1005
0
         dst_key_state_t next_state, uint8_t opts) {
1006
  /* (3a) */
1007
0
  dst_key_state_t states[2][NUM_KEYSTATES] = {
1008
    /* DNSKEY, ZRRSIG, KRRSIG, DS */
1009
0
    { NA, NA, NA, OMNIPRESENT }, /* DS present */
1010
0
    { NA, NA, NA, RUMOURED }     /* DS introducing */
1011
0
  };
1012
  /* successor n/a */
1013
0
  dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA };
1014
1015
  /*
1016
   * Equation (3a):
1017
   * There is a key with the DS in either RUMOURD or OMNIPRESENT state.
1018
   */
1019
0
  return keymgr_key_exists_with_state(keyring, key, type, next_state,
1020
0
              states[0], na, false, false) ||
1021
0
         keymgr_key_exists_with_state(keyring, key, type, next_state,
1022
0
              states[1], na, false, false) ||
1023
0
         ((opts & DNS_KEYMGRATTR_S2I) != 0 &&
1024
0
    keymgr_key_exists_with_state(keyring, key, type, next_state, na,
1025
0
               na, false, false));
1026
0
}
1027
1028
/*
1029
 * Check for existence of DNSKEY, or at least a good DNSKEY state.
1030
 * See equations what are good DNSKEY states.
1031
 *
1032
 */
1033
static bool
1034
keymgr_have_dnskey(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
1035
0
       dst_key_state_t next_state) {
1036
0
  dst_key_state_t states[9][NUM_KEYSTATES] = {
1037
    /* DNSKEY,     ZRRSIG, KRRSIG,      DS */
1038
0
    { OMNIPRESENT, NA, OMNIPRESENT, OMNIPRESENT }, /* (3b) */
1039
1040
0
    { OMNIPRESENT, NA, OMNIPRESENT, UNRETENTIVE }, /* (3c)p */
1041
0
    { OMNIPRESENT, NA, OMNIPRESENT, RUMOURED },    /* (3c)s */
1042
1043
0
    { UNRETENTIVE, NA, UNRETENTIVE, OMNIPRESENT }, /* (3d)p */
1044
0
    { OMNIPRESENT, NA, UNRETENTIVE, OMNIPRESENT }, /* (3d)p */
1045
0
    { UNRETENTIVE, NA, OMNIPRESENT, OMNIPRESENT }, /* (3d)p */
1046
0
    { RUMOURED, NA, RUMOURED, OMNIPRESENT },       /* (3d)s */
1047
0
    { OMNIPRESENT, NA, RUMOURED, OMNIPRESENT },    /* (3d)s */
1048
0
    { RUMOURED, NA, OMNIPRESENT, OMNIPRESENT },    /* (3d)s */
1049
0
  };
1050
  /* successor n/a */
1051
0
  dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA };
1052
1053
0
  return
1054
    /*
1055
     * Equation (3b):
1056
     * There is a key with the same algorithm with its DNSKEY,
1057
     * KRRSIG and DS records in OMNIPRESENT state.
1058
     */
1059
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1060
0
               states[0], na, false, true) ||
1061
    /*
1062
     * Equation (3c):
1063
     * There are two or more keys with an OMNIPRESENT DNSKEY and
1064
     * the DS records get swapped.  These keys must be in a
1065
     * successor relation.
1066
     */
1067
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1068
0
               states[1], states[2], true,
1069
0
               true) ||
1070
    /*
1071
     * Equation (3d):
1072
     * There are two or more keys with an OMNIPRESENT DS and
1073
     * the DNSKEY records and its KRRSIG records get swapped.
1074
     * These keys must be in a successor relation.  Since the
1075
     * state for DNSKEY and KRRSIG move independently, we have
1076
     * to check all combinations for DNSKEY and KRRSIG in
1077
     * OMNIPRESENT/UNRETENTIVE state for the predecessor, and
1078
     * OMNIPRESENT/RUMOURED state for the successor.
1079
     */
1080
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1081
0
               states[3], states[6], true,
1082
0
               true) ||
1083
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1084
0
               states[3], states[7], true,
1085
0
               true) ||
1086
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1087
0
               states[3], states[8], true,
1088
0
               true) ||
1089
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1090
0
               states[4], states[6], true,
1091
0
               true) ||
1092
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1093
0
               states[4], states[7], true,
1094
0
               true) ||
1095
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1096
0
               states[4], states[8], true,
1097
0
               true) ||
1098
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1099
0
               states[5], states[6], true,
1100
0
               true) ||
1101
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1102
0
               states[5], states[7], true,
1103
0
               true) ||
1104
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1105
0
               states[5], states[8], true,
1106
0
               true) ||
1107
    /*
1108
     * Equation (3e):
1109
     * The key may be in any state as long as all keys have their
1110
     * DS HIDDEN, or when their DS is not HIDDEN, there must be a
1111
     * key with its DS in the same state and its DNSKEY omnipresent.
1112
     * In other words, if a DS record for the same algorithm is
1113
     * is still available to some validators, there must be a
1114
     * chain of trust for those validators.
1115
     */
1116
0
    keymgr_ds_hidden_or_chained(keyring, key, type, next_state,
1117
0
              true, false);
1118
0
}
1119
1120
/*
1121
 * Check for existence of RRSIG (zsk), or a good RRSIG state.
1122
 * See equations what are good RRSIG states.
1123
 *
1124
 */
1125
static bool
1126
keymgr_have_rrsig(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
1127
0
      dst_key_state_t next_state) {
1128
0
  dst_key_state_t states[11][NUM_KEYSTATES] = {
1129
    /* DNSKEY,     ZRRSIG,      KRRSIG, DS */
1130
0
    { OMNIPRESENT, OMNIPRESENT, NA, NA }, /* (3f) */
1131
0
    { UNRETENTIVE, OMNIPRESENT, NA, NA }, /* (3g)p */
1132
0
    { RUMOURED, OMNIPRESENT, NA, NA },    /* (3g)s */
1133
0
    { OMNIPRESENT, UNRETENTIVE, NA, NA }, /* (3h)p */
1134
0
    { OMNIPRESENT, RUMOURED, NA, NA },    /* (3h)s */
1135
0
  };
1136
  /* successor n/a */
1137
0
  dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA };
1138
1139
0
  return
1140
    /*
1141
     * If all DS records are hidden than this rule can be ignored.
1142
     */
1143
0
    keymgr_ds_hidden_or_chained(keyring, key, type, next_state,
1144
0
              true, true) ||
1145
    /*
1146
     * Equation (3f):
1147
     * There is a key with the same algorithm with its DNSKEY and
1148
     * ZRRSIG records in OMNIPRESENT state.
1149
     */
1150
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1151
0
               states[0], na, false, true) ||
1152
    /*
1153
     * Equation (3g):
1154
     * There are two or more keys with OMNIPRESENT ZRRSIG
1155
     * records and the DNSKEY records get swapped.  These keys
1156
     * must be in a successor relation.
1157
     */
1158
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1159
0
               states[1], states[2], true,
1160
0
               true) ||
1161
    /*
1162
     * Equation (3h):
1163
     * There are two or more keys with an OMNIPRESENT DNSKEY
1164
     * and the ZRRSIG records get swapped.  These keys must be in
1165
     * a successor relation.
1166
     */
1167
0
    keymgr_key_exists_with_state(keyring, key, type, next_state,
1168
0
               states[3], states[4], true,
1169
0
               true) ||
1170
    /*
1171
     * Equation (3i):
1172
     * If no DNSKEYs are published, the state of the signatures is
1173
     * irrelevant.  In case a DNSKEY is published however, there
1174
     * must be a path that can be validated from there.
1175
     */
1176
0
    keymgr_dnskey_hidden_or_chained(keyring, key, type, next_state,
1177
0
            true);
1178
0
}
1179
1180
/*
1181
 * Check if a transition in the state machine is allowed by the policy.
1182
 * This means when we do rollovers, we want to follow the rules of the
1183
 * 1. Pre-publish rollover method (in case of a ZSK)
1184
 *    - First introduce the DNSKEY record.
1185
 *    - Only if the DNSKEY record is OMNIPRESENT, introduce ZRRSIG records.
1186
 *
1187
 * 2. Double-KSK rollover method (in case of a KSK)
1188
 *    - First introduce the DNSKEY record, as well as the KRRSIG records.
1189
 *    - Only if the DNSKEY record is OMNIPRESENT, suggest to introduce the DS.
1190
 */
1191
static bool
1192
keymgr_policy_approval(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
1193
0
           int type, dst_key_state_t next) {
1194
0
  dst_key_state_t dnskeystate = HIDDEN;
1195
0
  dst_key_state_t ksk_present[NUM_KEYSTATES] = { OMNIPRESENT, NA,
1196
0
                   OMNIPRESENT,
1197
0
                   OMNIPRESENT };
1198
0
  dst_key_state_t ds_rumoured[NUM_KEYSTATES] = { OMNIPRESENT, NA,
1199
0
                   OMNIPRESENT, RUMOURED };
1200
0
  dst_key_state_t ds_retired[NUM_KEYSTATES] = { OMNIPRESENT, NA,
1201
0
                  OMNIPRESENT,
1202
0
                  UNRETENTIVE };
1203
0
  dst_key_state_t ksk_rumoured[NUM_KEYSTATES] = { RUMOURED, NA, NA,
1204
0
              OMNIPRESENT };
1205
0
  dst_key_state_t ksk_retired[NUM_KEYSTATES] = { UNRETENTIVE, NA, NA,
1206
0
                   OMNIPRESENT };
1207
  /* successor n/a */
1208
0
  dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA };
1209
1210
0
  if (next != RUMOURED) {
1211
    /*
1212
     * Local policy only adds an extra barrier on transitions to
1213
     * the RUMOURED state.
1214
     */
1215
0
    return true;
1216
0
  }
1217
1218
0
  switch (type) {
1219
0
  case DST_KEY_DNSKEY:
1220
    /* No restrictions. */
1221
0
    return true;
1222
0
  case DST_KEY_ZRRSIG:
1223
    /* Make sure the DNSKEY record is OMNIPRESENT. */
1224
0
    (void)dst_key_getstate(key->key, DST_KEY_DNSKEY, &dnskeystate);
1225
0
    if (dnskeystate == OMNIPRESENT) {
1226
0
      return true;
1227
0
    }
1228
    /*
1229
     * Or are we introducing a new key for this algorithm? Because
1230
     * in that case allow publishing the RRSIG records before the
1231
     * DNSKEY.
1232
     */
1233
0
    return !(keymgr_key_exists_with_state(keyring, key, type, next,
1234
0
                  ksk_present, na, false,
1235
0
                  true) ||
1236
0
       keymgr_key_exists_with_state(keyring, key, type, next,
1237
0
                  ds_retired, ds_rumoured,
1238
0
                  true, true) ||
1239
0
       keymgr_key_exists_with_state(keyring, key, type, next,
1240
0
                  ksk_retired, ksk_rumoured,
1241
0
                  true, true));
1242
0
  case DST_KEY_KRRSIG:
1243
    /* Only introduce if the DNSKEY is also introduced. */
1244
0
    (void)dst_key_getstate(key->key, DST_KEY_DNSKEY, &dnskeystate);
1245
0
    return dnskeystate != HIDDEN;
1246
0
  case DST_KEY_DS:
1247
    /* Make sure the DNSKEY record is OMNIPRESENT. */
1248
0
    (void)dst_key_getstate(key->key, DST_KEY_DNSKEY, &dnskeystate);
1249
0
    return dnskeystate == OMNIPRESENT;
1250
0
  default:
1251
0
    return false;
1252
0
  }
1253
0
}
1254
1255
/*
1256
 * Check if a transition in the state machine is DNSSEC safe.
1257
 * This implements Equation(1) of "Flexible and Robust Key Rollover".
1258
 *
1259
 */
1260
static bool
1261
keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
1262
0
        int type, dst_key_state_t next_state, uint8_t opts) {
1263
  /* Debug logging. */
1264
0
  if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
1265
0
    bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b;
1266
0
    char keystr[DST_KEY_FORMATSIZE];
1267
0
    dst_key_format(key->key, keystr, sizeof(keystr));
1268
0
    rule1a = keymgr_have_ds(keyring, key, type, NA, opts);
1269
0
    rule1b = keymgr_have_ds(keyring, key, type, next_state, opts);
1270
0
    rule2a = keymgr_have_dnskey(keyring, key, type, NA);
1271
0
    rule2b = keymgr_have_dnskey(keyring, key, type, next_state);
1272
0
    rule3a = keymgr_have_rrsig(keyring, key, type, NA);
1273
0
    rule3b = keymgr_have_rrsig(keyring, key, type, next_state);
1274
0
    isc_log_write(
1275
0
      DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
1276
0
      ISC_LOG_DEBUG(1),
1277
0
      "keymgr: dnssec evaluation of %s %s record %s: "
1278
0
      "rule1=(~%s or %s) rule2=(~%s or %s) "
1279
0
      "rule3=(~%s or %s)",
1280
0
      keymgr_keyrole(key->key), keystr, keystatetags[type],
1281
0
      rule1a ? "true" : "false", rule1b ? "true" : "false",
1282
0
      rule2a ? "true" : "false", rule2b ? "true" : "false",
1283
0
      rule3a ? "true" : "false", rule3b ? "true" : "false");
1284
0
  }
1285
1286
0
  return
1287
    /*
1288
     * Rule 1: There must be a DS at all times.
1289
     * First check the current situation: if the rule check fails,
1290
     * we allow the transition to attempt to move us out of the
1291
     * invalid state.  If the rule check passes, also check if
1292
     * the next state is also still a valid situation.
1293
     */
1294
0
    (!keymgr_have_ds(keyring, key, type, NA, opts) ||
1295
0
     keymgr_have_ds(keyring, key, type, next_state, opts)) &&
1296
    /*
1297
     * Rule 2: There must be a DNSKEY at all times.  Again, first
1298
     * check the current situation, then assess the next state.
1299
     */
1300
0
    (!keymgr_have_dnskey(keyring, key, type, NA) ||
1301
0
     keymgr_have_dnskey(keyring, key, type, next_state)) &&
1302
    /*
1303
     * Rule 3: There must be RRSIG records at all times. Again,
1304
     * first check the current situation, then assess the next
1305
     * state.
1306
     */
1307
0
    (!keymgr_have_rrsig(keyring, key, type, NA) ||
1308
0
     keymgr_have_rrsig(keyring, key, type, next_state));
1309
0
}
1310
1311
/*
1312
 * Calculate the time when it is safe to do the next transition.
1313
 *
1314
 */
1315
static void
1316
keymgr_transition_time(dns_dnsseckey_t *key, int type,
1317
           dst_key_state_t next_state, dns_kasp_t *kasp,
1318
0
           isc_stdtime_t now, isc_stdtime_t *when) {
1319
0
  isc_result_t ret;
1320
0
  isc_stdtime_t lastchange, dstime, sigtime, nexttime = now;
1321
0
  dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
1322
0
  uint32_t dsstate, sigstate, signdelay = 0;
1323
1324
  /*
1325
   * No need to wait if we move things into an uncertain state.
1326
   */
1327
0
  if (next_state == RUMOURED || next_state == UNRETENTIVE) {
1328
0
    *when = now;
1329
0
    return;
1330
0
  }
1331
1332
0
  ret = dst_key_gettime(key->key, keystatetimes[type], &lastchange);
1333
0
  if (ret != ISC_R_SUCCESS) {
1334
    /* No last change, for safety purposes let's set it to now. */
1335
0
    dst_key_settime(key->key, keystatetimes[type], now);
1336
0
    lastchange = now;
1337
0
  }
1338
1339
0
  switch (type) {
1340
0
  case DST_KEY_DNSKEY:
1341
0
  case DST_KEY_KRRSIG:
1342
0
    switch (next_state) {
1343
0
    case OMNIPRESENT:
1344
      /*
1345
       * RFC 7583: The publication interval (Ipub) is the
1346
       * amount of time that must elapse after the
1347
       * publication of a DNSKEY (plus RRSIG (KSK)) before
1348
       * it can be assumed that any resolvers that have the
1349
       * relevant RRset cached have a copy of the new
1350
       * information.  This is the sum of the propagation
1351
       * delay (Dprp) and the DNSKEY TTL (TTLkey).  This
1352
       * translates to zone-propagation-delay + dnskey-ttl.
1353
       * We will also add the publish-safety interval.
1354
       */
1355
0
      nexttime = lastchange + dst_key_getttl(key->key) +
1356
0
           dns_kasp_zonepropagationdelay(kasp) +
1357
0
           dns_kasp_publishsafety(kasp);
1358
0
      break;
1359
0
    case HIDDEN:
1360
      /*
1361
       * Same as OMNIPRESENT but without the publish-safety
1362
       * interval.
1363
       */
1364
0
      nexttime = lastchange + dst_key_getttl(key->key) +
1365
0
           dns_kasp_zonepropagationdelay(kasp);
1366
0
      break;
1367
0
    default:
1368
0
      nexttime = now;
1369
0
      break;
1370
0
    }
1371
0
    break;
1372
0
  case DST_KEY_ZRRSIG:
1373
0
    switch (next_state) {
1374
0
    case OMNIPRESENT:
1375
0
    case HIDDEN:
1376
      /* Was there a full sign? */
1377
0
      sigstate = (next_state == HIDDEN) ? DST_TIME_SIGDELETE
1378
0
                : DST_TIME_SIGPUBLISH;
1379
0
      ret = dst_key_gettime(key->key, sigstate, &sigtime);
1380
0
      if (ret == ISC_R_SUCCESS && sigtime <= now) {
1381
0
        signdelay = 0;
1382
0
      } else {
1383
0
        sigtime = lastchange;
1384
0
        signdelay = dns_kasp_signdelay(kasp);
1385
0
      }
1386
1387
      /*
1388
       * RFC 7583: The retire interval (Iret) is the amount
1389
       * of time that must elapse after a DNSKEY or
1390
       * associated data enters the retire state for any
1391
       * dependent information (RRSIG ZSK) to be purged from
1392
       * validating resolver caches.  This is defined as:
1393
       *
1394
       *     Iret = Dsgn + Dprp + TTLsig
1395
       *
1396
       * Where Dsgn is the Dsgn is the delay needed to
1397
       * ensure that all existing RRsets have been re-signed
1398
       * with the new key, Dprp is the propagation delay and
1399
       * TTLsig is the maximum TTL of all zone RRSIG
1400
       * records.  This translates to:
1401
       *
1402
       *     Dsgn + zone-propagation-delay + max-zone-ttl.
1403
       */
1404
0
      nexttime = sigtime + ttlsig +
1405
0
           dns_kasp_zonepropagationdelay(kasp);
1406
      /*
1407
       * Only add the sign delay Dsgn and retire-safety if
1408
       * there is an actual predecessor or successor key.
1409
       */
1410
0
      uint32_t tag;
1411
0
      ret = dst_key_getnum(key->key, DST_NUM_PREDECESSOR,
1412
0
               &tag);
1413
0
      if (ret != ISC_R_SUCCESS) {
1414
0
        ret = dst_key_getnum(key->key,
1415
0
                 DST_NUM_SUCCESSOR, &tag);
1416
0
      }
1417
0
      if (ret == ISC_R_SUCCESS) {
1418
0
        nexttime += signdelay +
1419
0
              dns_kasp_retiresafety(kasp);
1420
0
      }
1421
0
      break;
1422
0
    default:
1423
0
      nexttime = now;
1424
0
      break;
1425
0
    }
1426
0
    break;
1427
0
  case DST_KEY_DS:
1428
0
    switch (next_state) {
1429
    /*
1430
     * RFC 7583: The successor DS record is published in
1431
     * the parent zone and after the registration delay
1432
     * (Dreg), the time taken after the DS record has been
1433
     * submitted to the parent zone manager for it to be
1434
     * placed in the zone.  Key N (the predecessor) must
1435
     * remain in the zone until any caches that contain a
1436
     * copy of the DS RRset have a copy containing the new
1437
     * DS record. This interval is the retire interval
1438
     * (Iret), given by:
1439
     *
1440
     *      Iret = DprpP + TTLds
1441
     *
1442
     * This translates to:
1443
     *
1444
     *      parent-propagation-delay + parent-ds-ttl.
1445
     */
1446
0
    case OMNIPRESENT:
1447
0
    case HIDDEN:
1448
      /* Make sure DS has been seen in/withdrawn from the
1449
       * parent. */
1450
0
      dsstate = next_state == HIDDEN ? DST_TIME_DSDELETE
1451
0
                   : DST_TIME_DSPUBLISH;
1452
0
      ret = dst_key_gettime(key->key, dsstate, &dstime);
1453
0
      if (ret != ISC_R_SUCCESS || dstime > now) {
1454
        /* Not yet, try again in an hour. */
1455
0
        nexttime = now + 3600;
1456
0
      } else {
1457
0
        nexttime =
1458
0
          dstime + dns_kasp_dsttl(kasp) +
1459
0
          dns_kasp_parentpropagationdelay(kasp);
1460
        /*
1461
         * Only add the retire-safety if there is an
1462
         * actual predecessor or successor key.
1463
         */
1464
0
        uint32_t tag;
1465
0
        ret = dst_key_getnum(key->key,
1466
0
                 DST_NUM_PREDECESSOR, &tag);
1467
0
        if (ret != ISC_R_SUCCESS) {
1468
0
          ret = dst_key_getnum(key->key,
1469
0
                   DST_NUM_SUCCESSOR,
1470
0
                   &tag);
1471
0
        }
1472
0
        if (ret == ISC_R_SUCCESS) {
1473
0
          nexttime += dns_kasp_retiresafety(kasp);
1474
0
        }
1475
0
      }
1476
0
      break;
1477
0
    default:
1478
0
      nexttime = now;
1479
0
      break;
1480
0
    }
1481
0
    break;
1482
0
  default:
1483
0
    UNREACHABLE();
1484
0
    break;
1485
0
  }
1486
1487
0
  *when = nexttime;
1488
0
}
1489
1490
/*
1491
 * Update keys.
1492
 * This implements Algorithm (1) of "Flexible and Robust Key Rollover".
1493
 *
1494
 */
1495
static isc_result_t
1496
keymgr_update(dns_dnsseckeylist_t *keyring, dns_kasp_t *kasp, isc_stdtime_t now,
1497
0
        isc_stdtime_t *nexttime, uint8_t opts) {
1498
0
  isc_result_t result = DNS_R_UNCHANGED;
1499
0
  bool changed;
1500
0
  bool force = ((opts & DNS_KEYMGRATTR_FORCESTEP) != 0);
1501
1502
  /* Repeat until nothing changed. */
1503
0
transition:
1504
0
  changed = false;
1505
1506
  /* For all keys in the zone. */
1507
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
1508
0
    char keystr[DST_KEY_FORMATSIZE];
1509
0
    dst_key_format(dkey->key, keystr, sizeof(keystr));
1510
1511
0
    if (dkey->purge) {
1512
      /* Skip purged keys. */
1513
0
      continue;
1514
0
    }
1515
1516
    /* For all records related to this key. */
1517
0
    for (int i = 0; i < NUM_KEYSTATES; i++) {
1518
0
      isc_result_t ret;
1519
0
      isc_stdtime_t when;
1520
0
      dst_key_state_t state, next_state;
1521
1522
0
      ret = dst_key_getstate(dkey->key, i, &state);
1523
0
      if (ret == ISC_R_NOTFOUND) {
1524
        /*
1525
         * This record type is not applicable for this
1526
         * key, continue to the next record type.
1527
         */
1528
0
        continue;
1529
0
      }
1530
1531
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1532
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1533
0
              "keymgr: examine %s %s type %s "
1534
0
              "in state %s",
1535
0
              keymgr_keyrole(dkey->key), keystr,
1536
0
              keystatetags[i], keystatestrings[state]);
1537
1538
      /* Get the desired next state. */
1539
0
      next_state = keymgr_desiredstate(dkey, state);
1540
0
      if (state == next_state) {
1541
        /*
1542
         * This record is in a stable state.
1543
         * No change needed, continue with the next
1544
         * record type.
1545
         */
1546
0
        isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1547
0
                DNS_LOGMODULE_DNSSEC,
1548
0
                ISC_LOG_DEBUG(1),
1549
0
                "keymgr: %s %s type %s in "
1550
0
                "stable state %s",
1551
0
                keymgr_keyrole(dkey->key), keystr,
1552
0
                keystatetags[i],
1553
0
                keystatestrings[state]);
1554
0
        continue;
1555
0
      }
1556
1557
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1558
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1559
0
              "keymgr: can we transition %s %s type %s "
1560
0
              "state %s to state %s?",
1561
0
              keymgr_keyrole(dkey->key), keystr,
1562
0
              keystatetags[i], keystatestrings[state],
1563
0
              keystatestrings[next_state]);
1564
1565
      /* Is the transition allowed according to policy? */
1566
0
      if (!keymgr_policy_approval(keyring, dkey, i,
1567
0
                next_state))
1568
0
      {
1569
        /* No, please respect rollover methods. */
1570
0
        isc_log_write(
1571
0
          DNS_LOGCATEGORY_DNSSEC,
1572
0
          DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1573
0
          "keymgr: policy says no to %s %s type "
1574
0
          "%s "
1575
0
          "state %s to state %s",
1576
0
          keymgr_keyrole(dkey->key), keystr,
1577
0
          keystatetags[i], keystatestrings[state],
1578
0
          keystatestrings[next_state]);
1579
1580
0
        continue;
1581
0
      }
1582
1583
      /* Is the transition DNSSEC safe? */
1584
0
      if (!keymgr_transition_allowed(keyring, dkey, i,
1585
0
                   next_state, opts))
1586
0
      {
1587
        /* No, this would make the zone bogus. */
1588
0
        isc_log_write(
1589
0
          DNS_LOGCATEGORY_DNSSEC,
1590
0
          DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1591
0
          "keymgr: dnssec says no to %s %s type "
1592
0
          "%s "
1593
0
          "state %s to state %s",
1594
0
          keymgr_keyrole(dkey->key), keystr,
1595
0
          keystatetags[i], keystatestrings[state],
1596
0
          keystatestrings[next_state]);
1597
0
        continue;
1598
0
      }
1599
1600
      /* Is it time to make the transition? */
1601
0
      when = now;
1602
0
      keymgr_transition_time(dkey, i, next_state, kasp, now,
1603
0
                 &when);
1604
0
      if (when > now) {
1605
        /* Not yet. */
1606
0
        isc_log_write(
1607
0
          DNS_LOGCATEGORY_DNSSEC,
1608
0
          DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1609
0
          "keymgr: time says no to %s %s type %s "
1610
0
          "state %s to state %s (wait %u "
1611
0
          "seconds)",
1612
0
          keymgr_keyrole(dkey->key), keystr,
1613
0
          keystatetags[i], keystatestrings[state],
1614
0
          keystatestrings[next_state],
1615
0
          when - now);
1616
0
        if (*nexttime == 0 || *nexttime > when) {
1617
0
          *nexttime = when;
1618
0
        }
1619
0
        continue;
1620
0
      }
1621
1622
      /*
1623
       * Are we allowed to make the transition automatically?
1624
       */
1625
0
      if (next_state != OMNIPRESENT && next_state != HIDDEN) {
1626
0
        if (dns_kasp_manualmode(kasp) && !force) {
1627
0
          isc_log_write(
1628
0
            DNS_LOGCATEGORY_DNSSEC,
1629
0
            DNS_LOGMODULE_DNSSEC,
1630
0
            ISC_LOG_INFO,
1631
0
            "keymgr-manual-mode: block "
1632
0
            "transition "
1633
0
            "%s %s type %s "
1634
0
            "state %s to state %s",
1635
0
            keymgr_keyrole(dkey->key),
1636
0
            keystr, keystatetags[i],
1637
0
            keystatestrings[state],
1638
0
            keystatestrings[next_state]);
1639
0
          continue;
1640
0
        }
1641
0
      }
1642
1643
      /* It is safe to make the transition. */
1644
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1645
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1646
0
              "keymgr: transition %s %s type %s "
1647
0
              "state %s to state %s!",
1648
0
              keymgr_keyrole(dkey->key), keystr,
1649
0
              keystatetags[i], keystatestrings[state],
1650
0
              keystatestrings[next_state]);
1651
1652
0
      dst_key_setstate(dkey->key, i, next_state);
1653
0
      dst_key_settime(dkey->key, keystatetimes[i], now);
1654
0
      INSIST(dst_key_ismodified(dkey->key));
1655
0
      changed = true;
1656
0
    }
1657
0
  }
1658
1659
  /* We changed something, continue processing. */
1660
0
  if (changed) {
1661
0
    result = ISC_R_SUCCESS;
1662
    /* No longer force for the next run */
1663
0
    force = false;
1664
0
    goto transition;
1665
0
  }
1666
1667
0
  return result;
1668
0
}
1669
1670
void
1671
dns_keymgr_key_init(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now,
1672
0
        bool csk) {
1673
0
  bool ksk, zsk;
1674
0
  isc_result_t ret;
1675
0
  isc_stdtime_t active = 0, pub = 0, syncpub = 0, retire = 0, remove = 0;
1676
0
  dst_key_state_t dnskey_state = HIDDEN;
1677
0
  dst_key_state_t ds_state = HIDDEN;
1678
0
  dst_key_state_t zrrsig_state = HIDDEN;
1679
0
  dst_key_state_t goal_state = HIDDEN;
1680
1681
0
  REQUIRE(key != NULL);
1682
0
  REQUIRE(key->key != NULL);
1683
1684
  /* Initialize role. */
1685
0
  ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk);
1686
0
  if (ret != ISC_R_SUCCESS) {
1687
0
    ksk = ((dst_key_flags(key->key) & DNS_KEYFLAG_KSK) != 0);
1688
0
    dst_key_setbool(key->key, DST_BOOL_KSK, ksk || csk);
1689
0
  }
1690
0
  ret = dst_key_getbool(key->key, DST_BOOL_ZSK, &zsk);
1691
0
  if (ret != ISC_R_SUCCESS) {
1692
0
    zsk = ((dst_key_flags(key->key) & DNS_KEYFLAG_KSK) == 0);
1693
0
    dst_key_setbool(key->key, DST_BOOL_ZSK, zsk || csk);
1694
0
  }
1695
1696
  /* Get time metadata. */
1697
0
  ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
1698
0
  if (active <= now && ret == ISC_R_SUCCESS) {
1699
0
    dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
1700
0
    ttlsig += dns_kasp_zonepropagationdelay(kasp);
1701
0
    if ((active + ttlsig) <= now) {
1702
0
      zrrsig_state = OMNIPRESENT;
1703
0
    } else {
1704
0
      zrrsig_state = RUMOURED;
1705
0
    }
1706
0
    goal_state = OMNIPRESENT;
1707
0
  }
1708
0
  ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub);
1709
0
  if (pub <= now && ret == ISC_R_SUCCESS) {
1710
0
    dns_ttl_t key_ttl = dst_key_getttl(key->key);
1711
0
    key_ttl += dns_kasp_zonepropagationdelay(kasp);
1712
0
    if ((pub + key_ttl) <= now) {
1713
0
      dnskey_state = OMNIPRESENT;
1714
0
    } else {
1715
0
      dnskey_state = RUMOURED;
1716
0
    }
1717
0
    goal_state = OMNIPRESENT;
1718
0
  }
1719
0
  ret = dst_key_gettime(key->key, DST_TIME_SYNCPUBLISH, &syncpub);
1720
0
  if (syncpub <= now && ret == ISC_R_SUCCESS) {
1721
0
    dns_ttl_t ds_ttl = dns_kasp_dsttl(kasp);
1722
0
    ds_ttl += dns_kasp_parentpropagationdelay(kasp);
1723
0
    if ((syncpub + ds_ttl) <= now) {
1724
0
      ds_state = OMNIPRESENT;
1725
0
    } else {
1726
0
      ds_state = RUMOURED;
1727
0
    }
1728
0
    goal_state = OMNIPRESENT;
1729
0
  }
1730
0
  ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
1731
0
  if (retire <= now && ret == ISC_R_SUCCESS) {
1732
0
    dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
1733
0
    ttlsig += dns_kasp_zonepropagationdelay(kasp);
1734
0
    if ((retire + ttlsig) <= now) {
1735
0
      zrrsig_state = HIDDEN;
1736
0
    } else {
1737
0
      zrrsig_state = UNRETENTIVE;
1738
0
    }
1739
0
    ds_state = UNRETENTIVE;
1740
0
    goal_state = HIDDEN;
1741
0
  }
1742
0
  ret = dst_key_gettime(key->key, DST_TIME_DELETE, &remove);
1743
0
  if (remove <= now && ret == ISC_R_SUCCESS) {
1744
0
    dns_ttl_t key_ttl = dst_key_getttl(key->key);
1745
0
    key_ttl += dns_kasp_zonepropagationdelay(kasp);
1746
0
    if ((remove + key_ttl) <= now) {
1747
0
      dnskey_state = HIDDEN;
1748
0
    } else {
1749
0
      dnskey_state = UNRETENTIVE;
1750
0
    }
1751
0
    zrrsig_state = HIDDEN;
1752
0
    ds_state = HIDDEN;
1753
0
    goal_state = HIDDEN;
1754
0
  }
1755
1756
  /* Set goal if not already set. */
1757
0
  if (dst_key_getstate(key->key, DST_KEY_GOAL, &goal_state) !=
1758
0
      ISC_R_SUCCESS)
1759
0
  {
1760
0
    dst_key_setstate(key->key, DST_KEY_GOAL, goal_state);
1761
0
  }
1762
1763
  /* Set key states for all keys that do not have them. */
1764
0
  INITIALIZE_STATE(key->key, DST_KEY_DNSKEY, DST_TIME_DNSKEY,
1765
0
       dnskey_state, now);
1766
0
  if (ksk || csk) {
1767
0
    INITIALIZE_STATE(key->key, DST_KEY_KRRSIG, DST_TIME_KRRSIG,
1768
0
         dnskey_state, now);
1769
0
    INITIALIZE_STATE(key->key, DST_KEY_DS, DST_TIME_DS, ds_state,
1770
0
         now);
1771
0
  }
1772
0
  if (zsk || csk) {
1773
0
    INITIALIZE_STATE(key->key, DST_KEY_ZRRSIG, DST_TIME_ZRRSIG,
1774
0
         zrrsig_state, now);
1775
0
  }
1776
0
}
1777
1778
static isc_result_t
1779
keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
1780
        dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *newkeys,
1781
        const dns_name_t *origin, dns_rdataclass_t rdclass,
1782
        dns_kasp_t *kasp, const char *keydir, uint32_t lifetime,
1783
        uint8_t opts, isc_stdtime_t now, isc_stdtime_t *nexttime,
1784
0
        isc_mem_t *mctx) {
1785
0
  char keystr[DST_KEY_FORMATSIZE];
1786
0
  char namestr[DNS_NAME_FORMATSIZE];
1787
0
  isc_stdtime_t retire = 0, active = 0, prepub = 0;
1788
0
  dns_dnsseckey_t *new_key = NULL;
1789
0
  dst_key_t *dst_key = NULL;
1790
0
  bool keycreated = false;
1791
1792
  /* Do we need to create a successor for the active key? */
1793
0
  if (active_key != NULL) {
1794
0
    if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
1795
0
      dst_key_format(active_key->key, keystr, sizeof(keystr));
1796
0
      isc_log_write(
1797
0
        DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
1798
0
        ISC_LOG_DEBUG(1),
1799
0
        "keymgr: DNSKEY %s (%s) is active in policy %s",
1800
0
        keystr, keymgr_keyrole(active_key->key),
1801
0
        dns_kasp_getname(kasp));
1802
0
    }
1803
1804
    /*
1805
     * Calculate when the successor needs to be published
1806
     * in the zone.
1807
     */
1808
0
    prepub = keymgr_prepublication_time(active_key, kasp, lifetime,
1809
0
                now);
1810
0
    if (prepub > now) {
1811
0
      if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
1812
0
        dst_key_format(active_key->key, keystr,
1813
0
                 sizeof(keystr));
1814
0
        isc_log_write(
1815
0
          DNS_LOGCATEGORY_DNSSEC,
1816
0
          DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1817
0
          "keymgr: new successor needed for "
1818
0
          "DNSKEY %s (%s) (policy %s) in %u "
1819
0
          "seconds",
1820
0
          keystr, keymgr_keyrole(active_key->key),
1821
0
          dns_kasp_getname(kasp), prepub - now);
1822
0
      }
1823
0
    }
1824
0
    if (prepub == 0 || prepub > now) {
1825
      /* No need to start rollover now. */
1826
0
      if (*nexttime == 0 || prepub < *nexttime) {
1827
0
        if (prepub > 0) {
1828
0
          *nexttime = prepub;
1829
0
        }
1830
0
      }
1831
0
      return ISC_R_SUCCESS;
1832
0
    }
1833
1834
0
    if (keymgr_key_has_successor(active_key, keyring)) {
1835
      /* Key already has successor. */
1836
0
      if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
1837
0
        dst_key_format(active_key->key, keystr,
1838
0
                 sizeof(keystr));
1839
0
        isc_log_write(
1840
0
          DNS_LOGCATEGORY_DNSSEC,
1841
0
          DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1842
0
          "keymgr: key DNSKEY %s (%s) (policy "
1843
0
          "%s) already has successor",
1844
0
          keystr, keymgr_keyrole(active_key->key),
1845
0
          dns_kasp_getname(kasp));
1846
0
      }
1847
0
      return ISC_R_SUCCESS;
1848
0
    }
1849
1850
0
    if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
1851
0
      dst_key_format(active_key->key, keystr, sizeof(keystr));
1852
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1853
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
1854
0
              "keymgr: need successor for DNSKEY %s "
1855
0
              "(%s) (policy %s)",
1856
0
              keystr, keymgr_keyrole(active_key->key),
1857
0
              dns_kasp_getname(kasp));
1858
0
    }
1859
1860
    /*
1861
     * If rollover is not allowed, warn.
1862
     */
1863
0
    if ((opts & DNS_KEYMGRATTR_NOROLL) != 0) {
1864
0
      dst_key_format(active_key->key, keystr, sizeof(keystr));
1865
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1866
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
1867
0
              "keymgr: DNSKEY %s (%s) is offline in "
1868
0
              "policy %s, cannot start rollover",
1869
0
              keystr, keymgr_keyrole(active_key->key),
1870
0
              dns_kasp_getname(kasp));
1871
0
      return ISC_R_SUCCESS;
1872
0
    }
1873
0
  } else if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
1874
0
    dns_name_format(origin, namestr, sizeof(namestr));
1875
0
    isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
1876
0
            ISC_LOG_DEBUG(1),
1877
0
            "keymgr: no active key found for %s (policy %s)",
1878
0
            namestr, dns_kasp_getname(kasp));
1879
0
  }
1880
1881
  /* It is time to do key rollover, we need a new key. */
1882
1883
  /*
1884
   * Check if there is a key available in pool because keys
1885
   * may have been pregenerated with dnssec-keygen.
1886
   */
1887
0
  ISC_LIST_FOREACH(*keyring, candidate, link) {
1888
0
    if (dns_kasp_key_match(kaspkey, candidate) &&
1889
0
        dst_key_is_unused(candidate->key))
1890
0
    {
1891
      /* Found a candidate in keyring. */
1892
0
      new_key = candidate;
1893
0
      break;
1894
0
    }
1895
0
  }
1896
1897
0
  if (dns_kasp_manualmode(kasp) && (opts & DNS_KEYMGRATTR_FORCESTEP) == 0)
1898
0
  {
1899
0
    if (active_key != NULL && new_key != NULL) {
1900
0
      char keystr2[DST_KEY_FORMATSIZE];
1901
0
      dst_key_format(active_key->key, keystr, sizeof(keystr));
1902
0
      dst_key_format(new_key->key, keystr2, sizeof(keystr2));
1903
0
      dns_name_format(origin, namestr, sizeof(namestr));
1904
0
      isc_log_write(
1905
0
        DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
1906
0
        ISC_LOG_INFO,
1907
0
        "keymgr-manual-mode: block %s rollover for key "
1908
0
        "%s to key %s (policy %s)",
1909
0
        keymgr_keyrole(active_key->key), keystr,
1910
0
        keystr2, dns_kasp_getname(kasp));
1911
0
    } else if (active_key != NULL) {
1912
0
      dst_key_format(active_key->key, keystr, sizeof(keystr));
1913
0
      dns_name_format(origin, namestr, sizeof(namestr));
1914
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1915
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
1916
0
              "keymgr-manual-mode: block %s rollover "
1917
0
              "for key %s (policy %s)",
1918
0
              keymgr_keyrole(active_key->key), keystr,
1919
0
              dns_kasp_getname(kasp));
1920
0
    } else if (new_key != NULL) {
1921
0
      dst_key_format(new_key->key, keystr, sizeof(keystr));
1922
0
      dns_name_format(origin, namestr, sizeof(namestr));
1923
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1924
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
1925
0
              "keymgr-manual-mode: block %s "
1926
0
              "introduction %s (policy %s)",
1927
0
              keymgr_keyrole(new_key->key), keystr,
1928
0
              dns_kasp_getname(kasp));
1929
0
    } else {
1930
0
      dns_name_format(origin, namestr, sizeof(namestr));
1931
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
1932
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
1933
0
              "keymgr-manual-mode: block new key "
1934
0
              "generation for zone %s (policy %s)",
1935
0
              namestr, dns_kasp_getname(kasp));
1936
0
    }
1937
0
    return ISC_R_SUCCESS;
1938
0
  }
1939
1940
0
  if (new_key == NULL) {
1941
    /* No key available in keyring, create a new one. */
1942
0
    bool csk = (dns_kasp_key_ksk(kaspkey) &&
1943
0
          dns_kasp_key_zsk(kaspkey));
1944
1945
0
    isc_result_t result = keymgr_createkey(
1946
0
      kaspkey, origin, kasp, rdclass, mctx, keydir, keyring,
1947
0
      now, newkeys, &dst_key);
1948
0
    if (result != ISC_R_SUCCESS) {
1949
0
      return result;
1950
0
    }
1951
0
    dst_key_setttl(dst_key, dns_kasp_dnskeyttl(kasp));
1952
0
    dst_key_settime(dst_key, DST_TIME_CREATED, now);
1953
0
    dns_dnsseckey_create(mctx, &dst_key, &new_key);
1954
0
    dns_keymgr_key_init(new_key, kasp, now, csk);
1955
0
    keycreated = true;
1956
0
  }
1957
0
  dst_key_setnum(new_key->key, DST_NUM_LIFETIME, lifetime);
1958
1959
  /* Got a key. */
1960
0
  if (active_key == NULL) {
1961
    /*
1962
     * If there is no active key found yet for this kasp
1963
     * key configuration, immediately make this key active.
1964
     */
1965
0
    dst_key_settime(new_key->key, DST_TIME_PUBLISH, now);
1966
0
    dst_key_settime(new_key->key, DST_TIME_ACTIVATE, now);
1967
0
    dns_keymgr_settime_syncpublish(new_key->key, kasp, true);
1968
0
    active = now;
1969
0
  } else {
1970
    /*
1971
     * This is a successor.  Mark the relationship.
1972
     */
1973
0
    isc_stdtime_t created;
1974
0
    (void)dst_key_gettime(new_key->key, DST_TIME_CREATED, &created);
1975
1976
0
    dst_key_setnum(new_key->key, DST_NUM_PREDECESSOR,
1977
0
             dst_key_id(active_key->key));
1978
0
    dst_key_setnum(active_key->key, DST_NUM_SUCCESSOR,
1979
0
             dst_key_id(new_key->key));
1980
0
    (void)dst_key_gettime(active_key->key, DST_TIME_INACTIVE,
1981
0
              &retire);
1982
0
    active = retire;
1983
1984
    /*
1985
     * If prepublication time and/or retire time are
1986
     * in the past (before the new key was created), use
1987
     * creation time as published and active time,
1988
     * effectively immediately making the key active.
1989
     */
1990
0
    if (prepub < created) {
1991
0
      active += (created - prepub);
1992
0
      prepub = created;
1993
0
    }
1994
0
    if (active < created) {
1995
0
      active = created;
1996
0
    }
1997
0
    dst_key_settime(new_key->key, DST_TIME_PUBLISH, prepub);
1998
0
    dst_key_settime(new_key->key, DST_TIME_ACTIVATE, active);
1999
0
    dns_keymgr_settime_syncpublish(new_key->key, kasp, false);
2000
2001
    /*
2002
     * Retire predecessor.
2003
     */
2004
0
    dst_key_setstate(active_key->key, DST_KEY_GOAL, HIDDEN);
2005
0
  }
2006
2007
  /* This key wants to be present. */
2008
0
  dst_key_setstate(new_key->key, DST_KEY_GOAL, OMNIPRESENT);
2009
2010
  /* Do we need to set retire time? */
2011
0
  if (lifetime > 0) {
2012
0
    uint32_t inactive;
2013
2014
0
    if (ckd_add(&inactive, active, lifetime)) {
2015
0
      log_key_overflow(new_key->key, "inactive");
2016
0
      inactive = UINT32_MAX;
2017
0
    }
2018
0
    dst_key_settime(new_key->key, DST_TIME_INACTIVE, inactive);
2019
0
    keymgr_settime_remove(new_key, kasp);
2020
0
  }
2021
2022
  /* Append dnsseckey to list of new keys. */
2023
0
  dns_dnssec_get_hints(new_key, now);
2024
0
  new_key->source = dns_keysource_repository;
2025
0
  INSIST(!new_key->legacy);
2026
0
  if (keycreated) {
2027
0
    ISC_LIST_APPEND(*newkeys, new_key, link);
2028
0
  }
2029
2030
  /* Logging. */
2031
0
  dst_key_format(new_key->key, keystr, sizeof(keystr));
2032
0
  isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
2033
0
          ISC_LOG_INFO, "keymgr: DNSKEY %s (%s) %s for policy %s",
2034
0
          keystr, keymgr_keyrole(new_key->key),
2035
0
          keycreated ? "created" : "selected",
2036
0
          dns_kasp_getname(kasp));
2037
0
  return ISC_R_SUCCESS;
2038
0
}
2039
2040
bool
2041
dns_keymgr_key_may_be_purged(const dst_key_t *key, uint32_t after,
2042
0
           isc_stdtime_t now) {
2043
0
  bool ksk = false;
2044
0
  bool zsk = false;
2045
0
  dst_key_state_t hidden[NUM_KEYSTATES] = { HIDDEN, NA, NA, NA };
2046
0
  isc_stdtime_t lastchange = 0;
2047
2048
0
  char keystr[DST_KEY_FORMATSIZE];
2049
0
  dst_key_format(key, keystr, sizeof(keystr));
2050
2051
  /* If 'purge-keys' is disabled, always retain keys. */
2052
0
  if (after == 0) {
2053
0
    return false;
2054
0
  }
2055
2056
  /* Don't purge keys with goal OMNIPRESENT */
2057
0
  if (dst_key_goal(key) == OMNIPRESENT) {
2058
0
    return false;
2059
0
  }
2060
2061
  /* Don't purge unused keys. */
2062
0
  if (dst_key_is_unused(key)) {
2063
0
    return false;
2064
0
  }
2065
2066
  /* If this key is completely HIDDEN it may be purged. */
2067
0
  (void)dst_key_getbool(key, DST_BOOL_KSK, &ksk);
2068
0
  (void)dst_key_getbool(key, DST_BOOL_ZSK, &zsk);
2069
0
  if (ksk) {
2070
0
    hidden[DST_KEY_KRRSIG] = HIDDEN;
2071
0
    hidden[DST_KEY_DS] = HIDDEN;
2072
0
  }
2073
0
  if (zsk) {
2074
0
    hidden[DST_KEY_ZRRSIG] = HIDDEN;
2075
0
  }
2076
0
  if (!keymgr_key_match_state(key, key, 0, NA, hidden)) {
2077
0
    return false;
2078
0
  }
2079
2080
  /*
2081
   * Check 'purge-keys' interval. If the interval has passed since
2082
   * the last key change, it may be purged.
2083
   */
2084
0
  for (int i = 0; i < NUM_KEYSTATES; i++) {
2085
0
    isc_stdtime_t change = 0;
2086
0
    (void)dst_key_gettime(key, keystatetimes[i], &change);
2087
0
    if (change > lastchange) {
2088
0
      lastchange = change;
2089
0
    }
2090
0
  }
2091
2092
0
  return (lastchange + after) < now;
2093
0
}
2094
2095
static void
2096
0
keymgr_purge_keyfile(dst_key_t *key, int type) {
2097
0
  isc_result_t ret;
2098
0
  isc_buffer_t fileb;
2099
0
  char filename[NAME_MAX];
2100
2101
  /*
2102
   * Make the filename.
2103
   */
2104
0
  isc_buffer_init(&fileb, filename, sizeof(filename));
2105
0
  ret = dst_key_buildfilename(key, type, dst_key_directory(key), &fileb);
2106
0
  if (ret != ISC_R_SUCCESS) {
2107
0
    char keystr[DST_KEY_FORMATSIZE];
2108
0
    dst_key_format(key, keystr, sizeof(keystr));
2109
0
    isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
2110
0
            ISC_LOG_WARNING,
2111
0
            "keymgr: failed to purge DNSKEY %s (%s): cannot "
2112
0
            "build filename (%s)",
2113
0
            keystr, keymgr_keyrole(key),
2114
0
            isc_result_totext(ret));
2115
0
    return;
2116
0
  }
2117
2118
0
  if (unlink(filename) < 0) {
2119
0
    char keystr[DST_KEY_FORMATSIZE];
2120
0
    dst_key_format(key, keystr, sizeof(keystr));
2121
0
    isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
2122
0
            ISC_LOG_WARNING,
2123
0
            "keymgr: failed to purge DNSKEY %s (%s): unlink "
2124
0
            "'%s' failed",
2125
0
            keystr, keymgr_keyrole(key), filename);
2126
0
  }
2127
0
}
2128
2129
static bool
2130
0
dst_key_doublematch(dns_dnsseckey_t *key, dns_kasp_t *kasp) {
2131
0
  int matches = 0;
2132
2133
0
  ISC_LIST_FOREACH(dns_kasp_keys(kasp), kkey, link) {
2134
0
    if (dns_kasp_key_match(kkey, key)) {
2135
0
      matches++;
2136
0
    }
2137
0
  }
2138
0
  return matches > 1;
2139
0
}
2140
2141
static void
2142
0
keymgr_zrrsig(dns_dnsseckeylist_t *keyring, isc_stdtime_t now) {
2143
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
2144
0
    isc_result_t ret;
2145
0
    bool zsk = false;
2146
2147
0
    ret = dst_key_getbool(dkey->key, DST_BOOL_ZSK, &zsk);
2148
0
    if (ret == ISC_R_SUCCESS && zsk) {
2149
0
      dst_key_state_t state;
2150
0
      isc_result_t result = dst_key_getstate(
2151
0
        dkey->key, DST_KEY_ZRRSIG, &state);
2152
0
      if (result == ISC_R_SUCCESS) {
2153
0
        if (state == RUMOURED) {
2154
0
          dst_key_settime(dkey->key,
2155
0
              DST_TIME_SIGPUBLISH,
2156
0
              now);
2157
0
        } else if (state == UNRETENTIVE) {
2158
0
          dst_key_settime(dkey->key,
2159
0
              DST_TIME_SIGDELETE,
2160
0
              now);
2161
0
        }
2162
0
      }
2163
0
    }
2164
0
  }
2165
0
}
2166
2167
/*
2168
 * Examine 'keys' and match 'kasp' policy.
2169
 *
2170
 */
2171
isc_result_t
2172
dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
2173
         isc_mem_t *mctx, dns_dnsseckeylist_t *keyring,
2174
         dns_dnsseckeylist_t *dnskeys, const char *keydir,
2175
         dns_kasp_t *kasp, uint8_t opts, isc_stdtime_t now,
2176
0
         isc_stdtime_t *nexttime) {
2177
0
  isc_result_t result = DNS_R_UNCHANGED;
2178
0
  dns_dnsseckeylist_t newkeys;
2179
0
  int numkeys = 0;
2180
0
  int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
2181
0
  char keystr[DST_KEY_FORMATSIZE];
2182
2183
0
  REQUIRE(dns_name_isvalid(origin));
2184
0
  REQUIRE(mctx != NULL);
2185
0
  REQUIRE(keyring != NULL);
2186
0
  REQUIRE(DNS_KASP_VALID(kasp));
2187
2188
0
  ISC_LIST_INIT(newkeys);
2189
2190
0
  *nexttime = 0;
2191
2192
  /* Debug logging: what keys are available in the keyring? */
2193
0
  if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
2194
0
    if (ISC_LIST_EMPTY(*keyring)) {
2195
0
      char namebuf[DNS_NAME_FORMATSIZE];
2196
0
      dns_name_format(origin, namebuf, sizeof(namebuf));
2197
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
2198
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
2199
0
              "keymgr: keyring empty (zone %s policy "
2200
0
              "%s)",
2201
0
              namebuf, dns_kasp_getname(kasp));
2202
0
    }
2203
2204
0
    ISC_LIST_FOREACH(*keyring, dkey, link) {
2205
0
      dst_key_format(dkey->key, keystr, sizeof(keystr));
2206
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
2207
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
2208
0
              "keymgr: keyring: %s (policy %s)", keystr,
2209
0
              dns_kasp_getname(kasp));
2210
0
    }
2211
0
    ISC_LIST_FOREACH(*dnskeys, dkey, link) {
2212
0
      dst_key_format(dkey->key, keystr, sizeof(keystr));
2213
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
2214
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
2215
0
              "keymgr: dnskeys: %s (policy %s)", keystr,
2216
0
              dns_kasp_getname(kasp));
2217
0
    }
2218
0
  }
2219
2220
0
  ISC_LIST_FOREACH(*dnskeys, dkey, link) {
2221
0
    numkeys++;
2222
0
  }
2223
2224
  /* Do we need to remove keys? */
2225
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
2226
0
    bool found_match = false;
2227
2228
0
    dns_keymgr_key_init(dkey, kasp, now, numkeys == 1);
2229
2230
0
    ISC_LIST_FOREACH(dns_kasp_keys(kasp), kkey, link) {
2231
0
      if (dns_kasp_key_match(kkey, dkey)) {
2232
0
        found_match = true;
2233
0
        break;
2234
0
      }
2235
0
    }
2236
2237
    /* No match, so retire unwanted retire key. */
2238
0
    if (!found_match) {
2239
0
      keymgr_key_retire(dkey, kasp, opts, now);
2240
0
    }
2241
2242
    /* Check purge-keys interval. */
2243
0
    if (dns_keymgr_key_may_be_purged(dkey->key,
2244
0
             dns_kasp_purgekeys(kasp), now))
2245
0
    {
2246
0
      dst_key_format(dkey->key, keystr, sizeof(keystr));
2247
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
2248
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2249
0
              "keymgr: purge DNSKEY %s (%s) according "
2250
0
              "to policy %s",
2251
0
              keystr, keymgr_keyrole(dkey->key),
2252
0
              dns_kasp_getname(kasp));
2253
2254
0
      keymgr_purge_keyfile(dkey->key, DST_TYPE_PUBLIC);
2255
0
      keymgr_purge_keyfile(dkey->key, DST_TYPE_PRIVATE);
2256
0
      keymgr_purge_keyfile(dkey->key, DST_TYPE_STATE);
2257
0
      dkey->purge = true;
2258
0
    }
2259
0
  }
2260
2261
  /* Create keys according to the policy, if come in short. */
2262
0
  ISC_LIST_FOREACH(dns_kasp_keys(kasp), kkey, link) {
2263
0
    uint32_t lifetime = dns_kasp_key_lifetime(kkey);
2264
0
    dns_dnsseckey_t *active_key = NULL;
2265
2266
    /* Do we have keys available for this kasp key? */
2267
0
    ISC_LIST_FOREACH(*keyring, dkey, link) {
2268
0
      if (dns_kasp_key_match(kkey, dkey)) {
2269
        /* Found a match. */
2270
0
        dst_key_format(dkey->key, keystr,
2271
0
                 sizeof(keystr));
2272
0
        isc_log_write(DNS_LOGCATEGORY_DNSSEC,
2273
0
                DNS_LOGMODULE_DNSSEC,
2274
0
                ISC_LOG_DEBUG(1),
2275
0
                "keymgr: DNSKEY %s (%s) matches "
2276
0
                "policy %s",
2277
0
                keystr, keymgr_keyrole(dkey->key),
2278
0
                dns_kasp_getname(kasp));
2279
2280
        /* Update lifetime if changed. */
2281
0
        keymgr_key_update_lifetime(dkey, kasp, now,
2282
0
                 lifetime);
2283
2284
0
        if (active_key) {
2285
          /* We already have an active key that
2286
           * matches the kasp policy.
2287
           */
2288
0
          if (!dst_key_is_unused(dkey->key) &&
2289
0
              !dst_key_doublematch(dkey, kasp) &&
2290
0
              (dst_key_goal(dkey->key) ==
2291
0
               OMNIPRESENT) &&
2292
0
              !keymgr_dep(dkey->key, keyring,
2293
0
              NULL) &&
2294
0
              !keymgr_dep(active_key->key,
2295
0
              keyring, NULL))
2296
0
          {
2297
            /*
2298
             * Multiple signing keys match
2299
             * the kasp key configuration.
2300
             * Retire excess keys in use.
2301
             */
2302
0
            keymgr_key_retire(dkey, kasp,
2303
0
                  opts, now);
2304
0
          }
2305
0
          continue;
2306
0
        }
2307
2308
        /*
2309
         * Save the matched key only if it is active
2310
         * or desires to be active.
2311
         */
2312
0
        if (dst_key_goal(dkey->key) == OMNIPRESENT ||
2313
0
            dst_key_is_active(dkey->key, now))
2314
0
        {
2315
0
          active_key = dkey;
2316
0
        }
2317
0
      }
2318
0
    }
2319
2320
0
    if (active_key == NULL) {
2321
      /*
2322
       * We didn't found an active key, perhaps the .private
2323
       * key file is offline. If so, we don't want to create
2324
       * a successor key. Check if we have an appropriate
2325
       * state file.
2326
       */
2327
0
      ISC_LIST_FOREACH(*dnskeys, dnskey, link) {
2328
0
        if (dns_kasp_key_match(kkey, dnskey)) {
2329
          /* Found a match. */
2330
0
          dst_key_format(dnskey->key, keystr,
2331
0
                   sizeof(keystr));
2332
0
          isc_log_write(
2333
0
            DNS_LOGCATEGORY_DNSSEC,
2334
0
            DNS_LOGMODULE_DNSSEC,
2335
0
            ISC_LOG_DEBUG(1),
2336
0
            "keymgr: DNSKEY %s (%s) "
2337
0
            "offline, policy %s",
2338
0
            keystr,
2339
0
            keymgr_keyrole(dnskey->key),
2340
0
            dns_kasp_getname(kasp));
2341
0
          opts |= DNS_KEYMGRATTR_NOROLL;
2342
0
          active_key = dnskey;
2343
0
          break;
2344
0
        }
2345
0
      }
2346
0
    }
2347
2348
    /* See if this key requires a rollover. */
2349
0
    RETERR(keymgr_key_rollover(
2350
0
      kkey, active_key, keyring, &newkeys, origin, rdclass,
2351
0
      kasp, keydir, lifetime, opts, now, nexttime, mctx));
2352
2353
0
    opts &= ~DNS_KEYMGRATTR_NOROLL;
2354
0
  }
2355
2356
  /* Walked all kasp key configurations.  Append new keys. */
2357
0
  if (!ISC_LIST_EMPTY(newkeys)) {
2358
0
    ISC_LIST_APPENDLIST(*keyring, newkeys, link);
2359
0
  }
2360
2361
  /*
2362
   * If the policy has an empty key list, this means the zone is going
2363
   * back to unsigned.
2364
   */
2365
0
  if (dns_kasp_keylist_empty(kasp)) {
2366
0
    opts |= DNS_KEYMGRATTR_S2I;
2367
0
  }
2368
2369
  /* In case of a full sign, store ZRRSIGPublish/ZRRSIGDelete. */
2370
0
  if ((opts & DNS_KEYMGRATTR_FULLSIGN) != 0) {
2371
0
    keymgr_zrrsig(keyring, now);
2372
0
  }
2373
2374
  /* Read to update key states. */
2375
0
  isc_result_t retval = keymgr_update(keyring, kasp, now, nexttime, opts);
2376
2377
  /* Store key states and update hints. */
2378
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
2379
0
    bool modified = dst_key_ismodified(dkey->key);
2380
0
    if (dst_key_getttl(dkey->key) != dns_kasp_dnskeyttl(kasp)) {
2381
0
      dst_key_setttl(dkey->key, dns_kasp_dnskeyttl(kasp));
2382
0
      modified = true;
2383
0
      retval = ISC_R_SUCCESS;
2384
0
    }
2385
0
    if (modified && !dkey->purge) {
2386
0
      const char *directory = dst_key_directory(dkey->key);
2387
0
      if (directory == NULL) {
2388
0
        directory = ".";
2389
0
      }
2390
2391
0
      dns_dnssec_get_hints(dkey, now);
2392
0
      RETERR(dst_key_tofile(dkey->key, options, directory));
2393
0
      dst_key_setmodified(dkey->key, false);
2394
2395
0
      if (!isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
2396
0
        continue;
2397
0
      }
2398
0
      dst_key_format(dkey->key, keystr, sizeof(keystr));
2399
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
2400
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(3),
2401
0
              "keymgr: DNSKEY %s (%s) "
2402
0
              "saved to directory %s, policy %s",
2403
0
              keystr, keymgr_keyrole(dkey->key),
2404
0
              directory, dns_kasp_getname(kasp));
2405
0
    }
2406
0
    dst_key_setmodified(dkey->key, false);
2407
0
  }
2408
2409
0
  result = retval;
2410
0
failure:
2411
0
  if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
2412
0
    ISC_LIST_FOREACH(newkeys, newkey, link) {
2413
0
      ISC_LIST_UNLINK(newkeys, newkey, link);
2414
0
      INSIST(newkey->key != NULL);
2415
0
      dst_key_free(&newkey->key);
2416
0
      dns_dnsseckey_destroy(mctx, &newkey);
2417
0
    }
2418
0
  }
2419
2420
0
  if (isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
2421
0
    char namebuf[DNS_NAME_FORMATSIZE];
2422
0
    dns_name_format(origin, namebuf, sizeof(namebuf));
2423
0
    isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
2424
0
            ISC_LOG_DEBUG(3), "keymgr: %s done", namebuf);
2425
0
  }
2426
0
  return result;
2427
0
}
2428
2429
static isc_result_t
2430
keymgr_checkds(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
2431
         isc_stdtime_t now, isc_stdtime_t when, bool dspublish,
2432
0
         dns_keytag_t id, unsigned int alg, bool check_id) {
2433
0
  int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
2434
0
  const char *directory = NULL;
2435
0
  isc_result_t result;
2436
0
  dns_dnsseckey_t *ksk_key = NULL;
2437
2438
0
  REQUIRE(DNS_KASP_VALID(kasp));
2439
0
  REQUIRE(keyring != NULL);
2440
2441
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
2442
0
    isc_result_t ret;
2443
0
    bool ksk = false;
2444
2445
0
    ret = dst_key_getbool(dkey->key, DST_BOOL_KSK, &ksk);
2446
0
    if (ret == ISC_R_SUCCESS && ksk) {
2447
0
      if (check_id && dst_key_id(dkey->key) != id) {
2448
0
        continue;
2449
0
      }
2450
0
      if (alg > 0 && dst_key_alg(dkey->key) != alg) {
2451
0
        continue;
2452
0
      }
2453
2454
0
      if (ksk_key != NULL) {
2455
        /*
2456
         * Only checkds for one key at a time.
2457
         */
2458
0
        return DNS_R_TOOMANYKEYS;
2459
0
      }
2460
2461
0
      ksk_key = dkey;
2462
0
    }
2463
0
  }
2464
2465
0
  if (ksk_key == NULL) {
2466
0
    return DNS_R_NOKEYMATCH;
2467
0
  }
2468
2469
0
  if (dspublish) {
2470
0
    dst_key_state_t s;
2471
0
    dst_key_settime(ksk_key->key, DST_TIME_DSPUBLISH, when);
2472
0
    result = dst_key_getstate(ksk_key->key, DST_KEY_DS, &s);
2473
0
    if (result != ISC_R_SUCCESS || s != RUMOURED) {
2474
0
      dst_key_setstate(ksk_key->key, DST_KEY_DS, RUMOURED);
2475
0
    }
2476
0
  } else {
2477
0
    dst_key_state_t s;
2478
0
    dst_key_settime(ksk_key->key, DST_TIME_DSDELETE, when);
2479
0
    result = dst_key_getstate(ksk_key->key, DST_KEY_DS, &s);
2480
0
    if (result != ISC_R_SUCCESS || s != UNRETENTIVE) {
2481
0
      dst_key_setstate(ksk_key->key, DST_KEY_DS, UNRETENTIVE);
2482
0
    }
2483
0
  }
2484
2485
0
  if (isc_log_wouldlog(ISC_LOG_NOTICE)) {
2486
0
    char keystr[DST_KEY_FORMATSIZE];
2487
0
    char timestr[26]; /* Minimal buf as per ctime_r() spec. */
2488
2489
0
    dst_key_format(ksk_key->key, keystr, sizeof(keystr));
2490
0
    isc_stdtime_tostring(when, timestr, sizeof(timestr));
2491
0
    isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
2492
0
            ISC_LOG_NOTICE,
2493
0
            "keymgr: checkds DS for key %s seen %s at %s",
2494
0
            keystr, dspublish ? "published" : "withdrawn",
2495
0
            timestr);
2496
0
  }
2497
2498
  /* Store key state and update hints. */
2499
0
  directory = dst_key_directory(ksk_key->key);
2500
0
  if (directory == NULL) {
2501
0
    directory = ".";
2502
0
  }
2503
2504
0
  dns_dnssec_get_hints(ksk_key, now);
2505
0
  result = dst_key_tofile(ksk_key->key, options, directory);
2506
0
  if (result == ISC_R_SUCCESS) {
2507
0
    dst_key_setmodified(ksk_key->key, false);
2508
0
  }
2509
2510
0
  return result;
2511
0
}
2512
2513
isc_result_t
2514
dns_keymgr_checkds(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
2515
0
       isc_stdtime_t now, isc_stdtime_t when, bool dspublish) {
2516
0
  return keymgr_checkds(kasp, keyring, now, when, dspublish, 0, 0, false);
2517
0
}
2518
2519
isc_result_t
2520
dns_keymgr_checkds_id(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
2521
          isc_stdtime_t now, isc_stdtime_t when, bool dspublish,
2522
0
          dns_keytag_t id, unsigned int alg) {
2523
0
  return keymgr_checkds(kasp, keyring, now, when, dspublish, id, alg,
2524
0
            true);
2525
0
}
2526
2527
static isc_result_t
2528
keytime_status(dst_key_t *key, isc_stdtime_t now, isc_buffer_t *buf,
2529
0
         const char *pre, int ks, int kt) {
2530
0
  char timestr[26]; /* Minimal buf as per ctime_r() spec. */
2531
0
  isc_result_t result = ISC_R_SUCCESS;
2532
0
  isc_stdtime_t when = 0;
2533
0
  dst_key_state_t state = NA;
2534
2535
0
  RETERR(isc_buffer_printf(buf, "%s", pre));
2536
0
  (void)dst_key_getstate(key, ks, &state);
2537
0
  isc_result_t r = dst_key_gettime(key, kt, &when);
2538
0
  if (state == RUMOURED || state == OMNIPRESENT) {
2539
0
    RETERR(isc_buffer_printf(buf, "yes - since "));
2540
0
  } else if (now < when) {
2541
0
    RETERR(isc_buffer_printf(buf, "no  - scheduled "));
2542
0
  } else {
2543
0
    return isc_buffer_printf(buf, "no\n");
2544
0
  }
2545
0
  if (r == ISC_R_SUCCESS) {
2546
0
    isc_stdtime_tostring(when, timestr, sizeof(timestr));
2547
0
    RETERR(isc_buffer_printf(buf, "%s\n", timestr));
2548
0
  }
2549
2550
0
failure:
2551
0
  return result;
2552
0
}
2553
2554
static isc_result_t
2555
rollover_status(dns_dnsseckey_t *dkey, dns_kasp_t *kasp, isc_stdtime_t now,
2556
0
    isc_buffer_t *buf, bool zsk) {
2557
0
  char timestr[26]; /* Minimal buf as per ctime_r() spec. */
2558
0
  isc_result_t result = ISC_R_SUCCESS;
2559
0
  isc_stdtime_t active_time = 0;
2560
0
  dst_key_state_t state = NA, goal = NA;
2561
0
  int rrsig, active, retire;
2562
0
  dst_key_t *key = dkey->key;
2563
2564
0
  if (zsk) {
2565
0
    rrsig = DST_KEY_ZRRSIG;
2566
0
    active = DST_TIME_ACTIVATE;
2567
0
    retire = DST_TIME_INACTIVE;
2568
0
  } else {
2569
0
    rrsig = DST_KEY_KRRSIG;
2570
0
    active = DST_TIME_PUBLISH;
2571
0
    retire = DST_TIME_DELETE;
2572
0
  }
2573
2574
0
  RETERR(isc_buffer_printf(buf, "\n"));
2575
2576
0
  (void)dst_key_getstate(key, DST_KEY_GOAL, &goal);
2577
0
  (void)dst_key_getstate(key, rrsig, &state);
2578
0
  (void)dst_key_gettime(key, active, &active_time);
2579
0
  if (active_time == 0) {
2580
    // only interested in keys that were once active.
2581
0
    return ISC_R_SUCCESS;
2582
0
  }
2583
2584
0
  if (goal == HIDDEN && (state == UNRETENTIVE || state == HIDDEN)) {
2585
0
    isc_stdtime_t remove_time = 0;
2586
    // is the key removed yet?
2587
0
    state = NA;
2588
0
    (void)dst_key_getstate(key, DST_KEY_DNSKEY, &state);
2589
0
    if (state == RUMOURED || state == OMNIPRESENT) {
2590
0
      result = dst_key_gettime(key, DST_TIME_DELETE,
2591
0
             &remove_time);
2592
0
      if (result == ISC_R_SUCCESS) {
2593
0
        RETERR(isc_buffer_printf(
2594
0
          buf, "  Key is retired, will be "
2595
0
               "removed on "));
2596
0
        isc_stdtime_tostring(remove_time, timestr,
2597
0
                 sizeof(timestr));
2598
0
        RETERR(isc_buffer_printf(buf, "%s", timestr));
2599
0
      }
2600
0
    } else {
2601
0
      RETERR(isc_buffer_printf(buf, "  Key has been removed "
2602
0
                  "from the zone"));
2603
0
    }
2604
0
  } else {
2605
0
    isc_stdtime_t retire_time = 0;
2606
0
    result = dst_key_gettime(key, retire, &retire_time);
2607
0
    if (result == ISC_R_SUCCESS) {
2608
0
      if (now < retire_time) {
2609
0
        if (goal == OMNIPRESENT) {
2610
0
          RETERR(isc_buffer_printf(
2611
0
            buf, "  Next rollover "
2612
0
                 "scheduled on "));
2613
0
          retire_time = keymgr_prepublication_time(
2614
0
            dkey, kasp,
2615
0
            retire_time - active_time, now);
2616
0
        } else {
2617
0
          RETERR(isc_buffer_printf(
2618
0
            buf, "  Key will retire on "));
2619
0
        }
2620
0
      } else {
2621
0
        RETERR(isc_buffer_printf(buf, "  Rollover is "
2622
0
                    "due since "));
2623
0
      }
2624
0
      isc_stdtime_tostring(retire_time, timestr,
2625
0
               sizeof(timestr));
2626
0
      RETERR(isc_buffer_printf(buf, "%s", timestr));
2627
0
    } else {
2628
0
      RETERR(isc_buffer_printf(buf,
2629
0
             "  No rollover scheduled"));
2630
0
    }
2631
0
  }
2632
0
  RETERR(isc_buffer_printf(buf, "\n"));
2633
2634
0
failure:
2635
0
  return result;
2636
0
}
2637
2638
static isc_result_t
2639
0
keystate_status(dst_key_t *key, isc_buffer_t *buf, const char *pre, int ks) {
2640
0
  dst_key_state_t state = NA;
2641
0
  isc_result_t result = ISC_R_SUCCESS;
2642
2643
0
  (void)dst_key_getstate(key, ks, &state);
2644
0
  switch (state) {
2645
0
  case HIDDEN:
2646
0
    RETERR(isc_buffer_printf(buf, "  - %shidden\n", pre));
2647
0
    break;
2648
0
  case RUMOURED:
2649
0
    RETERR(isc_buffer_printf(buf, "  - %srumoured\n", pre));
2650
0
    break;
2651
0
  case OMNIPRESENT:
2652
0
    RETERR(isc_buffer_printf(buf, "  - %somnipresent\n", pre));
2653
0
    break;
2654
0
  case UNRETENTIVE:
2655
0
    RETERR(isc_buffer_printf(buf, "  - %sunretentive\n", pre));
2656
0
    break;
2657
0
  case NA:
2658
0
  default:
2659
    /* print nothing */
2660
0
    break;
2661
0
  }
2662
2663
0
failure:
2664
0
  return result;
2665
0
}
2666
2667
isc_result_t
2668
dns_keymgr_status(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
2669
0
      isc_stdtime_t now, char *out, size_t out_len) {
2670
0
  isc_buffer_t buf;
2671
0
  isc_result_t result = ISC_R_SUCCESS;
2672
0
  char timestr[26]; /* Minimal buf as per ctime_r() spec. */
2673
2674
0
  REQUIRE(DNS_KASP_VALID(kasp));
2675
0
  REQUIRE(keyring != NULL);
2676
0
  REQUIRE(out != NULL);
2677
2678
0
  isc_buffer_init(&buf, out, out_len);
2679
2680
  // policy name
2681
0
  RETERR(isc_buffer_printf(&buf, "dnssec-policy: %s\n",
2682
0
         dns_kasp_getname(kasp)));
2683
0
  RETERR(isc_buffer_printf(&buf, "current time:  "));
2684
0
  isc_stdtime_tostring(now, timestr, sizeof(timestr));
2685
0
  RETERR(isc_buffer_printf(&buf, "%s\n", timestr));
2686
2687
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
2688
0
    char algstr[DNS_NAME_FORMATSIZE];
2689
0
    bool ksk = false, zsk = false;
2690
2691
0
    if (dst_key_is_unused(dkey->key)) {
2692
0
      continue;
2693
0
    }
2694
2695
    // key data
2696
0
    dns_secalg_format((dns_secalg_t)dst_key_alg(dkey->key), algstr,
2697
0
          sizeof(algstr));
2698
0
    RETERR(isc_buffer_printf(&buf, "\nkey: %d (%s), %s\n",
2699
0
           dst_key_id(dkey->key), algstr,
2700
0
           keymgr_keyrole(dkey->key)));
2701
2702
    // publish status
2703
0
    RETERR(keytime_status(dkey->key, now, &buf,
2704
0
              "  published:      ", DST_KEY_DNSKEY,
2705
0
              DST_TIME_PUBLISH));
2706
2707
    // signing status
2708
0
    result = dst_key_getbool(dkey->key, DST_BOOL_KSK, &ksk);
2709
0
    if (result == ISC_R_SUCCESS && ksk) {
2710
0
      RETERR(keytime_status(
2711
0
        dkey->key, now, &buf, "  key signing:    ",
2712
0
        DST_KEY_KRRSIG, DST_TIME_PUBLISH));
2713
0
    }
2714
0
    result = dst_key_getbool(dkey->key, DST_BOOL_ZSK, &zsk);
2715
0
    if (result == ISC_R_SUCCESS && zsk) {
2716
0
      RETERR(keytime_status(
2717
0
        dkey->key, now, &buf, "  zone signing:   ",
2718
0
        DST_KEY_ZRRSIG, DST_TIME_ACTIVATE));
2719
0
    }
2720
2721
    // rollover status
2722
0
    RETERR(rollover_status(dkey, kasp, now, &buf, zsk));
2723
2724
    // key states
2725
0
    RETERR(keystate_status(dkey->key, &buf,
2726
0
               "goal:           ", DST_KEY_GOAL));
2727
0
    RETERR(keystate_status(dkey->key, &buf,
2728
0
               "dnskey:         ", DST_KEY_DNSKEY));
2729
0
    RETERR(keystate_status(dkey->key, &buf,
2730
0
               "ds:             ", DST_KEY_DS));
2731
0
    RETERR(keystate_status(dkey->key, &buf,
2732
0
               "zone rrsig:     ", DST_KEY_ZRRSIG));
2733
0
    RETERR(keystate_status(dkey->key, &buf,
2734
0
               "key rrsig:      ", DST_KEY_KRRSIG));
2735
0
  }
2736
2737
0
failure:
2738
2739
0
  return result;
2740
0
}
2741
2742
isc_result_t
2743
dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
2744
        isc_stdtime_t now, isc_stdtime_t when, dns_keytag_t id,
2745
0
        unsigned int algorithm) {
2746
0
  int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
2747
0
  const char *directory = NULL;
2748
0
  isc_result_t result;
2749
0
  dns_dnsseckey_t *key = NULL;
2750
0
  isc_stdtime_t active, retire, prepub;
2751
2752
0
  REQUIRE(DNS_KASP_VALID(kasp));
2753
0
  REQUIRE(keyring != NULL);
2754
2755
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
2756
0
    if (dst_key_id(dkey->key) != id) {
2757
0
      continue;
2758
0
    }
2759
0
    if (algorithm > 0 && dst_key_alg(dkey->key) != algorithm) {
2760
0
      continue;
2761
0
    }
2762
0
    if (key != NULL) {
2763
      /*
2764
       * Only rollover for one key at a time.
2765
       */
2766
0
      return DNS_R_TOOMANYKEYS;
2767
0
    }
2768
0
    key = dkey;
2769
0
  }
2770
2771
0
  if (key == NULL) {
2772
0
    return DNS_R_NOKEYMATCH;
2773
0
  }
2774
2775
0
  result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
2776
0
  if (result != ISC_R_SUCCESS || active > now) {
2777
0
    return DNS_R_KEYNOTACTIVE;
2778
0
  }
2779
2780
0
  result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
2781
0
  if (result != ISC_R_SUCCESS) {
2782
    /**
2783
     * Default to as if this key was not scheduled to
2784
     * become retired, as if it had unlimited lifetime.
2785
     */
2786
0
    retire = 0;
2787
0
  }
2788
2789
  /**
2790
   * Usually when is set to now, which is before the scheduled
2791
   * prepublication time, meaning we reduce the lifetime of the
2792
   * key. But in some cases, the lifetime can also be extended.
2793
   * We accept it, but we can return an error here if that
2794
   * turns out to be unintuitive behavior.
2795
   */
2796
0
  prepub = dst_key_getttl(key->key) + dns_kasp_publishsafety(kasp) +
2797
0
     dns_kasp_zonepropagationdelay(kasp);
2798
0
  retire = when + prepub;
2799
2800
0
  dst_key_settime(key->key, DST_TIME_INACTIVE, retire);
2801
2802
  /* Store key state and update hints. */
2803
0
  directory = dst_key_directory(key->key);
2804
0
  if (directory == NULL) {
2805
0
    directory = ".";
2806
0
  }
2807
2808
0
  dns_dnssec_get_hints(key, now);
2809
0
  result = dst_key_tofile(key->key, options, directory);
2810
0
  if (result == ISC_R_SUCCESS) {
2811
0
    dst_key_setmodified(key->key, false);
2812
0
  }
2813
2814
0
  return result;
2815
0
}
2816
2817
isc_result_t
2818
dns_keymgr_offline(const dns_name_t *origin, dns_dnsseckeylist_t *keyring,
2819
       dns_kasp_t *kasp, isc_stdtime_t now,
2820
0
       isc_stdtime_t *nexttime) {
2821
0
  isc_result_t result = ISC_R_SUCCESS;
2822
0
  int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
2823
0
  char keystr[DST_KEY_FORMATSIZE];
2824
2825
0
  *nexttime = 0;
2826
2827
  /* Store key states and update hints. */
2828
0
  ISC_LIST_FOREACH(*keyring, dkey, link) {
2829
0
    bool modified;
2830
0
    bool ksk = false, zsk = false;
2831
0
    isc_stdtime_t active = 0, published = 0, inactive = 0,
2832
0
            remove = 0;
2833
0
    isc_stdtime_t lastchange = 0, nextchange = 0;
2834
0
    dst_key_state_t dnskey_state = HIDDEN, zrrsig_state = HIDDEN,
2835
0
        goal_state = HIDDEN;
2836
0
    dst_key_state_t current_dnskey = HIDDEN,
2837
0
        current_zrrsig = HIDDEN, current_goal = HIDDEN;
2838
2839
0
    (void)dst_key_role(dkey->key, &ksk, &zsk);
2840
0
    if (ksk || !zsk) {
2841
0
      continue;
2842
0
    }
2843
2844
0
    dns_keymgr_key_init(dkey, kasp, now, false);
2845
2846
    /* Get current metadata */
2847
0
    RETERR(dst_key_getstate(dkey->key, DST_KEY_DNSKEY,
2848
0
          &current_dnskey));
2849
0
    RETERR(dst_key_getstate(dkey->key, DST_KEY_ZRRSIG,
2850
0
          &current_zrrsig));
2851
0
    RETERR(dst_key_getstate(dkey->key, DST_KEY_GOAL,
2852
0
          &current_goal));
2853
0
    RETERR(dst_key_gettime(dkey->key, DST_TIME_PUBLISH,
2854
0
               &published));
2855
0
    RETERR(dst_key_gettime(dkey->key, DST_TIME_ACTIVATE, &active));
2856
0
    (void)dst_key_gettime(dkey->key, DST_TIME_INACTIVE, &inactive);
2857
0
    (void)dst_key_gettime(dkey->key, DST_TIME_DELETE, &remove);
2858
2859
    /* Determine key states from the metadata. */
2860
0
    if (active <= now) {
2861
0
      dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
2862
0
      ttlsig += dns_kasp_zonepropagationdelay(kasp);
2863
0
      if ((active + ttlsig) <= now) {
2864
0
        zrrsig_state = OMNIPRESENT;
2865
0
      } else {
2866
0
        zrrsig_state = RUMOURED;
2867
0
        (void)dst_key_gettime(dkey->key,
2868
0
                  DST_TIME_ZRRSIG,
2869
0
                  &lastchange);
2870
0
        nextchange = lastchange + ttlsig +
2871
0
               dns_kasp_retiresafety(kasp);
2872
0
      }
2873
0
      goal_state = OMNIPRESENT;
2874
0
    }
2875
2876
0
    if (published <= now) {
2877
0
      dns_ttl_t key_ttl = dst_key_getttl(dkey->key);
2878
0
      key_ttl += dns_kasp_zonepropagationdelay(kasp);
2879
0
      if ((published + key_ttl) <= now) {
2880
0
        dnskey_state = OMNIPRESENT;
2881
0
      } else {
2882
0
        dnskey_state = RUMOURED;
2883
0
        (void)dst_key_gettime(dkey->key,
2884
0
                  DST_TIME_DNSKEY,
2885
0
                  &lastchange);
2886
0
        nextchange = lastchange + key_ttl +
2887
0
               dns_kasp_publishsafety(kasp);
2888
0
      }
2889
0
      goal_state = OMNIPRESENT;
2890
0
    }
2891
2892
0
    if (inactive > 0 && inactive <= now) {
2893
0
      dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
2894
0
      ttlsig += dns_kasp_zonepropagationdelay(kasp);
2895
0
      if ((inactive + ttlsig) <= now) {
2896
0
        zrrsig_state = HIDDEN;
2897
0
      } else {
2898
0
        zrrsig_state = UNRETENTIVE;
2899
0
        (void)dst_key_gettime(dkey->key,
2900
0
                  DST_TIME_ZRRSIG,
2901
0
                  &lastchange);
2902
0
        nextchange = lastchange + ttlsig +
2903
0
               dns_kasp_retiresafety(kasp);
2904
0
      }
2905
0
      goal_state = HIDDEN;
2906
0
    }
2907
2908
0
    if (remove > 0 && remove <= now) {
2909
0
      dns_ttl_t key_ttl = dst_key_getttl(dkey->key);
2910
0
      key_ttl += dns_kasp_zonepropagationdelay(kasp);
2911
0
      if ((remove + key_ttl) <= now) {
2912
0
        dnskey_state = HIDDEN;
2913
0
      } else {
2914
0
        dnskey_state = UNRETENTIVE;
2915
0
        (void)dst_key_gettime(dkey->key,
2916
0
                  DST_TIME_DNSKEY,
2917
0
                  &lastchange);
2918
0
        nextchange =
2919
0
          lastchange + key_ttl +
2920
0
          dns_kasp_zonepropagationdelay(kasp);
2921
0
      }
2922
0
      zrrsig_state = HIDDEN;
2923
0
      goal_state = HIDDEN;
2924
0
    }
2925
2926
0
    if ((*nexttime == 0 || *nexttime > nextchange) &&
2927
0
        nextchange > 0)
2928
0
    {
2929
0
      *nexttime = nextchange;
2930
0
    }
2931
2932
    /* Update key states if necessary. */
2933
0
    if (goal_state != current_goal) {
2934
0
      dst_key_setstate(dkey->key, DST_KEY_GOAL, goal_state);
2935
0
    }
2936
0
    if (dnskey_state != current_dnskey) {
2937
0
      dst_key_setstate(dkey->key, DST_KEY_DNSKEY,
2938
0
           dnskey_state);
2939
0
      dst_key_settime(dkey->key, DST_TIME_DNSKEY, now);
2940
0
    }
2941
0
    if (zrrsig_state != current_zrrsig) {
2942
0
      dst_key_setstate(dkey->key, DST_KEY_ZRRSIG,
2943
0
           zrrsig_state);
2944
0
      dst_key_settime(dkey->key, DST_TIME_ZRRSIG, now);
2945
0
      if (zrrsig_state == RUMOURED) {
2946
0
        dkey->first_sign = true;
2947
0
      }
2948
0
    }
2949
0
    modified = dst_key_ismodified(dkey->key);
2950
2951
0
    if (modified) {
2952
0
      const char *directory = dst_key_directory(dkey->key);
2953
0
      if (directory == NULL) {
2954
0
        directory = ".";
2955
0
      }
2956
2957
0
      dns_dnssec_get_hints(dkey, now);
2958
2959
0
      RETERR(dst_key_tofile(dkey->key, options, directory));
2960
0
      dst_key_setmodified(dkey->key, false);
2961
2962
0
      if (!isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
2963
0
        continue;
2964
0
      }
2965
0
      dst_key_format(dkey->key, keystr, sizeof(keystr));
2966
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC,
2967
0
              DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(3),
2968
0
              "keymgr: DNSKEY %s (%s) "
2969
0
              "saved to directory %s, policy %s",
2970
0
              keystr, keymgr_keyrole(dkey->key),
2971
0
              directory, dns_kasp_getname(kasp));
2972
0
    }
2973
0
    dst_key_setmodified(dkey->key, false);
2974
0
  }
2975
2976
0
  result = ISC_R_SUCCESS;
2977
2978
0
failure:
2979
0
  if (isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
2980
0
    char namebuf[DNS_NAME_FORMATSIZE];
2981
0
    dns_name_format(origin, namebuf, sizeof(namebuf));
2982
0
    isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
2983
0
            ISC_LOG_DEBUG(3), "keymgr: %s (offline-ksk) done",
2984
0
            namebuf);
2985
0
  }
2986
0
  return result;
2987
0
}