Home | History | Annotate | Line # | Download | only in validator
      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 (RFC8914) 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