]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/unbound/validator/val_sigcrypt.h
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / contrib / unbound / validator / val_sigcrypt.h
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 */