1317692Sdim/* 2317692Sdim * validator/val_sigcrypt.h - validator signature crypto functions. 3317692Sdim * 4317692Sdim * Copyright (c) 2007, NLnet Labs. All rights reserved. 5317692Sdim * 6317692Sdim * This software is open source. 7317692Sdim * 8317692Sdim * Redistribution and use in source and binary forms, with or without 9317692Sdim * modification, are permitted provided that the following conditions 10317692Sdim * are met: 11317692Sdim * 12317692Sdim * Redistributions of source code must retain the above copyright notice, 13321238Sdim * this list of conditions and the following disclaimer. 14318384Sdim * 15317692Sdim * Redistributions in binary form must reproduce the above copyright notice, 16317692Sdim * this list of conditions and the following disclaimer in the documentation 17317692Sdim * and/or other materials provided with the distribution. 18317692Sdim * 19318384Sdim * Neither the name of the NLNET LABS nor the names of its contributors may 20317692Sdim * be used to endorse or promote products derived from this software without 21317692Sdim * specific prior written permission. 22317969Sdim * 23317969Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24317969Sdim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25317969Sdim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26317969Sdim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27317692Sdim * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28317692Sdim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29341825Sdim * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30317692Sdim * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31327952Sdim * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32327952Sdim * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33317692Sdim * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34317692Sdim */ 35317692Sdim 36317692Sdim/** 37341825Sdim * \file 38317692Sdim * 39317692Sdim * This file contains helper functions for the validator module. 40317692Sdim * The functions help with signature verification and checking, the 41317692Sdim * bridging between RR wireformat data and crypto calls. 42317692Sdim */ 43317692Sdim 44341825Sdim#ifndef VALIDATOR_VAL_SIGCRYPT_H 45317692Sdim#define VALIDATOR_VAL_SIGCRYPT_H 46317692Sdim#include "util/data/packed_rrset.h" 47317692Sdimstruct val_env; 48317692Sdimstruct module_env; 49317692Sdimstruct ub_packed_rrset_key; 50317692Sdimstruct rbtree_t; 51317692Sdimstruct regional; 52317692Sdimstruct sldns_buffer; 53317692Sdim 54317692Sdim/** number of entries in algorithm needs array */ 55317692Sdim#define ALGO_NEEDS_MAX 256 56317692Sdim 57317692Sdim/** 58317692Sdim * Storage for algorithm needs. DNSKEY algorithms. 59317692Sdim */ 60317692Sdimstruct algo_needs { 61317692Sdim /** the algorithms (8-bit) with each a number. 62317692Sdim * 0: not marked. 63317692Sdim * 1: marked 'necessary but not yet fulfilled' 64317692Sdim * 2: marked bogus. 65317692Sdim * Indexed by algorithm number. 66317692Sdim */ 67317692Sdim uint8_t needs[ALGO_NEEDS_MAX]; 68317692Sdim /** the number of entries in the array that are unfulfilled */ 69317692Sdim size_t num; 70317692Sdim}; 71317692Sdim 72317969Sdim/** 73317969Sdim * Initialize algo needs structure, set algos from rrset as needed. 74317692Sdim * Results are added to an existing need structure. 75318384Sdim * @param n: struct with storage. 76317969Sdim * @param dnskey: algos from this struct set as necessary. DNSKEY set. 77317692Sdim * @param sigalg: adds to signalled algorithm list too. 78317692Sdim */ 79317692Sdimvoid algo_needs_init_dnskey_add(struct algo_needs* n, 80317692Sdim struct ub_packed_rrset_key* dnskey, uint8_t* sigalg); 81317692Sdim 82317692Sdim/** 83317692Sdim * Initialize algo needs structure from a signalled algo list. 84317692Sdim * @param n: struct with storage. 85317692Sdim * @param sigalg: signalled algorithm list, numbers ends with 0. 86317692Sdim */ 87327952Sdimvoid algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg); 88317692Sdim 89317692Sdim/** 90317692Sdim * Initialize algo needs structure, set algos from rrset as needed. 91317692Sdim * @param n: struct with storage. 92317692Sdim * @param ds: algos from this struct set as necessary. DS set. 93317692Sdim * @param fav_ds_algo: filter to use only this DS algo. 94317692Sdim * @param sigalg: list of signalled algos, constructed as output, 95317692Sdim * provide size ALGO_NEEDS_MAX+1. list of algonumbers, ends with a zero. 96317692Sdim */ 97317692Sdimvoid algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds, 98317969Sdim int fav_ds_algo, uint8_t* sigalg); 99317969Sdim 100317692Sdim/** 101317692Sdim * Mark this algorithm as a success, sec_secure, and see if we are done. 102318384Sdim * @param n: storage structure processed. 103317969Sdim * @param algo: the algorithm processed to be secure. 104317692Sdim * @return if true, processing has finished successfully, we are satisfied. 105317692Sdim */ 106317692Sdimint algo_needs_set_secure(struct algo_needs* n, uint8_t algo); 107317692Sdim 108317969Sdim/** 109317969Sdim * Mark this algorithm a failure, sec_bogus. It can later be overridden 110317692Sdim * by a success for this algorithm (with a different signature). 111344779Sdim * @param n: storage structure processed. 112344779Sdim * @param algo: the algorithm processed to be bogus. 113344779Sdim */ 114344779Sdimvoid algo_needs_set_bogus(struct algo_needs* n, uint8_t algo); 115344779Sdim 116344779Sdim/** 117344779Sdim * See how many algorithms are missing (not bogus or secure, but not processed) 118344779Sdim * @param n: storage structure processed. 119318384Sdim * @return number of algorithms missing after processing. 120317692Sdim */ 121317692Sdimsize_t algo_needs_num_missing(struct algo_needs* n); 122317969Sdim 123317692Sdim/** 124317692Sdim * See which algo is missing. 125317692Sdim * @param n: struct after processing. 126317692Sdim * @return if 0 an algorithm was bogus, if a number, this algorithm was 127317969Sdim * missing. So on 0, report why that was bogus, on number report a missing 128317969Sdim * algorithm. There could be multiple missing, this reports the first one. 129317969Sdim */ 130317969Sdimint algo_needs_missing(struct algo_needs* n); 131317969Sdim 132317969Sdim/** 133317969Sdim * Format error reason for algorithm missing. 134317969Sdim * @param env: module env with scratch for temp storage of string. 135317969Sdim * @param alg: DNSKEY-algorithm missing. 136317969Sdim * @param reason: destination. 137317692Sdim * @param s: string, appended with 'with algorithm ..'. 138317692Sdim */ 139317692Sdimvoid algo_needs_reason(struct module_env* env, int alg, char** reason, char* s); 140317969Sdim 141327952Sdim/** 142317969Sdim * Check if dnskey matches a DS digest 143317969Sdim * Does not check dnskey-keyid footprint, just the digest. 144317692Sdim * @param env: module environment. Uses scratch space. 145317692Sdim * @param dnskey_rrset: DNSKEY rrset. 146317692Sdim * @param dnskey_idx: index of RR in rrset. 147317692Sdim * @param ds_rrset: DS rrset 148317692Sdim * @param ds_idx: index of RR in DS rrset. 149317692Sdim * @return true if it matches, false on error, not supported or no match. 150317692Sdim */ 151317692Sdimint ds_digest_match_dnskey(struct module_env* env, 152317692Sdim struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, 153317692Sdim struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 154317692Sdim 155317969Sdim/** 156317692Sdim * Get dnskey keytag, footprint value 157317692Sdim * @param dnskey_rrset: DNSKEY rrset. 158317692Sdim * @param dnskey_idx: index of RR in rrset. 159317692Sdim * @return the keytag or 0 for badly formatted DNSKEYs. 160317692Sdim */ 161327952Sdimuint16_t dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, 162318384Sdim size_t dnskey_idx); 163327952Sdim 164327952Sdim/** 165327952Sdim * Get DS keytag, footprint value that matches the DNSKEY keytag it signs. 166327952Sdim * @param ds_rrset: DS rrset 167327952Sdim * @param ds_idx: index of RR in DS rrset. 168327952Sdim * @return the keytag or 0 for badly formatted DSs. 169317692Sdim */ 170317692Sdimuint16_t ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 171317692Sdim 172317692Sdim/** 173317692Sdim * See if DNSKEY algorithm is supported 174317692Sdim * @param dnskey_rrset: DNSKEY rrset. 175317692Sdim * @param dnskey_idx: index of RR in rrset. 176327952Sdim * @return true if supported. 177327952Sdim */ 178327952Sdimint dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset, 179327952Sdim size_t dnskey_idx); 180327952Sdim 181327952Sdim/** 182327952Sdim * See if DS digest algorithm is supported 183327952Sdim * @param ds_rrset: DS rrset 184327952Sdim * @param ds_idx: index of RR in DS rrset. 185327952Sdim * @return true if supported. 186327952Sdim */ 187327952Sdimint ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 188327952Sdim size_t ds_idx); 189317692Sdim 190318384Sdim/** 191317692Sdim * Get DS RR digest algorithm 192318384Sdim * @param ds_rrset: DS rrset. 193317692Sdim * @param ds_idx: which DS. 194317692Sdim * @return algorithm or 0 if DS too short. 195318384Sdim */ 196317692Sdimint ds_get_digest_algo(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 197317692Sdim 198317692Sdim/** 199317692Sdim * See if DS key algorithm is supported 200317692Sdim * @param ds_rrset: DS rrset 201317692Sdim * @param ds_idx: index of RR in DS rrset. 202317692Sdim * @return true if supported. 203317692Sdim */ 204317692Sdimint ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 205317692Sdim size_t ds_idx); 206317692Sdim 207317692Sdim/** 208317692Sdim * Get DS RR key algorithm. This value should match with the DNSKEY algo. 209317692Sdim * @param k: DS rrset. 210318384Sdim * @param idx: which DS. 211317692Sdim * @return algorithm or 0 if DS too short. 212318384Sdim */ 213317692Sdimint ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx); 214317969Sdim 215317692Sdim/** 216317969Sdim * Get DNSKEY RR signature algorithm 217327952Sdim * @param k: DNSKEY rrset. 218341825Sdim * @param idx: which DNSKEY RR. 219341825Sdim * @return algorithm or 0 if DNSKEY too short. 220320970Sdim */ 221320970Sdimint dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx); 222320970Sdim 223320970Sdim/** 224320970Sdim * Get DNSKEY RR flags 225320970Sdim * @param k: DNSKEY rrset. 226320970Sdim * @param idx: which DNSKEY RR. 227320970Sdim * @return flags or 0 if DNSKEY too short. 228317969Sdim */ 229317692Sdimuint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx); 230327952Sdim 231317692Sdim/** 232317969Sdim * Verify rrset against dnskey rrset. 233317969Sdim * @param env: module environment, scratch space is used. 234317692Sdim * @param ve: validator environment, date settings. 235317692Sdim * @param rrset: to be validated. 236317969Sdim * @param dnskey: DNSKEY rrset, keyset to try. 237317969Sdim * @param sigalg: if nonNULL provide downgrade protection otherwise one 238317692Sdim * algorithm is enough. 239317692Sdim * @param reason: if bogus, a string returned, fixed or alloced in scratch. 240320970Sdim * @return SECURE if one key in the set verifies one rrsig. 241320970Sdim * UNCHECKED on allocation errors, unsupported algorithms, malformed data, 242320970Sdim * and BOGUS on verification failures (no keys match any signatures). 243320970Sdim */ 244320970Sdimenum sec_status dnskeyset_verify_rrset(struct module_env* env, 245320970Sdim struct val_env* ve, struct ub_packed_rrset_key* rrset, 246317692Sdim struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason); 247317692Sdim 248320970Sdim/** 249320970Sdim * verify rrset against one specific dnskey (from rrset) 250317692Sdim * @param env: module environment, scratch space is used. 251317692Sdim * @param ve: validator environment, date settings. 252317692Sdim * @param rrset: to be validated. 253317692Sdim * @param dnskey: DNSKEY rrset, keyset. 254317969Sdim * @param dnskey_idx: which key from the rrset to try. 255317969Sdim * @param reason: if bogus, a string returned, fixed or alloced in scratch. 256317969Sdim * @return secure if *this* key signs any of the signatures on rrset. 257317969Sdim * unchecked on error or and bogus on bad signature. 258317969Sdim */ 259317969Sdimenum sec_status dnskey_verify_rrset(struct module_env* env, 260317692Sdim struct val_env* ve, struct ub_packed_rrset_key* rrset, 261317969Sdim struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason); 262317969Sdim 263317969Sdim/** 264317692Sdim * verify rrset, with dnskey rrset, for a specific rrsig in rrset 265317692Sdim * @param env: module environment, scratch space is used. 266317692Sdim * @param ve: validator environment, date settings. 267317692Sdim * @param now: current time for validation (can be overridden). 268318384Sdim * @param rrset: to be validated. 269318384Sdim * @param dnskey: DNSKEY rrset, keyset to try. 270318384Sdim * @param sig_idx: which signature to try to validate. 271341825Sdim * @param sortree: reused sorted order. Stored in region. Pass NULL at start, 272317692Sdim * and for a new rrset. 273317692Sdim * @param reason: if bogus, a string returned, fixed or alloced in scratch. 274317692Sdim * @return secure if any key signs *this* signature. bogus if no key signs it, 275317692Sdim * or unchecked on error. 276317692Sdim */ 277317692Sdimenum sec_status dnskeyset_verify_rrset_sig(struct module_env* env, 278317692Sdim struct val_env* ve, time_t now, struct ub_packed_rrset_key* rrset, 279317692Sdim struct ub_packed_rrset_key* dnskey, size_t sig_idx, 280317692Sdim struct rbtree_t** sortree, char** reason); 281317692Sdim 282317692Sdim/** 283317692Sdim * verify rrset, with specific dnskey(from set), for a specific rrsig 284317692Sdim * @param region: scratch region used for temporary allocation. 285317692Sdim * @param buf: scratch buffer used for canonicalized rrset data. 286317692Sdim * @param ve: validator environment, date settings. 287317692Sdim * @param now: current time for validation (can be overridden). 288317692Sdim * @param rrset: to be validated. 289317692Sdim * @param dnskey: DNSKEY rrset, keyset. 290317692Sdim * @param dnskey_idx: which key from the rrset to try. 291317692Sdim * @param sig_idx: which signature to try to validate. 292317692Sdim * @param sortree: pass NULL at start, the sorted rrset order is returned. 293317692Sdim * pass it again for the same rrset. 294341825Sdim * @param buf_canon: if true, the buffer is already canonical. 295317692Sdim * pass false at start. pass old value only for same rrset and same 296318384Sdim * signature (but perhaps different key) for reuse. 297317692Sdim * @param reason: if bogus, a string returned, fixed or alloced in scratch. 298317692Sdim * @return secure if this key signs this signature. unchecked on error or 299317692Sdim * bogus if it did not validate. 300317692Sdim */ 301317692Sdimenum sec_status dnskey_verify_rrset_sig(struct regional* region, 302317692Sdim struct sldns_buffer* buf, struct val_env* ve, time_t now, 303317692Sdim struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, 304317692Sdim size_t dnskey_idx, size_t sig_idx, 305317692Sdim struct rbtree_t** sortree, int* buf_canon, char** reason); 306317692Sdim 307317692Sdim/** 308317692Sdim * canonical compare for two tree entries 309317692Sdim */ 310317692Sdimint canonical_tree_compare(const void* k1, const void* k2); 311317692Sdim 312317692Sdim/** 313317692Sdim * Compare two rrsets and see if they are the same, canonicalised. 314317692Sdim * The rrsets are not altered. 315317969Sdim * @param region: temporary region. 316317969Sdim * @param k1: rrset1 317317969Sdim * @param k2: rrset2 318344779Sdim * @return true if equal. 319317969Sdim */ 320317969Sdimint rrset_canonical_equal(struct regional* region, 321317969Sdim struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2); 322317969Sdim 323317969Sdim#endif /* VALIDATOR_VAL_SIGCRYPT_H */ 324317969Sdim