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 LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * 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 struct val_env; 48 struct module_env; 49 struct ub_packed_rrset_key; 50 struct rbtree_t; 51 struct regional; 52 53 /** number of entries in algorithm needs array */ 54 #define ALGO_NEEDS_MAX 256 55 56 /** 57 * Storage for algorithm needs. DNSKEY algorithms. 58 */ 59 struct algo_needs { 60 /** the algorithms (8-bit) with each a number. 61 * 0: not marked. 62 * 1: marked 'necessary but not yet fulfilled' 63 * 2: marked bogus. 64 * Indexed by algorithm number. 65 */ 66 uint8_t needs[ALGO_NEEDS_MAX]; 67 /** the number of entries in the array that are unfulfilled */ 68 size_t num; 69 }; 70 71 /** 72 * Initialize algo needs structure, set algos from rrset as needed. 73 * Results are added to an existing need structure. 74 * @param n: struct with storage. 75 * @param dnskey: algos from this struct set as necessary. DNSKEY set. 76 * @param sigalg: adds to signalled algorithm list too. 77 */ 78 void algo_needs_init_dnskey_add(struct algo_needs* n, 79 struct ub_packed_rrset_key* dnskey, uint8_t* sigalg); 80 81 /** 82 * Initialize algo needs structure from a signalled algo list. 83 * @param n: struct with storage. 84 * @param sigalg: signalled algorithm list, numbers ends with 0. 85 */ 86 void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg); 87 88 /** 89 * Initialize algo needs structure, set algos from rrset as needed. 90 * @param n: struct with storage. 91 * @param ds: algos from this struct set as necessary. DS set. 92 * @param fav_ds_algo: filter to use only this DS algo. 93 * @param sigalg: list of signalled algos, constructed as output, 94 * provide size ALGO_NEEDS_MAX+1. list of algonumbers, ends with a zero. 95 */ 96 void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds, 97 int fav_ds_algo, uint8_t* sigalg); 98 99 /** 100 * Mark this algorithm as a success, sec_secure, and see if we are done. 101 * @param n: storage structure processed. 102 * @param algo: the algorithm processed to be secure. 103 * @return if true, processing has finished successfully, we are satisfied. 104 */ 105 int algo_needs_set_secure(struct algo_needs* n, uint8_t algo); 106 107 /** 108 * Mark this algorithm a failure, sec_bogus. It can later be overridden 109 * by a success for this algorithm (with a different signature). 110 * @param n: storage structure processed. 111 * @param algo: the algorithm processed to be bogus. 112 */ 113 void algo_needs_set_bogus(struct algo_needs* n, uint8_t algo); 114 115 /** 116 * See how many algorithms are missing (not bogus or secure, but not processed) 117 * @param n: storage structure processed. 118 * @return number of algorithms missing after processing. 119 */ 120 size_t algo_needs_num_missing(struct algo_needs* n); 121 122 /** 123 * See which algo is missing. 124 * @param n: struct after processing. 125 * @return if 0 an algorithm was bogus, if a number, this algorithm was 126 * missing. So on 0, report why that was bogus, on number report a missing 127 * algorithm. There could be multiple missing, this reports the first one. 128 */ 129 int algo_needs_missing(struct algo_needs* n); 130 131 /** 132 * Format error reason for algorithm missing. 133 * @param env: module env with scratch for temp storage of string. 134 * @param alg: DNSKEY-algorithm missing. 135 * @param reason: destination. 136 * @param s: string, appended with 'with algorithm ..'. 137 */ 138 void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s); 139 140 /** 141 * Check if dnskey matches a DS digest 142 * Does not check dnskey-keyid footprint, just the digest. 143 * @param env: module environment. Uses scratch space. 144 * @param dnskey_rrset: DNSKEY rrset. 145 * @param dnskey_idx: index of RR in rrset. 146 * @param ds_rrset: DS rrset 147 * @param ds_idx: index of RR in DS rrset. 148 * @return true if it matches, false on error, not supported or no match. 149 */ 150 int ds_digest_match_dnskey(struct module_env* env, 151 struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, 152 struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 153 154 /** 155 * Get dnskey keytag, footprint value 156 * @param dnskey_rrset: DNSKEY rrset. 157 * @param dnskey_idx: index of RR in rrset. 158 * @return the keytag or 0 for badly formatted DNSKEYs. 159 */ 160 uint16_t dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, 161 size_t dnskey_idx); 162 163 /** 164 * Get DS keytag, footprint value that matches the DNSKEY keytag it signs. 165 * @param ds_rrset: DS rrset 166 * @param ds_idx: index of RR in DS rrset. 167 * @return the keytag or 0 for badly formatted DSs. 168 */ 169 uint16_t ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 170 171 /** 172 * See if DNSKEY algorithm is supported 173 * @param dnskey_rrset: DNSKEY rrset. 174 * @param dnskey_idx: index of RR in rrset. 175 * @return true if supported. 176 */ 177 int dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset, 178 size_t dnskey_idx); 179 180 /** 181 * See if DS digest algorithm is supported 182 * @param ds_rrset: DS rrset 183 * @param ds_idx: index of RR in DS rrset. 184 * @return true if supported. 185 */ 186 int ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 187 size_t ds_idx); 188 189 /** 190 * Get DS RR digest algorithm 191 * @param ds_rrset: DS rrset. 192 * @param ds_idx: which DS. 193 * @return algorithm or 0 if DS too short. 194 */ 195 int ds_get_digest_algo(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 196 197 /** 198 * See if DS key algorithm is supported 199 * @param ds_rrset: DS rrset 200 * @param ds_idx: index of RR in DS rrset. 201 * @return true if supported. 202 */ 203 int ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 204 size_t ds_idx); 205 206 /** 207 * Get DS RR key algorithm. This value should match with the DNSKEY algo. 208 * @param k: DS rrset. 209 * @param idx: which DS. 210 * @return algorithm or 0 if DS too short. 211 */ 212 int ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx); 213 214 /** 215 * Get DNSKEY RR signature algorithm 216 * @param k: DNSKEY rrset. 217 * @param idx: which DNSKEY RR. 218 * @return algorithm or 0 if DNSKEY too short. 219 */ 220 int dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx); 221 222 /** 223 * Get DNSKEY RR flags 224 * @param k: DNSKEY rrset. 225 * @param idx: which DNSKEY RR. 226 * @return flags or 0 if DNSKEY too short. 227 */ 228 uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx); 229 230 /** 231 * Verify rrset against dnskey rrset. 232 * @param env: module environment, scratch space is used. 233 * @param ve: validator environment, date settings. 234 * @param rrset: to be validated. 235 * @param dnskey: DNSKEY rrset, keyset to try. 236 * @param sigalg: if nonNULL provide downgrade protection otherwise one 237 * algorithm is enough. 238 * @param reason: if bogus, a string returned, fixed or alloced in scratch. 239 * @return SECURE if one key in the set verifies one rrsig. 240 * UNCHECKED on allocation errors, unsupported algorithms, malformed data, 241 * and BOGUS on verification failures (no keys match any signatures). 242 */ 243 enum sec_status dnskeyset_verify_rrset(struct module_env* env, 244 struct val_env* ve, struct ub_packed_rrset_key* rrset, 245 struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason); 246 247 /** 248 * verify rrset against one specific dnskey (from rrset) 249 * @param env: module environment, scratch space is used. 250 * @param ve: validator environment, date settings. 251 * @param rrset: to be validated. 252 * @param dnskey: DNSKEY rrset, keyset. 253 * @param dnskey_idx: which key from the rrset to try. 254 * @param reason: if bogus, a string returned, fixed or alloced in scratch. 255 * @return secure if *this* key signs any of the signatures on rrset. 256 * unchecked on error or and bogus on bad signature. 257 */ 258 enum sec_status dnskey_verify_rrset(struct module_env* env, 259 struct val_env* ve, struct ub_packed_rrset_key* rrset, 260 struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason); 261 262 /** 263 * verify rrset, with dnskey rrset, for a specific rrsig in rrset 264 * @param env: module environment, scratch space is used. 265 * @param ve: validator environment, date settings. 266 * @param now: current time for validation (can be overridden). 267 * @param rrset: to be validated. 268 * @param dnskey: DNSKEY rrset, keyset to try. 269 * @param sig_idx: which signature to try to validate. 270 * @param sortree: reused sorted order. Stored in region. Pass NULL at start, 271 * and for a new rrset. 272 * @param reason: if bogus, a string returned, fixed or alloced in scratch. 273 * @return secure if any key signs *this* signature. bogus if no key signs it, 274 * or unchecked on error. 275 */ 276 enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env, 277 struct val_env* ve, uint32_t now, struct ub_packed_rrset_key* rrset, 278 struct ub_packed_rrset_key* dnskey, size_t sig_idx, 279 struct rbtree_t** sortree, char** reason); 280 281 /** 282 * verify rrset, with specific dnskey(from set), for a specific rrsig 283 * @param region: scratch region used for temporary allocation. 284 * @param buf: scratch buffer used for canonicalized rrset data. 285 * @param ve: validator environment, date settings. 286 * @param now: current time for validation (can be overridden). 287 * @param rrset: to be validated. 288 * @param dnskey: DNSKEY rrset, keyset. 289 * @param dnskey_idx: which key from the rrset to try. 290 * @param sig_idx: which signature to try to validate. 291 * @param sortree: pass NULL at start, the sorted rrset order is returned. 292 * pass it again for the same rrset. 293 * @param buf_canon: if true, the buffer is already canonical. 294 * pass false at start. pass old value only for same rrset and same 295 * signature (but perhaps different key) for reuse. 296 * @param reason: if bogus, a string returned, fixed or alloced in scratch. 297 * @return secure if this key signs this signature. unchecked on error or 298 * bogus if it did not validate. 299 */ 300 enum sec_status dnskey_verify_rrset_sig(struct regional* region, 301 ldns_buffer* buf, struct val_env* ve, uint32_t now, 302 struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, 303 size_t dnskey_idx, size_t sig_idx, 304 struct rbtree_t** sortree, int* buf_canon, char** reason); 305 306 /** 307 * canonical compare for two tree entries 308 */ 309 int canonical_tree_compare(const void* k1, const void* k2); 310 311 #endif /* VALIDATOR_VAL_SIGCRYPT_H */ 312