1238106Sdes/* 2238106Sdes * validator/val_sigcrypt.h - validator signature crypto functions. 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24266114Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25266114Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26266114Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27266114Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28266114Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29266114Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30266114Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31266114Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32266114Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33266114Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains helper functions for the validator module. 40238106Sdes * The functions help with signature verification and checking, the 41238106Sdes * bridging between RR wireformat data and crypto calls. 42238106Sdes */ 43238106Sdes 44238106Sdes#ifndef VALIDATOR_VAL_SIGCRYPT_H 45238106Sdes#define VALIDATOR_VAL_SIGCRYPT_H 46238106Sdes#include "util/data/packed_rrset.h" 47356345Scy#include "sldns/pkthdr.h" 48238106Sdesstruct val_env; 49238106Sdesstruct module_env; 50356345Scystruct module_qstate; 51238106Sdesstruct ub_packed_rrset_key; 52356345Scystruct rbtree_type; 53238106Sdesstruct regional; 54266114Sdesstruct sldns_buffer; 55238106Sdes 56238106Sdes/** number of entries in algorithm needs array */ 57238106Sdes#define ALGO_NEEDS_MAX 256 58238106Sdes 59238106Sdes/** 60238106Sdes * Storage for algorithm needs. DNSKEY algorithms. 61238106Sdes */ 62238106Sdesstruct algo_needs { 63238106Sdes /** the algorithms (8-bit) with each a number. 64238106Sdes * 0: not marked. 65238106Sdes * 1: marked 'necessary but not yet fulfilled' 66238106Sdes * 2: marked bogus. 67238106Sdes * Indexed by algorithm number. 68238106Sdes */ 69238106Sdes uint8_t needs[ALGO_NEEDS_MAX]; 70238106Sdes /** the number of entries in the array that are unfulfilled */ 71238106Sdes size_t num; 72238106Sdes}; 73238106Sdes 74238106Sdes/** 75238106Sdes * Initialize algo needs structure, set algos from rrset as needed. 76238106Sdes * Results are added to an existing need structure. 77238106Sdes * @param n: struct with storage. 78238106Sdes * @param dnskey: algos from this struct set as necessary. DNSKEY set. 79238106Sdes * @param sigalg: adds to signalled algorithm list too. 80238106Sdes */ 81238106Sdesvoid algo_needs_init_dnskey_add(struct algo_needs* n, 82238106Sdes struct ub_packed_rrset_key* dnskey, uint8_t* sigalg); 83238106Sdes 84238106Sdes/** 85238106Sdes * Initialize algo needs structure from a signalled algo list. 86238106Sdes * @param n: struct with storage. 87238106Sdes * @param sigalg: signalled algorithm list, numbers ends with 0. 88238106Sdes */ 89238106Sdesvoid algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg); 90238106Sdes 91238106Sdes/** 92238106Sdes * Initialize algo needs structure, set algos from rrset as needed. 93238106Sdes * @param n: struct with storage. 94238106Sdes * @param ds: algos from this struct set as necessary. DS set. 95238106Sdes * @param fav_ds_algo: filter to use only this DS algo. 96238106Sdes * @param sigalg: list of signalled algos, constructed as output, 97238106Sdes * provide size ALGO_NEEDS_MAX+1. list of algonumbers, ends with a zero. 98238106Sdes */ 99238106Sdesvoid algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds, 100238106Sdes int fav_ds_algo, uint8_t* sigalg); 101238106Sdes 102238106Sdes/** 103238106Sdes * Mark this algorithm as a success, sec_secure, and see if we are done. 104238106Sdes * @param n: storage structure processed. 105238106Sdes * @param algo: the algorithm processed to be secure. 106238106Sdes * @return if true, processing has finished successfully, we are satisfied. 107238106Sdes */ 108238106Sdesint algo_needs_set_secure(struct algo_needs* n, uint8_t algo); 109238106Sdes 110238106Sdes/** 111238106Sdes * Mark this algorithm a failure, sec_bogus. It can later be overridden 112238106Sdes * by a success for this algorithm (with a different signature). 113238106Sdes * @param n: storage structure processed. 114238106Sdes * @param algo: the algorithm processed to be bogus. 115238106Sdes */ 116238106Sdesvoid algo_needs_set_bogus(struct algo_needs* n, uint8_t algo); 117238106Sdes 118238106Sdes/** 119238106Sdes * See how many algorithms are missing (not bogus or secure, but not processed) 120238106Sdes * @param n: storage structure processed. 121238106Sdes * @return number of algorithms missing after processing. 122238106Sdes */ 123238106Sdessize_t algo_needs_num_missing(struct algo_needs* n); 124238106Sdes 125238106Sdes/** 126238106Sdes * See which algo is missing. 127238106Sdes * @param n: struct after processing. 128238106Sdes * @return if 0 an algorithm was bogus, if a number, this algorithm was 129238106Sdes * missing. So on 0, report why that was bogus, on number report a missing 130238106Sdes * algorithm. There could be multiple missing, this reports the first one. 131238106Sdes */ 132238106Sdesint algo_needs_missing(struct algo_needs* n); 133238106Sdes 134238106Sdes/** 135238106Sdes * Format error reason for algorithm missing. 136238106Sdes * @param env: module env with scratch for temp storage of string. 137238106Sdes * @param alg: DNSKEY-algorithm missing. 138238106Sdes * @param reason: destination. 139238106Sdes * @param s: string, appended with 'with algorithm ..'. 140238106Sdes */ 141238106Sdesvoid algo_needs_reason(struct module_env* env, int alg, char** reason, char* s); 142238106Sdes 143238106Sdes/** 144238106Sdes * Check if dnskey matches a DS digest 145238106Sdes * Does not check dnskey-keyid footprint, just the digest. 146238106Sdes * @param env: module environment. Uses scratch space. 147238106Sdes * @param dnskey_rrset: DNSKEY rrset. 148238106Sdes * @param dnskey_idx: index of RR in rrset. 149238106Sdes * @param ds_rrset: DS rrset 150238106Sdes * @param ds_idx: index of RR in DS rrset. 151238106Sdes * @return true if it matches, false on error, not supported or no match. 152238106Sdes */ 153238106Sdesint ds_digest_match_dnskey(struct module_env* env, 154238106Sdes struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, 155238106Sdes struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 156238106Sdes 157238106Sdes/** 158238106Sdes * Get dnskey keytag, footprint value 159238106Sdes * @param dnskey_rrset: DNSKEY rrset. 160238106Sdes * @param dnskey_idx: index of RR in rrset. 161238106Sdes * @return the keytag or 0 for badly formatted DNSKEYs. 162238106Sdes */ 163238106Sdesuint16_t dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, 164238106Sdes size_t dnskey_idx); 165238106Sdes 166238106Sdes/** 167238106Sdes * Get DS keytag, footprint value that matches the DNSKEY keytag it signs. 168238106Sdes * @param ds_rrset: DS rrset 169238106Sdes * @param ds_idx: index of RR in DS rrset. 170238106Sdes * @return the keytag or 0 for badly formatted DSs. 171238106Sdes */ 172238106Sdesuint16_t ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 173238106Sdes 174238106Sdes/** 175238106Sdes * See if DNSKEY algorithm is supported 176238106Sdes * @param dnskey_rrset: DNSKEY rrset. 177238106Sdes * @param dnskey_idx: index of RR in rrset. 178238106Sdes * @return true if supported. 179238106Sdes */ 180238106Sdesint dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset, 181238106Sdes size_t dnskey_idx); 182238106Sdes 183238106Sdes/** 184238106Sdes * See if DS digest algorithm is supported 185238106Sdes * @param ds_rrset: DS rrset 186238106Sdes * @param ds_idx: index of RR in DS rrset. 187238106Sdes * @return true if supported. 188238106Sdes */ 189238106Sdesint ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 190238106Sdes size_t ds_idx); 191238106Sdes 192238106Sdes/** 193238106Sdes * Get DS RR digest algorithm 194238106Sdes * @param ds_rrset: DS rrset. 195238106Sdes * @param ds_idx: which DS. 196238106Sdes * @return algorithm or 0 if DS too short. 197238106Sdes */ 198238106Sdesint ds_get_digest_algo(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); 199238106Sdes 200238106Sdes/** 201238106Sdes * See if DS key algorithm is supported 202238106Sdes * @param ds_rrset: DS rrset 203238106Sdes * @param ds_idx: index of RR in DS rrset. 204238106Sdes * @return true if supported. 205238106Sdes */ 206238106Sdesint ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 207238106Sdes size_t ds_idx); 208238106Sdes 209238106Sdes/** 210238106Sdes * Get DS RR key algorithm. This value should match with the DNSKEY algo. 211238106Sdes * @param k: DS rrset. 212238106Sdes * @param idx: which DS. 213238106Sdes * @return algorithm or 0 if DS too short. 214238106Sdes */ 215238106Sdesint ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx); 216238106Sdes 217238106Sdes/** 218238106Sdes * Get DNSKEY RR signature algorithm 219238106Sdes * @param k: DNSKEY rrset. 220238106Sdes * @param idx: which DNSKEY RR. 221238106Sdes * @return algorithm or 0 if DNSKEY too short. 222238106Sdes */ 223238106Sdesint dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx); 224238106Sdes 225238106Sdes/** 226238106Sdes * Get DNSKEY RR flags 227238106Sdes * @param k: DNSKEY rrset. 228238106Sdes * @param idx: which DNSKEY RR. 229238106Sdes * @return flags or 0 if DNSKEY too short. 230238106Sdes */ 231238106Sdesuint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx); 232238106Sdes 233238106Sdes/** 234238106Sdes * Verify rrset against dnskey rrset. 235238106Sdes * @param env: module environment, scratch space is used. 236238106Sdes * @param ve: validator environment, date settings. 237238106Sdes * @param rrset: to be validated. 238238106Sdes * @param dnskey: DNSKEY rrset, keyset to try. 239238106Sdes * @param sigalg: if nonNULL provide downgrade protection otherwise one 240238106Sdes * algorithm is enough. 241238106Sdes * @param reason: if bogus, a string returned, fixed or alloced in scratch. 242356345Scy * @param section: section of packet where this rrset comes from. 243356345Scy * @param qstate: qstate with region. 244238106Sdes * @return SECURE if one key in the set verifies one rrsig. 245238106Sdes * UNCHECKED on allocation errors, unsupported algorithms, malformed data, 246238106Sdes * and BOGUS on verification failures (no keys match any signatures). 247238106Sdes */ 248238106Sdesenum sec_status dnskeyset_verify_rrset(struct module_env* env, 249238106Sdes struct val_env* ve, struct ub_packed_rrset_key* rrset, 250356345Scy struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason, 251356345Scy sldns_pkt_section section, struct module_qstate* qstate); 252238106Sdes 253238106Sdes/** 254238106Sdes * verify rrset against one specific dnskey (from rrset) 255238106Sdes * @param env: module environment, scratch space is used. 256238106Sdes * @param ve: validator environment, date settings. 257238106Sdes * @param rrset: to be validated. 258238106Sdes * @param dnskey: DNSKEY rrset, keyset. 259238106Sdes * @param dnskey_idx: which key from the rrset to try. 260238106Sdes * @param reason: if bogus, a string returned, fixed or alloced in scratch. 261356345Scy * @param section: section of packet where this rrset comes from. 262356345Scy * @param qstate: qstate with region. 263238106Sdes * @return secure if *this* key signs any of the signatures on rrset. 264238106Sdes * unchecked on error or and bogus on bad signature. 265238106Sdes */ 266238106Sdesenum sec_status dnskey_verify_rrset(struct module_env* env, 267238106Sdes struct val_env* ve, struct ub_packed_rrset_key* rrset, 268356345Scy struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason, 269356345Scy sldns_pkt_section section, struct module_qstate* qstate); 270238106Sdes 271238106Sdes/** 272238106Sdes * verify rrset, with dnskey rrset, for a specific rrsig in rrset 273238106Sdes * @param env: module environment, scratch space is used. 274238106Sdes * @param ve: validator environment, date settings. 275238106Sdes * @param now: current time for validation (can be overridden). 276238106Sdes * @param rrset: to be validated. 277238106Sdes * @param dnskey: DNSKEY rrset, keyset to try. 278238106Sdes * @param sig_idx: which signature to try to validate. 279238106Sdes * @param sortree: reused sorted order. Stored in region. Pass NULL at start, 280238106Sdes * and for a new rrset. 281238106Sdes * @param reason: if bogus, a string returned, fixed or alloced in scratch. 282356345Scy * @param section: section of packet where this rrset comes from. 283356345Scy * @param qstate: qstate with region. 284238106Sdes * @return secure if any key signs *this* signature. bogus if no key signs it, 285238106Sdes * or unchecked on error. 286238106Sdes */ 287238106Sdesenum sec_status dnskeyset_verify_rrset_sig(struct module_env* env, 288266114Sdes struct val_env* ve, time_t now, struct ub_packed_rrset_key* rrset, 289238106Sdes struct ub_packed_rrset_key* dnskey, size_t sig_idx, 290356345Scy struct rbtree_type** sortree, char** reason, sldns_pkt_section section, 291356345Scy struct module_qstate* qstate); 292238106Sdes 293238106Sdes/** 294238106Sdes * verify rrset, with specific dnskey(from set), for a specific rrsig 295238106Sdes * @param region: scratch region used for temporary allocation. 296238106Sdes * @param buf: scratch buffer used for canonicalized rrset data. 297238106Sdes * @param ve: validator environment, date settings. 298238106Sdes * @param now: current time for validation (can be overridden). 299238106Sdes * @param rrset: to be validated. 300238106Sdes * @param dnskey: DNSKEY rrset, keyset. 301238106Sdes * @param dnskey_idx: which key from the rrset to try. 302238106Sdes * @param sig_idx: which signature to try to validate. 303238106Sdes * @param sortree: pass NULL at start, the sorted rrset order is returned. 304238106Sdes * pass it again for the same rrset. 305238106Sdes * @param buf_canon: if true, the buffer is already canonical. 306238106Sdes * pass false at start. pass old value only for same rrset and same 307238106Sdes * signature (but perhaps different key) for reuse. 308238106Sdes * @param reason: if bogus, a string returned, fixed or alloced in scratch. 309356345Scy * @param section: section of packet where this rrset comes from. 310356345Scy * @param qstate: qstate with region. 311238106Sdes * @return secure if this key signs this signature. unchecked on error or 312238106Sdes * bogus if it did not validate. 313238106Sdes */ 314238106Sdesenum sec_status dnskey_verify_rrset_sig(struct regional* region, 315266114Sdes struct sldns_buffer* buf, struct val_env* ve, time_t now, 316238106Sdes struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, 317238106Sdes size_t dnskey_idx, size_t sig_idx, 318356345Scy struct rbtree_type** sortree, int* buf_canon, char** reason, 319356345Scy sldns_pkt_section section, struct module_qstate* qstate); 320238106Sdes 321238106Sdes/** 322238106Sdes * canonical compare for two tree entries 323238106Sdes */ 324238106Sdesint canonical_tree_compare(const void* k1, const void* k2); 325238106Sdes 326266114Sdes/** 327266114Sdes * Compare two rrsets and see if they are the same, canonicalised. 328266114Sdes * The rrsets are not altered. 329266114Sdes * @param region: temporary region. 330266114Sdes * @param k1: rrset1 331266114Sdes * @param k2: rrset2 332266114Sdes * @return true if equal. 333266114Sdes */ 334266114Sdesint rrset_canonical_equal(struct regional* region, 335266114Sdes struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2); 336266114Sdes 337238106Sdes#endif /* VALIDATOR_VAL_SIGCRYPT_H */ 338