xref: /openbsd/usr.sbin/nsd/tsig.h (revision 898184e3)
1 /*
2  * tsig.h -- TSIG definitions (RFC 2845).
3  *
4  * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 #ifndef _TSIG_H_
11 #define _TSIG_H_
12 
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netdb.h>
16 
17 #include "buffer.h"
18 #include "dname.h"
19 
20 #define TSIG_ERROR_NOERROR  0
21 #define TSIG_ERROR_BADSIG   16
22 #define TSIG_ERROR_BADKEY   17
23 #define TSIG_ERROR_BADTIME  18
24 
25 #define TSIG_HMAC_MD5       157
26 #define TSIG_HMAC_SHA1      158
27 #define TSIG_HMAC_SHA256    159
28 
29 typedef struct tsig_algorithm tsig_algorithm_type;
30 typedef struct tsig_key tsig_key_type;
31 typedef struct tsig_record tsig_record_type;
32 
33 enum tsig_status
34 {
35 	TSIG_NOT_PRESENT,
36 	TSIG_OK,
37 	TSIG_ERROR
38 };
39 typedef enum tsig_status tsig_status_type;
40 
41 struct tsig_lookup_struct_table
42 {
43 	uint8_t id;
44 	const char* short_name;
45 };
46 typedef struct tsig_lookup_struct_table tsig_lookup_algorithm_table;
47 
48 /*
49  * A TSIG HMAC algorithm, such as hmac-md5.
50  */
51 struct tsig_algorithm
52 {
53 	/*
54 	 * Short name of the algorithm, such as "hmac-md5".
55 	 */
56 	const char *short_name;
57 
58 	/*
59 	 * Full wireformat name of the algorithm, such as
60 	 * "hmac-md5.sig-alg.reg.int."
61 	 */
62 	const dname_type *wireformat_name;
63 
64 	/*
65 	 * The maximum size of a digest generated by this algorithm.
66 	 */
67 	size_t maximum_digest_size;
68 
69 	/*
70 	 * Algorithm implementation specific data.
71 	 */
72 	const void *data;
73 
74 	/*
75 	 * Create a new HMAC context.
76 	 */
77 	void *(*hmac_create_context)(region_type *region);
78 
79 	/*
80 	 * Initialize an HMAC context with the specified algorithm and
81 	 * key.
82 	 */
83 	void  (*hmac_init_context)(void *context,
84 				   tsig_algorithm_type *algorithm,
85 				   tsig_key_type *key);
86 
87 	/*
88 	 * Update the HMAC context with the specified data.
89 	 */
90 	void  (*hmac_update)(void *context, const void *data, size_t size);
91 
92 	/*
93 	 * Generate the final digest.  DIGEST points to a buffer of at
94 	 * least maximum_digest_size bytes.
95 	 */
96 	void  (*hmac_final)(void *context, uint8_t *digest, size_t *size);
97 };
98 
99 /*
100  * A TSIG key used to sign and verify packets.
101  */
102 struct tsig_key
103 {
104 	const dname_type *name;
105 	size_t            size;
106 	const uint8_t    *data;
107 };
108 
109 struct tsig_record
110 {
111 	tsig_status_type     status;
112 	size_t               position;
113 	size_t               response_count;
114 	size_t               updates_since_last_prepare;
115 	void                *context;
116 	tsig_algorithm_type *algorithm;
117 	tsig_key_type       *key;
118 	size_t               prior_mac_size;
119 	uint8_t             *prior_mac_data;
120 
121 	/* TSIG RR data is allocated in the rr_region.  */
122 	region_type      *rr_region;
123 	region_type	 *context_region;
124 	const dname_type *key_name;
125 	const dname_type *algorithm_name;
126 	uint16_t          signed_time_high;
127 	uint32_t          signed_time_low;
128 	uint16_t          signed_time_fudge;
129 	uint16_t          mac_size;
130 	uint8_t          *mac_data;
131 	uint16_t          original_query_id;
132 	uint16_t          error_code;
133 	uint16_t          other_size;
134 	uint8_t          *other_data;
135 };
136 
137 /*
138  * Initialize the TSIG module (including TSIG implementation modules
139  * such as tsig-openssl).
140  */
141 int tsig_init(region_type *region);
142 
143 /*
144  * Add the specified key to the TSIG key table.
145  */
146 void tsig_add_key(tsig_key_type *key);
147 
148 /*
149  * Add the specified algorithm to the TSIG algorithm table.
150  */
151 void tsig_add_algorithm(tsig_algorithm_type *algorithm);
152 
153 /*
154  * Find an HMAC algorithm based on its short name.
155  */
156 tsig_algorithm_type *tsig_get_algorithm_by_name(const char *name);
157 
158 /*
159  * Return a descriptive error message based on the TSIG error code.
160  */
161 const char *tsig_error(int error_code);
162 
163 /*
164  * Create the tsig record internal structure. Allocs it.
165  * Call init_record afterwards before doing more with it.
166  *
167  * The region is used to attach a cleanup function that destroys the tsig.
168  */
169 void tsig_create_record(tsig_record_type* tsig,
170 			region_type* region);
171 
172 /*
173  * Like tsig_create_record, with custom region settings.
174  * The size params are used to customise the rr_region and context_region.
175  */
176 void tsig_create_record_custom(tsig_record_type* tsig,
177 			region_type* region,
178 			size_t chunk_size,
179 			size_t large_object_size,
180 			size_t initial_cleanup_size);
181 
182 /*
183  * Call this before starting to analyze or signing a sequence of
184  * packets.
185  *
186  * ALGORITHM and KEY are optional and are only needed if you want to
187  * sign the initial query.  Otherwise the key and algorithm are looked
188  * up in the algorithm and key table when a received TSIG RR is
189  * processed.
190  */
191 void tsig_init_record(tsig_record_type *data,
192 		      tsig_algorithm_type *algorithm,
193 		      tsig_key_type *key);
194 
195 /*
196  * Validate the TSIG RR key and algorithm from the TSIG RR.  Otherwise
197  * update the TSIG error code.  The MAC itself is not validated.
198  *
199  * Returns non-zero if the key and algorithm could be validated.
200  */
201 int tsig_from_query(tsig_record_type *tsig);
202 
203 /*
204  * Prepare TSIG for signing of a query.  This initializes TSIG with
205  * the algorithm and key stored in the TSIG record.
206  */
207 void tsig_init_query(tsig_record_type *tsig, uint16_t original_query_id);
208 
209 /*
210  * Prepare TSIG for performing an HMAC calculation.  If the TSIG
211  * contains a prior HMAC it is inserted first into the hash
212  * calculation.
213  */
214 void tsig_prepare(tsig_record_type *tsig);
215 
216 /*
217  * Add the first LENGTH octets of PACKET to the TSIG hash, replacing
218  * the PACKET's id with the original query id from TSIG.  If the query
219  * is a response the TSIG response count is incremented.
220  */
221 void tsig_update(tsig_record_type *tsig, buffer_type *packet, size_t length);
222 
223 /*
224  * Finalize the TSIG record by hashing the TSIG data.  If the TSIG
225  * response count is greater than 1 only the timers are hashed.
226  * Signed time is set to the current time.  The TSIG record can be
227  * added to a packet using tsig_append_rr().
228  *
229  * The calculated MAC is also stored as the prior MAC, so it can be
230  * used as a running MAC.
231  */
232 void tsig_sign(tsig_record_type *tsig);
233 
234 /*
235  * Verify the calculated MAC against the MAC in the TSIG RR.
236  *
237  * The calculated MAC is also stored as the prior MAC, so it can be
238  * used as a running MAC.
239  */
240 int tsig_verify(tsig_record_type *tsig);
241 
242 /*
243  * Find the TSIG RR in QUERY and parse it if present.  Store the
244  * parsed results in TSIG.
245  *
246  * Returns non-zero if no parsing error occurred, use the tsig->status
247  * field to find out if the TSIG record was present.
248  */
249 int tsig_find_rr(tsig_record_type *tsig, buffer_type *packet);
250 
251 /*
252  * Call this to analyze the TSIG RR starting at the current location
253  * of PACKET. On success true is returned and the results are stored
254  * in TSIG.
255  *
256  * Returns non-zero if no parsing error occurred, use the tsig->status
257  * field to find out if the TSIG record was present.
258  */
259 int tsig_parse_rr(tsig_record_type *tsig, buffer_type *packet);
260 
261 /*
262  * Append the TSIG record to the response PACKET.
263  */
264 void tsig_append_rr(tsig_record_type *tsig, buffer_type *packet);
265 
266 /*
267  * The amount of space to reserve in the response for the TSIG data
268  * (if required).
269  */
270 size_t tsig_reserved_space(tsig_record_type *tsig);
271 
272 /*
273  * status or error_code must already be in error.
274  * prepares content for error packet.
275  */
276 void tsig_error_reply(tsig_record_type *tsig);
277 
278 /*
279  * compare tsig algorithm names case insensitive.
280  */
281 int tsig_strlowercmp(const char* str1, const char* str2);
282 
283 /*
284  * cleanup tsig openssl stuff.
285  */
286 void tsig_finalize(void);
287 
288 #endif /* _TSIG_H_ */
289