1 /* 2 * validator/val_sigcrypt.h - validator signature crypto functions. 3 * 4 * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /** 37 * \file 38 * 39 * This file contains helper functions for the validator module. 40 * The functions help with signature verification and checking, the 41 * bridging between RR wireformat data and crypto calls. 42 */ 43 44 #ifndef VALIDATOR_VAL_SIGCRYPT_H 45 #define VALIDATOR_VAL_SIGCRYPT_H 46 #include "util/data/packed_rrset.h" 47 #include "sldns/pkthdr.h" 48 #include "sldns/rrdef.h" 49 struct val_env; 50 struct module_env; 51 struct module_qstate; 52 struct ub_packed_rrset_key; 53 struct rbtree_type; 54 struct regional; 55 struct sldns_buffer; 56 57 /** number of entries in algorithm needs array */ 58 #define ALGO_NEEDS_MAX 256 59 60 /** 61 * Storage for algorithm needs. DNSKEY algorithms. 62 */ 63 struct algo_needs { 64 /** the algorithms (8-bit) with each a number. 65 * 0: not marked. 66 * 1: marked 'necessary but not yet fulfilled' 67 * 2: marked bogus. 68 * Indexed by algorithm number. 69 */ 70 uint8_t needs[ALGO_NEEDS_MAX]; 71 /** the number of entries in the array that are unfulfilled */ 72 size_t num; 73 }; 74 75 /** 76 * Initialize algo needs structure, set algos from rrset as needed. 77 * Results are added to an existing need structure. 78 * @param n: struct with storage. 79 * @param dnskey: algos from this struct set as necessary. DNSKEY set. 80 * @param sigalg: adds to signalled algorithm list too. 81 */ 82 void algo_needs_init_dnskey_add(struct algo_needs* n, 83 struct ub_packed_rrset_key* dnskey, uint8_t* sigalg); 84 85 /** 86 * Initialize algo needs structure from a signalled algo list. 87 * @param n: struct with storage. 88 * @param sigalg: signalled algorithm list, numbers ends with 0. 89 */ 90 void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg); 91 92 /** 93 * Initialize algo needs structure, set algos from rrset as needed. 94 * @param n: struct with storage. 95 * @param ds: algos from this struct set as necessary. DS set. 96 * @param fav_ds_algo: filter to use only this DS algo. 97 * @param sigalg: list of signalled algos, constructed as output, 98 * provide size ALGO_NEEDS_MAX+1. list of algonumbers, ends with a zero. 99 */ 100 void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds, 101 int fav_ds_algo, uint8_t* sigalg); 102 103 /** 104 * Mark this algorithm as a success, sec_secure, and see if we are done. 105 * @param n: storage structure processed. 106 * @param algo: the algorithm processed to be secure. 107 * @return if true, processing has finished successfully, we are satisfied. 108 */ 109 int algo_needs_set_secure(struct algo_needs* n, uint8_t algo); 110 111 /** 112 * Mark this algorithm a failure, sec_bogus. It can later be overridden 113 * by a success for this algorithm (with a different signature). 114 * @param n: storage structure processed. 115 * @param algo: the algorithm processed to be bogus. 116 */ 117 void algo_needs_set_bogus(struct algo_needs* n, uint8_t algo); 118 119 /** 120 * See how many algorithms are missing (not bogus or secure, but not processed) 121 * @param n: storage structure processed. 122 * @return number of algorithms missing after processing. 123 */ 124 size_t algo_needs_num_missing(struct algo_needs* n); 125 126 /** 127 * See which algo is missing. 128 * @param n: struct after processing. 129 * @return if 0 an algorithm was bogus, if a number, this algorithm was 130 * missing. So on 0, report why that was bogus, on number report a missing 131 * algorithm. There could be multiple missing, this reports the first one. 132 */ 133 int algo_needs_missing(struct algo_needs* n); 134 135 /** 136 * Format error reason for algorithm missing. 137 * @param alg: DNSKEY-algorithm missing. 138 * @param reason: destination. 139 * @param s: string, appended with 'with algorithm ..'. 140 * @param reasonbuf: buffer to use for fail reason string print. 141 * @param reasonlen: length of reasonbuf. 142 */ 143 void algo_needs_reason(int alg, char** reason, char* s, char* reasonbuf, 144 size_t reasonlen); 145 146 /** 147 * Check if dnskey matches a DS digest 148 * Does not check dnskey-keyid footprint, just the digest. 149 * @param env: module environment. Uses scratch space. 150 * @param dnskey_rrset: DNSKEY rrset. 151 * @param dnskey_idx: index of RR in rrset. 152 * @param ds_rrset: DS rrset 153 * @param ds_idx: index of RR in DS rrset. 154 * @return true if it matches, false on error, not supported or no match. 155 */ 156 int ds_digest_match_dnskey(struct module_env* env, 157 struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, 158 struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 159 160 /** 161 * Get dnskey keytag, footprint value 162 * @param dnskey_rrset: DNSKEY rrset. 163 * @param dnskey_idx: index of RR in rrset. 164 * @return the keytag or 0 for badly formatted DNSKEYs. 165 */ 166 uint16_t dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, 167 size_t dnskey_idx); 168 169 /** 170 * Get DS keytag, footprint value that matches the DNSKEY keytag it signs. 171 * @param ds_rrset: DS rrset 172 * @param ds_idx: index of RR in DS rrset. 173 * @return the keytag or 0 for badly formatted DSs. 174 */ 175 uint16_t ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 176 177 /** 178 * See if DNSKEY algorithm is supported 179 * @param dnskey_rrset: DNSKEY rrset. 180 * @param dnskey_idx: index of RR in rrset. 181 * @return true if supported. 182 */ 183 int dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset, 184 size_t dnskey_idx); 185 186 /** 187 * See if the DNSKEY size at that algorithm is supported. 188 * @param dnskey_rrset: DNSKEY rrset. 189 * @param dnskey_idx: index of RR in rrset. 190 * @return true if supported. 191 */ 192 int dnskey_size_is_supported(struct ub_packed_rrset_key* dnskey_rrset, 193 size_t dnskey_idx); 194 195 /** 196 * See if the DNSKEY size at that algorithm is supported for all the 197 * RRs in the DNSKEY RRset. 198 * @param dnskey_rrset: DNSKEY rrset. 199 * @return true if supported. 200 */ 201 int dnskeyset_size_is_supported(struct ub_packed_rrset_key* dnskey_rrset); 202 203 /** 204 * See if DS digest algorithm is supported 205 * @param ds_rrset: DS rrset 206 * @param ds_idx: index of RR in DS rrset. 207 * @return true if supported. 208 */ 209 int ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 210 size_t ds_idx); 211 212 /** 213 * Get DS RR digest algorithm 214 * @param ds_rrset: DS rrset. 215 * @param ds_idx: which DS. 216 * @return algorithm or 0 if DS too short. 217 */ 218 int ds_get_digest_algo(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 219 220 /** 221 * See if DS key algorithm is supported 222 * @param ds_rrset: DS rrset 223 * @param ds_idx: index of RR in DS rrset. 224 * @return true if supported. 225 */ 226 int ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 227 size_t ds_idx); 228 229 /** 230 * Get DS RR key algorithm. This value should match with the DNSKEY algo. 231 * @param k: DS rrset. 232 * @param idx: which DS. 233 * @return algorithm or 0 if DS too short. 234 */ 235 int ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx); 236 237 /** 238 * Get DNSKEY RR signature algorithm 239 * @param k: DNSKEY rrset. 240 * @param idx: which DNSKEY RR. 241 * @return algorithm or 0 if DNSKEY too short. 242 */ 243 int dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx); 244 245 /** 246 * Get DNSKEY RR flags 247 * @param k: DNSKEY rrset. 248 * @param idx: which DNSKEY RR. 249 * @return flags or 0 if DNSKEY too short. 250 */ 251 uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx); 252 253 /** 254 * Verify rrset against dnskey rrset. 255 * @param env: module environment, scratch space is used. 256 * @param ve: validator environment, date settings. 257 * @param rrset: to be validated. 258 * @param dnskey: DNSKEY rrset, keyset to try. 259 * @param sigalg: if nonNULL provide downgrade protection otherwise one 260 * algorithm is enough. 261 * @param reason: if bogus, a string returned, fixed or alloced in scratch. 262 * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. 263 * @param section: section of packet where this rrset comes from. 264 * @param qstate: qstate with region. 265 * @param verified: if not NULL the number of RRSIG validations is returned. 266 * @param reasonbuf: buffer to use for fail reason string print. 267 * @param reasonlen: length of reasonbuf. 268 * @return SECURE if one key in the set verifies one rrsig. 269 * UNCHECKED on allocation errors, unsupported algorithms, malformed data, 270 * and BOGUS on verification failures (no keys match any signatures). 271 */ 272 enum sec_status dnskeyset_verify_rrset(struct module_env* env, 273 struct val_env* ve, struct ub_packed_rrset_key* rrset, 274 struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, 275 char** reason, sldns_ede_code *reason_bogus, 276 sldns_pkt_section section, struct module_qstate* qstate, int* verified, 277 char* reasonbuf, size_t reasonlen); 278 279 /** 280 * verify rrset against one specific dnskey (from rrset) 281 * @param env: module environment, scratch space is used. 282 * @param ve: validator environment, date settings. 283 * @param rrset: to be validated. 284 * @param dnskey: DNSKEY rrset, keyset. 285 * @param dnskey_idx: which key from the rrset to try. 286 * @param reason: if bogus, a string returned, fixed or alloced in scratch. 287 * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. 288 * @param section: section of packet where this rrset comes from. 289 * @param qstate: qstate with region. 290 * @return secure if *this* key signs any of the signatures on rrset. 291 * unchecked on error or and bogus on bad signature. 292 */ 293 enum sec_status dnskey_verify_rrset(struct module_env* env, struct val_env* ve, 294 struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, 295 size_t dnskey_idx, char** reason, sldns_ede_code *reason_bogus, 296 sldns_pkt_section section, struct module_qstate* qstate); 297 298 /** 299 * verify rrset, with specific dnskey(from set), for a specific rrsig 300 * @param region: scratch region used for temporary allocation. 301 * @param buf: scratch buffer used for canonicalized rrset data. 302 * @param ve: validator environment, date settings. 303 * @param now: current time for validation (can be overridden). 304 * @param rrset: to be validated. 305 * @param dnskey: DNSKEY rrset, keyset. 306 * @param dnskey_idx: which key from the rrset to try. 307 * @param sig_idx: which signature to try to validate. 308 * @param sortree: pass NULL at start, the sorted rrset order is returned. 309 * pass it again for the same rrset. 310 * @param buf_canon: if true, the buffer is already canonical. 311 * pass false at start. pass old value only for same rrset and same 312 * signature (but perhaps different key) for reuse. 313 * @param reason: if bogus, a string returned, fixed or alloced in scratch. 314 * @param reason_bogus: EDE (8914) code paired with the reason of failure. 315 * @param section: section of packet where this rrset comes from. 316 * @param qstate: qstate with region. 317 * @return secure if this key signs this signature. unchecked on error or 318 * bogus if it did not validate. 319 */ 320 enum sec_status dnskey_verify_rrset_sig(struct regional* region, 321 struct sldns_buffer* buf, struct val_env* ve, time_t now, 322 struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, 323 size_t dnskey_idx, size_t sig_idx, 324 struct rbtree_type** sortree, int* buf_canon, 325 char** reason, sldns_ede_code *reason_bogus, 326 sldns_pkt_section section, struct module_qstate* qstate); 327 328 /** 329 * canonical compare for two tree entries 330 */ 331 int canonical_tree_compare(const void* k1, const void* k2); 332 333 /** 334 * Compare two rrsets and see if they are the same, canonicalised. 335 * The rrsets are not altered. 336 * @param region: temporary region. 337 * @param k1: rrset1 338 * @param k2: rrset2 339 * @return true if equal. 340 */ 341 int rrset_canonical_equal(struct regional* region, 342 struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2); 343 344 /** 345 * Canonicalize an rrset into the buffer. For an auth zone record, so 346 * this does not use a signature, or the RRSIG TTL or the wildcard label 347 * count from the RRSIG. 348 * @param region: temporary region. 349 * @param buf: the buffer to use. 350 * @param k: the rrset to insert. 351 * @return false on alloc error. 352 */ 353 int rrset_canonicalize_to_buffer(struct regional* region, 354 struct sldns_buffer* buf, struct ub_packed_rrset_key* k); 355 356 #endif /* VALIDATOR_VAL_SIGCRYPT_H */ 357