1 /* $NetBSD: dnssec.h,v 1.8 2022/09/23 12:15:30 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #ifndef DNS_DNSSEC_H 17 #define DNS_DNSSEC_H 1 18 19 /*! \file dns/dnssec.h */ 20 21 #include <stdbool.h> 22 23 #include <isc/lang.h> 24 #include <isc/stats.h> 25 #include <isc/stdtime.h> 26 27 #include <dns/diff.h> 28 #include <dns/types.h> 29 30 #include <dst/dst.h> 31 32 ISC_LANG_BEGINDECLS 33 34 LIBDNS_EXTERNAL_DATA extern isc_stats_t *dns_dnssec_stats; 35 36 /*%< Maximum number of keys supported in a zone. */ 37 #define DNS_MAXZONEKEYS 32 38 39 /* 40 * Indicates how the signer found this key: in the key repository, at the 41 * zone apex, or specified by the user. 42 */ 43 typedef enum { 44 dns_keysource_unknown, 45 dns_keysource_repository, 46 dns_keysource_zoneapex, 47 dns_keysource_user 48 } dns_keysource_t; 49 50 /* 51 * A DNSSEC key and hints about its intended use gleaned from metadata 52 */ 53 struct dns_dnsseckey { 54 dst_key_t *key; 55 bool hint_publish; /*% metadata says to publish */ 56 bool force_publish; /*% publish regardless of metadata 57 * */ 58 bool hint_sign; /*% metadata says to sign with this 59 * key */ 60 bool force_sign; /*% sign with key regardless of 61 * metadata */ 62 bool hint_revoke; /*% metadata says revoke key */ 63 bool hint_remove; /*% metadata says *don't* publish */ 64 bool is_active; /*% key is already active */ 65 bool first_sign; /*% key is newly becoming active */ 66 bool purge; /*% remove key files */ 67 unsigned int prepublish; /*% how long until active? */ 68 dns_keysource_t source; /*% how the key was found */ 69 bool ksk; /*% this is a key-signing key */ 70 bool zsk; /*% this is a zone-signing key */ 71 bool legacy; /*% this is old-style key with no 72 * metadata (possibly generated by 73 * an older version of BIND9) and 74 * should be ignored when searching 75 * for keys to import into the zone */ 76 unsigned int index; /*% position in list */ 77 ISC_LINK(dns_dnsseckey_t) link; 78 }; 79 80 isc_result_t 81 dns_dnssec_keyfromrdata(const dns_name_t *name, const dns_rdata_t *rdata, 82 isc_mem_t *mctx, dst_key_t **key); 83 /*%< 84 * Creates a DST key from a DNS record. Basically a wrapper around 85 * dst_key_fromdns(). 86 * 87 * Requires: 88 *\li 'name' is not NULL 89 *\li 'rdata' is not NULL 90 *\li 'mctx' is not NULL 91 *\li 'key' is not NULL 92 *\li '*key' is NULL 93 * 94 * Returns: 95 *\li #ISC_R_SUCCESS 96 *\li #ISC_R_NOMEMORY 97 *\li DST_R_INVALIDPUBLICKEY 98 *\li various errors from dns_name_totext 99 */ 100 101 isc_result_t 102 dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 103 isc_stdtime_t *inception, isc_stdtime_t *expire, 104 isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata); 105 /*%< 106 * Generates a RRSIG record covering this rdataset. This has no effect 107 * on existing RRSIG records. 108 * 109 * Requires: 110 *\li 'name' (the owner name of the record) is a valid name 111 *\li 'set' is a valid rdataset 112 *\li 'key' is a valid key 113 *\li 'inception' is not NULL 114 *\li 'expire' is not NULL 115 *\li 'mctx' is not NULL 116 *\li 'buffer' is not NULL 117 *\li 'sigrdata' is not NULL 118 * 119 * Returns: 120 *\li #ISC_R_SUCCESS 121 *\li #ISC_R_NOMEMORY 122 *\li #ISC_R_NOSPACE 123 *\li #DNS_R_INVALIDTIME - the expiration is before the inception 124 *\li #DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either 125 * it is not a zone key or its flags prevent 126 * authentication) 127 *\li DST_R_* 128 */ 129 130 isc_result_t 131 dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 132 bool ignoretime, unsigned int maxbits, isc_mem_t *mctx, 133 dns_rdata_t *sigrdata, dns_name_t *wild); 134 /*%< 135 * Verifies the RRSIG record covering this rdataset signed by a specific 136 * key. This does not determine if the key's owner is authorized to sign 137 * this record, as this requires a resolver or database. 138 * If 'ignoretime' is true, temporal validity will not be checked. 139 * 140 * 'maxbits' specifies the maximum number of rsa exponent bits accepted. 141 * 142 * Requires: 143 *\li 'name' (the owner name of the record) is a valid name 144 *\li 'set' is a valid rdataset 145 *\li 'key' is a valid key 146 *\li 'mctx' is not NULL 147 *\li 'sigrdata' is a valid rdata containing a SIG record 148 *\li 'wild' if non-NULL then is a valid and has a buffer. 149 * 150 * Returns: 151 *\li #ISC_R_SUCCESS 152 *\li #ISC_R_NOMEMORY 153 *\li #DNS_R_FROMWILDCARD - the signature is valid and is from 154 * a wildcard expansion. dns_dnssec_verify2() only. 155 * 'wild' contains the name of the wildcard if non-NULL. 156 *\li #DNS_R_SIGINVALID - the signature fails to verify 157 *\li #DNS_R_SIGEXPIRED - the signature has expired 158 *\li #DNS_R_SIGFUTURE - the signature's validity period has not begun 159 *\li #DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either 160 * it is not a zone key or its flags prevent 161 * authentication) 162 *\li DST_R_* 163 */ 164 165 /*@{*/ 166 isc_result_t 167 dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node, 168 const dns_name_t *name, const char *directory, 169 isc_stdtime_t now, isc_mem_t *mctx, 170 unsigned int maxkeys, dst_key_t **keys, 171 unsigned int *nkeys); 172 173 /*%< 174 * Finds a set of zone keys. 175 * XXX temporary - this should be handled in dns_zone_t. 176 */ 177 /*@}*/ 178 179 bool 180 dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now); 181 /*%< 182 * 183 * Returns true if 'key' is active as of the time specified 184 * in 'now' (i.e., if the activation date has passed, inactivation or 185 * deletion date has not yet been reached, and the key is not revoked 186 * -- or if it is a legacy key without metadata). Otherwise returns 187 * false. 188 * 189 * Requires: 190 *\li 'key' is a valid key 191 */ 192 193 isc_result_t 194 dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key); 195 /*%< 196 * Signs a message with a SIG(0) record. This is implicitly called by 197 * dns_message_renderend() if msg->sig0key is not NULL. 198 * 199 * Requires: 200 *\li 'msg' is a valid message 201 *\li 'key' is a valid key that can be used for signing 202 * 203 * Returns: 204 *\li #ISC_R_SUCCESS 205 *\li #ISC_R_NOMEMORY 206 *\li DST_R_* 207 */ 208 209 isc_result_t 210 dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, 211 dst_key_t *key); 212 /*%< 213 * Verifies a message signed by a SIG(0) record. This is not 214 * called implicitly by dns_message_parse(). If dns_message_signer() 215 * is called before dns_dnssec_verifymessage(), it will return 216 * #DNS_R_NOTVERIFIEDYET. dns_dnssec_verifymessage() will set 217 * the verified_sig0 flag in msg if the verify succeeds, and 218 * the sig0status field otherwise. 219 * 220 * Requires: 221 *\li 'source' is a valid buffer containing the unparsed message 222 *\li 'msg' is a valid message 223 *\li 'key' is a valid key 224 * 225 * Returns: 226 *\li #ISC_R_SUCCESS 227 *\li #ISC_R_NOMEMORY 228 *\li #ISC_R_NOTFOUND - no SIG(0) was found 229 *\li #DNS_R_SIGINVALID - the SIG record is not well-formed or 230 * was not generated by the key. 231 *\li DST_R_* 232 */ 233 234 bool 235 dns_dnssec_selfsigns(dns_rdata_t *rdata, const dns_name_t *name, 236 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 237 bool ignoretime, isc_mem_t *mctx); 238 239 bool 240 dns_dnssec_signs(dns_rdata_t *rdata, const dns_name_t *name, 241 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 242 bool ignoretime, isc_mem_t *mctx); 243 /*%< 244 * Verify that 'rdataset' is validly signed in 'sigrdataset' by 245 * the key in 'rdata'. 246 * 247 * dns_dnssec_selfsigns() requires that rdataset be a DNSKEY or KEY 248 * rrset. dns_dnssec_signs() works on any rrset. 249 */ 250 251 isc_result_t 252 dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, 253 dns_dnsseckey_t **dkp); 254 /*%< 255 * Create and initialize a dns_dnsseckey_t structure. 256 * 257 * Requires: 258 *\li 'dkp' is not NULL and '*dkp' is NULL. 259 * 260 * Returns: 261 *\li #ISC_R_SUCCESS 262 *\li #ISC_R_NOMEMORY 263 */ 264 265 void 266 dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp); 267 /*%< 268 * Reclaim a dns_dnsseckey_t structure. 269 * 270 * Requires: 271 *\li 'dkp' is not NULL and '*dkp' is not NULL. 272 * 273 * Ensures: 274 *\li '*dkp' is NULL. 275 */ 276 277 void 278 dns_dnssec_get_hints(dns_dnsseckey_t *key, isc_stdtime_t now); 279 /*%< 280 * Get hints on DNSSEC key whether this key can be published 281 * and/or is active. Timing metadata is compared to 'now'. 282 * 283 * Requires: 284 *\li 'key' is a pointer to a DNSSEC key and is not NULL. 285 */ 286 287 isc_result_t 288 dns_dnssec_findmatchingkeys(const dns_name_t *origin, const char *directory, 289 isc_stdtime_t now, isc_mem_t *mctx, 290 dns_dnsseckeylist_t *keylist); 291 /*%< 292 * Search 'directory' for K* key files matching the name in 'origin'. 293 * Append all such keys, along with use hints gleaned from their 294 * metadata, onto 'keylist'. Skip any unsupported algorithms. 295 * 296 * Requires: 297 *\li 'keylist' is not NULL 298 * 299 * Returns: 300 *\li #ISC_R_SUCCESS 301 *\li #ISC_R_NOTFOUND 302 *\li #ISC_R_NOMEMORY 303 *\li any error returned by dns_name_totext(), isc_dir_open(), or 304 * dst_key_fromnamedfile() 305 * 306 * Ensures: 307 *\li On error, keylist is unchanged 308 */ 309 310 isc_result_t 311 dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, 312 isc_mem_t *mctx, dns_rdataset_t *keyset, 313 dns_rdataset_t *keysigs, dns_rdataset_t *soasigs, 314 bool savekeys, bool publickey, 315 dns_dnsseckeylist_t *keylist); 316 /*%< 317 * Append the contents of a DNSKEY rdataset 'keyset' to 'keylist'. 318 * Omit duplicates. If 'publickey' is false, search 'directory' for 319 * matching key files, and load the private keys that go with 320 * the public ones. If 'savekeys' is true, mark the keys so 321 * they will not be deleted or inactivated regardless of metadata. 322 * 323 * 'keysigs' and 'soasigs', if not NULL and associated, contain the 324 * RRSIGS for the DNSKEY and SOA records respectively and are used to mark 325 * whether a key is already active in the zone. 326 */ 327 328 isc_result_t 329 dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, 330 dns_dnsseckeylist_t *removed, const dns_name_t *origin, 331 dns_ttl_t hint_ttl, dns_diff_t *diff, isc_mem_t *mctx, 332 void (*report)(const char *, ...)); 333 /*%< 334 * Update the list of keys in 'keys' with new key information in 'newkeys'. 335 * 336 * For each key in 'newkeys', see if it has a match in 'keys'. 337 * - If not, and if the metadata says the key should be published: 338 * add it to 'keys', and place a dns_difftuple into 'diff' so 339 * the key can be added to the DNSKEY set. If the metadata says it 340 * should be active, set the first_sign flag. 341 * - If so, and if the metadata says it should be removed: 342 * remove it from 'keys', and place a dns_difftuple into 'diff' so 343 * the key can be removed from the DNSKEY set. if 'removed' is non-NULL, 344 * copy the key into that list; otherwise destroy it. 345 * - Otherwise, make sure keys has current metadata. 346 * 347 * 'hint_ttl' is the TTL to use for the DNSKEY RRset if there is no 348 * existing RRset, and if none of the keys to be added has a default TTL 349 * (in which case we would use the shortest one). If the TTL is longer 350 * than the time until a new key will be activated, then we have to delay 351 * the key's activation. 352 * 353 * 'report' points to a function for reporting status. 354 * 355 * On completion, any remaining keys in 'newkeys' are freed. 356 */ 357 358 isc_result_t 359 dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys, 360 dns_rdataset_t *cds, dns_rdataset_t *cdnskey, 361 isc_stdtime_t now, dns_ttl_t hint_ttl, dns_diff_t *diff, 362 isc_mem_t *mctx); 363 /*%< 364 * Update the CDS and CDNSKEY RRsets, adding and removing keys as needed. 365 * 366 * Returns: 367 *\li ISC_R_SUCCESS 368 *\li Other values indicate error 369 */ 370 371 isc_result_t 372 dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey, 373 dns_name_t *origin, dns_rdataclass_t zclass, 374 dns_ttl_t ttl, dns_diff_t *diff, isc_mem_t *mctx, 375 bool expect_cds_delete, bool expect_cdnskey_delete); 376 /*%< 377 * Add or remove the CDS DELETE record and the CDNSKEY DELETE record. 378 * If 'expect_cds_delete' is true, the CDS DELETE record should be present. 379 * Otherwise, the CDS DELETE record must be removed from the RRsets (if 380 * present). If 'expect_cdnskey_delete' is true, the CDNSKEY DELETE record 381 * should be present. Otherwise, the CDNSKEY DELETE record must be removed 382 * from the RRsets (if present). 383 * 384 * Returns: 385 *\li ISC_R_SUCCESS 386 *\li Other values indicate error 387 */ 388 389 isc_result_t 390 dns_dnssec_matchdskey(dns_name_t *name, dns_rdata_t *dsrdata, 391 dns_rdataset_t *keyset, dns_rdata_t *keyrdata); 392 /*%< 393 * Given a DS rdata and a DNSKEY RRset, find the DNSKEY rdata that matches 394 * the DS, and place it in 'keyrdata'. 395 * 396 * Returns: 397 *\li ISC_R_SUCCESS 398 *\li ISC_R_NOTFOUND 399 *\li Other values indicate error 400 */ 401 ISC_LANG_ENDDECLS 402 403 #endif /* DNS_DNSSEC_H */ 404