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