]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Introduce kasp structure
authorMatthijs Mekking <matthijs@isc.org>
Tue, 3 Sep 2019 08:39:25 +0000 (10:39 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 6 Nov 2019 21:31:44 +0000 (22:31 +0100)
This stores the dnssec-policy configuration and adds methods to
create, destroy, and attach/detach, as well as find a policy with
the same name in a list.

Also, add structures and functions for creating and destroying
kasp keys.

lib/dns/Makefile.in
lib/dns/include/dns/kasp.h [new file with mode: 0644]
lib/dns/include/dns/types.h
lib/dns/include/dns/zone.h
lib/dns/kasp.c [new file with mode: 0644]
lib/dns/win32/libdns.def.in
lib/dns/win32/libdns.vcxproj.filters.in
lib/dns/win32/libdns.vcxproj.in
lib/dns/zone.c
util/copyrights

index d99b54919a58e7b5dbc77c5e590b36379bf25a57..4e28fe4b3349594d84209956008668e749b21b28 100644 (file)
@@ -64,7 +64,7 @@ DNSOBJS =     acl.@O@ adb.@O@ badcache.@O@ byaddr.@O@ \
                db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
                dlz.@O@ dns64.@O@ dnsrps.@O@ dnssec.@O@ ds.@O@ dyndb.@O@ \
                ecs.@O@ fixedname.@O@ forward.@O@ \
-               ipkeylist.@O@ iptable.@O@ journal.@O@ keydata.@O@ \
+               ipkeylist.@O@ iptable.@O@ journal.@O@ kasp.@O@ keydata.@O@ \
                keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
                master.@O@ masterdump.@O@ message.@O@ \
                name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ nta.@O@ \
@@ -101,8 +101,8 @@ DNSSRCS =   acl.c adb.c badcache. byaddr.c \
                db.c dbiterator.c dbtable.c diff.c dispatch.c \
                dlz.c dns64.c dnsrps.c dnssec.c ds.c dyndb.c \
                ecs.c fixedname.c forward.c \
-               ipkeylist.c iptable.c journal.c keydata.c keytable.c lib.c \
-               log.c lookup.c master.c masterdump.c message.c \
+               ipkeylist.c iptable.c journal.c kasp.c keydata.c keytable.c \
+               lib.c log.c lookup.c master.c masterdump.c message.c \
                name.c ncache.c nsec.c nsec3.c nta.c \
                order.c peer.c portlist.c \
                rbt.c rbtdb.c rcode.c rdata.c rdatalist.c \
diff --git a/lib/dns/include/dns/kasp.h b/lib/dns/include/dns/kasp.h
new file mode 100644 (file)
index 0000000..12998d4
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef DNS_KASP_H
+#define DNS_KASP_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/kasp.h
+ * \brief
+ * DNSSEC Key and Signing Policy (KASP)
+ *
+ * A "kasp" is a DNSSEC policy, that determines how a zone should be
+ * signed and maintained.
+ */
+
+#include <time.h>
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/refcount.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/* Stores a KASP key */
+struct dns_kasp_key {
+       isc_mem_t*                      mctx;
+
+       /* Locked by themselves. */
+       isc_refcount_t                  references;
+
+       /* Under owner's locking control. */
+       ISC_LINK(struct dns_kasp_key)   link;
+
+       /* Configuration */
+       time_t                          lifetime;
+       uint32_t                        algorithm;
+       int                             length;
+       uint8_t                         role;
+};
+
+/* Stores a DNSSEC policy */
+struct dns_kasp {
+       unsigned int                    magic;
+       isc_mem_t*                      mctx;
+       char*                           name;
+
+       /* Internals. */
+       isc_mutex_t                     lock;
+       bool                            frozen;
+
+       /* Locked by themselves. */
+       isc_refcount_t                  references;
+
+       /* Under owner's locking control. */
+       ISC_LINK(struct dns_kasp)       link;
+
+       /* Configuration: signatures */
+       uint32_t                        signatures_refresh;
+       uint32_t                        signatures_validity;
+       uint32_t                        signatures_validity_dnskey;
+
+       /* Configuration: Keys */
+       dns_kasp_keylist_t              keys;
+       uint32_t                        dnskey_ttl;
+
+       /* Configuration: Timings */
+       uint32_t                        publish_safety;
+       uint32_t                        retire_safety;
+
+       // TODO: The rest of the KASP configuration
+};
+
+#define DNS_KASP_MAGIC                 ISC_MAGIC('K','A','S','P')
+#define DNS_KASP_VALID(kasp)           ISC_MAGIC_VALID(kasp, DNS_KASP_MAGIC)
+
+/* Defaults */
+#define DNS_KASP_SIG_REFRESH           (86400*5)
+#define DNS_KASP_SIG_VALIDITY          (86400*14)
+#define DNS_KASP_SIG_VALIDITY_DNSKEY   (86400*14)
+#define DNS_KASP_KEY_TTL               (3600)
+#define DNS_KASP_PUBLISH_SAFETY                (300)
+#define DNS_KASP_RETIRE_SAFETY         (300)
+
+/* Key roles */
+#define DNS_KASP_KEY_ROLE_KSK          0x01
+#define DNS_KASP_KEY_ROLE_ZSK          0x02
+
+isc_result_t
+dns_kasp_create(isc_mem_t *mctx, const char* name, dns_kasp_t **kaspp);
+/*%<
+ * Create a KASP.
+ *
+ * Requires:
+ *
+ *\li  'mctx' is a valid memory context.
+ *
+ *\li  'name' is a valid C string.
+ *
+ *\li  kaspp != NULL && *kaspp == NULL
+ *
+ * Returns:
+ *
+ *\li  #ISC_R_SUCCESS
+ *\li  #ISC_R_NOMEMORY
+ *
+ *\li  Other errors are possible.
+ */
+
+void
+dns_kasp_attach(dns_kasp_t *source, dns_kasp_t **targetp);
+/*%<
+ * Attach '*targetp' to 'source'.
+ *
+ * Requires:
+ *
+ *\li   'source' is a valid, frozen kasp.
+ *
+ *\li   'targetp' points to a NULL dns_kasp_t *.
+ *
+ * Ensures:
+ *
+ *\li   *targetp is attached to source.
+ *
+ *\li   While *targetp is attached, the kasp will not shut down.
+ */
+
+void
+dns_kasp_detach(dns_kasp_t **kaspp);
+/*%<
+ * Detach KASP.
+ *
+ * Requires:
+ *
+ *\li   'kaspp' points to a valid dns_kasp_t *
+ *
+ * Ensures:
+ *
+ *\li   *kaspp is NULL.
+ */
+
+void
+dns_kasp_freeze(dns_kasp_t *kasp);
+/*%<
+ * Freeze kasp.  No changes can be made to kasp configuration while frozen.
+ *
+ * Requires:
+ *
+ *\li   'kasp' is a valid, unfrozen kasp.
+ *
+ * Ensures:
+ *
+ *\li   'kasp' is frozen.
+ */
+
+void
+dns_kasp_thaw(dns_kasp_t *kasp);
+/*%<
+ * Thaw kasp.
+ *
+ * Requires:
+ *
+ *\li   'kasp' is a valid, frozen kasp.
+ *
+ * Ensures:
+ *
+ *\li   'kasp' is no longer frozen.
+ */
+
+const char*
+dns_kasp_getname(dns_kasp_t *kasp);
+/*%<
+ * Get kasp name.
+ *
+ * Requires:
+ *
+ *\li   'kasp' is a valid, frozen kasp.
+ *
+ * Returns:
+ *
+ *\li   name of 'kasp'.
+ */
+
+isc_result_t
+dns_kasplist_find(dns_kasplist_t *list, const char *name, dns_kasp_t **kaspp);
+/*%<
+ * Search for a kasp with name 'name' in 'list'.
+ * If found, '*kaspp' is (strongly) attached to it.
+ *
+ * Requires:
+ *
+ *\li   'kaspp' points to a NULL dns_kasp_t *.
+ *
+ * Returns:
+ *
+ *\li   #ISC_R_SUCCESS          A matching kasp was found.
+ *\li   #ISC_R_NOTFOUND         No matching kasp was found.
+ */
+
+isc_result_t
+dns_kasp_key_create(isc_mem_t* mctx, dns_kasp_key_t **keyp);
+/*%<
+ * Create a key inside a KASP.
+ *
+ * Requires:
+ *
+ *\li  'mctx' is a valid memory context.
+ *
+ *\li  keyp != NULL && *keyp == NULL
+ *
+ * Returns:
+ *
+ *\li  #ISC_R_SUCCESS
+ *\li  #ISC_R_NOMEMORY
+ *
+ *\li  Other errors are possible.
+ */
+
+void
+dns_kasp_key_destroy(dns_kasp_key_t* key);
+/*%<
+ * Destroy a KASP key.
+ *
+ * Requires:
+ *
+ *\li  'key' is a valid KASP key.
+ *
+ *\li  kasp != NULL && key != NULL
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_KASP_H */
index 329ee7d277706c9177ad44816e17e7450f792bbb..728fb0c0a1ff80ede8934a00353bd98ec45cb6ba 100644 (file)
@@ -91,6 +91,10 @@ typedef struct dns_fwdtable                  dns_fwdtable_t;
 typedef struct dns_geoip_databases             dns_geoip_databases_t;
 typedef struct dns_iptable                     dns_iptable_t;
 typedef uint32_t                               dns_iterations_t;
+typedef struct dns_kasp                                dns_kasp_t;
+typedef ISC_LIST(dns_kasp_t)                   dns_kasplist_t;
+typedef struct dns_kasp_key                    dns_kasp_key_t;
+typedef ISC_LIST(dns_kasp_key_t)               dns_kasp_keylist_t;
 typedef uint16_t                               dns_keyflags_t;
 typedef struct dns_keynode                     dns_keynode_t;
 typedef ISC_LIST(dns_keynode_t)                        dns_keynodelist_t;
index 0ad20356db6e2448f1dcf6122830ab7daf77860f..a80301f917cc4d22c34cb621151de939547184cc 100644 (file)
@@ -665,6 +665,24 @@ dns_zone_unload(dns_zone_t *zone);
  *\li  'zone' to be a valid zone.
  */
 
+dns_kasp_t*
+dns_zone_getkasp(dns_zone_t *zone);
+/*%<
+ *     Returns the current kasp.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t* kasp);
+/*%<
+ *     Set kasp for zone.  If a kasp is already set, it will be detached.
+ *
+ * Requires:
+ *\li  'zone' to be a valid zone.
+ */
+
 void
 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option,
                   bool value);
diff --git a/lib/dns/kasp.c b/lib/dns/kasp.c
new file mode 100644 (file)
index 0000000..ce401cd
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <string.h>
+
+#include <isc/assertions.h>
+#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/log.h>
+#include <dns/kasp.h>
+
+isc_result_t
+dns_kasp_create(isc_mem_t *mctx, const char *name, dns_kasp_t **kaspp)
+{
+       dns_kasp_t *kasp;
+
+       REQUIRE(name != NULL);
+       REQUIRE(kaspp != NULL && *kaspp == NULL);
+
+       kasp = isc_mem_get(mctx, sizeof(*kasp));
+       kasp->mctx = NULL;
+       isc_mem_attach(mctx, &kasp->mctx);
+
+       kasp->name = isc_mem_strdup(mctx, name);
+       isc_mutex_init(&kasp->lock);
+       kasp->frozen = false;
+
+       isc_refcount_init(&kasp->references, 1);
+
+       ISC_LINK_INIT(kasp, link);
+
+       kasp->signatures_refresh = DNS_KASP_SIG_REFRESH;
+       kasp->signatures_validity = DNS_KASP_SIG_VALIDITY;
+       kasp->signatures_validity_dnskey = DNS_KASP_SIG_VALIDITY_DNSKEY;
+
+       ISC_LIST_INIT(kasp->keys);
+
+       kasp->dnskey_ttl = DNS_KASP_KEY_TTL;
+       kasp->publish_safety = DNS_KASP_PUBLISH_SAFETY;
+       kasp->retire_safety = DNS_KASP_RETIRE_SAFETY;
+
+       // TODO: The rest of the KASP configuration
+
+       kasp->magic = DNS_KASP_MAGIC;
+       *kaspp = kasp;
+
+       return (ISC_R_SUCCESS);
+}
+
+void
+dns_kasp_attach(dns_kasp_t *source, dns_kasp_t **targetp) {
+       REQUIRE(DNS_KASP_VALID(source));
+       REQUIRE(targetp != NULL && *targetp == NULL);
+       isc_refcount_increment(&source->references);
+       *targetp = source;
+}
+
+static inline void
+destroy(dns_kasp_t *kasp) {
+       dns_kasp_key_t *key;
+       dns_kasp_key_t *key_next;
+
+       for (key = ISC_LIST_HEAD(kasp->keys); key != NULL; key = key_next) {
+               key_next = ISC_LIST_NEXT(key, link);
+               ISC_LIST_UNLINK(kasp->keys, key, link);
+               dns_kasp_key_destroy(key);
+       }
+       ISC_INSIST(ISC_LIST_EMPTY(kasp->keys));
+
+       isc_mem_free(kasp->mctx, kasp->name);
+       isc_mem_putanddetach(&kasp->mctx, kasp, sizeof(*kasp));
+}
+
+void
+dns_kasp_detach(dns_kasp_t **kaspp) {
+       REQUIRE(kaspp != NULL && DNS_KASP_VALID(*kaspp));
+       dns_kasp_t *kasp = *kaspp;
+       *kaspp = NULL;
+
+       if (isc_refcount_decrement(&kasp->references) == 1) {
+               destroy(kasp);
+       }
+}
+
+void
+dns_kasp_freeze(dns_kasp_t *kasp) {
+       REQUIRE(DNS_KASP_VALID(kasp));
+       REQUIRE(!kasp->frozen);
+       kasp->frozen = true;
+}
+
+void
+dns_kasp_thaw(dns_kasp_t *kasp) {
+       REQUIRE(DNS_KASP_VALID(kasp));
+       REQUIRE(kasp->frozen);
+       kasp->frozen = false;
+}
+
+const char*
+dns_kasp_getname(dns_kasp_t *kasp) {
+       REQUIRE(DNS_KASP_VALID(kasp));
+       return kasp->name;
+}
+
+isc_result_t
+dns_kasplist_find(dns_kasplist_t *list, const char *name, dns_kasp_t **kaspp)
+{
+       dns_kasp_t *kasp;
+
+       if (list == NULL) {
+               return (ISC_R_NOTFOUND);
+       }
+       INSIST(list != NULL);
+
+       for (kasp = ISC_LIST_HEAD(*list); kasp != NULL;
+            kasp = ISC_LIST_NEXT(kasp, link))
+       {
+               if (strcmp(kasp->name, name) == 0) {
+                       break;
+               }
+       }
+       if (kasp == NULL) {
+               return (ISC_R_NOTFOUND);
+       }
+       dns_kasp_attach(kasp, kaspp);
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_kasp_key_create(isc_mem_t* mctx, dns_kasp_key_t **keyp)
+{
+       dns_kasp_key_t *key;
+
+       REQUIRE(keyp != NULL && *keyp == NULL);
+
+       key = isc_mem_get(mctx, sizeof(*key));
+       key->mctx = NULL;
+       isc_mem_attach(mctx, &key->mctx);
+
+       ISC_LINK_INIT(key, link);
+
+       key->lifetime = 0;
+       key->algorithm = 0;
+       key->length = -1;
+       key->role = 0;
+       *keyp = key;
+       return (ISC_R_SUCCESS);
+}
+
+void
+dns_kasp_key_destroy(dns_kasp_key_t* key)
+{
+       REQUIRE(key != NULL);
+       isc_mem_putanddetach(&key->mctx, key, sizeof(*key));
+}
index a3c7a90af5a8a1ff4de3feac44716a0f5e6430bf..ce6e55b00c16f6178edb595587c835542b72401c 100644 (file)
@@ -413,6 +413,15 @@ dns_journal_rollforward
 dns_journal_set_sourceserial
 dns_journal_write_transaction
 dns_journal_writediff
+dns_kasp_create
+dns_kasp_attach
+dns_kasp_detach
+dns_kasp_freeze
+dns_kasp_getname
+dns_kasp_key_create
+dns_kasp_key_destroy
+dns_kasp_thaw
+dns_kasplist_find
 dns_keydata_fromdnskey
 dns_keydata_todnskey
 dns_keyflags_fromtext
@@ -1154,6 +1163,7 @@ dns_zone_getidleout
 dns_zone_getincludes
 dns_zone_getjournal
 dns_zone_getjournalsize
+dns_zone_getkasp
 dns_zone_getkeydirectory
 dns_zone_getkeyopts
 dns_zone_getkeyvalidityinterval
@@ -1255,6 +1265,7 @@ dns_zone_setidleout
 dns_zone_setisself
 dns_zone_setjournal
 dns_zone_setjournalsize
+dns_zone_setkasp
 dns_zone_setkeydirectory
 dns_zone_setkeyopt
 dns_zone_setkeyvalidityinterval
index 56f12aeba2bce094d8c58adb12f1149e72a514a0..b06e21792b134c9d8c9610f0c9294d67192b8b8e 100644 (file)
     <ClCompile Include="..\journal.c">
       <Filter>Library Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\kasp.c">
+      <Filter>Library Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\keydata.c">
       <Filter>Library Source Files</Filter>
     </ClCompile>
     <ClInclude Include="..\include\dns\journal.h">
       <Filter>Library Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\include\dns\kasp.h">
+      <Filter>Library Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\include\dns\keydata.h">
       <Filter>Library Header Files</Filter>
     </ClInclude>
index 43c3acef8a1af4472f48f259bd1e9157e63bdf0c..9a749d28e6853881ad62c6ba68a6bd77a8d1812e 100644 (file)
     <ClCompile Include="..\ipkeylist.c" />
     <ClCompile Include="..\iptable.c" />
     <ClCompile Include="..\journal.c" />
+    <ClCompile Include="..\kasp.c" />
     <ClCompile Include="..\key.c" />
     <ClCompile Include="..\keydata.c" />
     <ClCompile Include="..\keytable.c" />
     <ClInclude Include="..\include\dns\ipkeylist.h" />
     <ClInclude Include="..\include\dns\iptable.h" />
     <ClInclude Include="..\include\dns\journal.h" />
+    <ClInclude Include="..\include\dns\kasp.h" />
     <ClInclude Include="..\include\dns\keydata.h" />
     <ClInclude Include="..\include\dns\keyflags.h" />
     <ClInclude Include="..\include\dns\keytable.h" />
index 6d5417955774be7ce5f4f9c49cd4faa9eb733650..720df2807a37a10d9b22bb4215aa027792408497 100644 (file)
@@ -45,6 +45,7 @@
 #include <dns/dnssec.h>
 #include <dns/events.h>
 #include <dns/journal.h>
+#include <dns/kasp.h>
 #include <dns/keydata.h>
 #include <dns/keytable.h>
 #include <dns/keyvalues.h>
@@ -303,6 +304,7 @@ struct dns_zone {
        uint32_t                sigresigninginterval;
        dns_view_t              *view;
        dns_view_t              *prev_view;
+       dns_kasp_t              *kasp;
        dns_checkmxfunc_t       checkmx;
        dns_checksrvfunc_t      checksrv;
        dns_checknsfunc_t       checkns;
@@ -1014,6 +1016,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        zone->sigvalidityinterval = 30 * 24 * 3600;
        zone->keyvalidityinterval = 0;
        zone->sigresigninginterval = 7 * 24 * 3600;
+       zone->kasp = NULL;
        zone->view = NULL;
        zone->prev_view = NULL;
        zone->checkmx = NULL;
@@ -1184,6 +1187,9 @@ zone_free(dns_zone_t *zone) {
                isc_mem_free(zone->mctx, zone->keydirectory);
        }
        zone->keydirectory = NULL;
+       if (zone->kasp != NULL) {
+               dns_kasp_detach(&zone->kasp);
+       }
        zone->journalsize = -1;
        if (zone->journal != NULL) {
                isc_mem_free(zone->mctx, zone->journal);
@@ -5537,6 +5543,29 @@ dns_zone_setflag(dns_zone_t *zone, unsigned int flags, bool value) {
        }
 }
 
+void
+dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t* kasp)
+{
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       if (zone->kasp != NULL) {
+               dns_kasp_t* oldkasp = zone->kasp;
+               zone->kasp = NULL;
+               dns_kasp_detach(&oldkasp);
+       }
+       zone->kasp = kasp;
+       UNLOCK_ZONE(zone);
+}
+
+dns_kasp_t*
+dns_zone_getkasp(dns_zone_t *zone)
+{
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       return (zone->kasp);
+}
+
 void
 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option,
                   bool value)
index 1f7fef1d1dff8c7f5d9e348a0aeb48b8b2dba9ea..cff1a45fc0435ea09d219b59d8f968b8ef923dc2 100644 (file)
 ./lib/dns/include/dns/ipkeylist.h              C       2016,2018,2019
 ./lib/dns/include/dns/iptable.h                        C       2007,2012,2014,2016,2018,2019
 ./lib/dns/include/dns/journal.h                        C       1999,2000,2001,2004,2005,2006,2007,2008,2009,2011,2013,2016,2017,2018,2019
+./lib/dns/include/dns/kasp.h                   C       2019
 ./lib/dns/include/dns/keydata.h                        C       2009,2016,2018,2019
 ./lib/dns/include/dns/keyflags.h               C       1999,2000,2001,2004,2005,2006,2007,2016,2018,2019
 ./lib/dns/include/dns/keytable.h               C       2000,2001,2004,2005,2007,2009,2010,2014,2015,2016,2017,2018,2019
 ./lib/dns/ipkeylist.c                          C       2016,2018,2019
 ./lib/dns/iptable.c                            C       2007,2008,2009,2013,2014,2016,2017,2018,2019
 ./lib/dns/journal.c                            C       1999,2000,2001,2002,2004,2005,2007,2008,2009,2010,2011,2013,2014,2015,2016,2017,2018,2019
+./lib/dns/kasp.c                               C       2019
 ./lib/dns/key.c                                        C       2001,2004,2005,2006,2007,2011,2016,2018,2019
 ./lib/dns/keydata.c                            C       2009,2014,2016,2018,2019
 ./lib/dns/keytable.c                           C       2000,2001,2004,2005,2007,2009,2010,2013,2014,2015,2016,2017,2018,2019