Coverage Report

Created: 2026-04-05 06:47

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