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