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