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