xref: /openbsd-src/usr.sbin/nsd/tsig.h (revision 3efee2e132f9af6db74577d714f3304be2b3af74)
162ac0c33Sjakob /*
262ac0c33Sjakob  * tsig.h -- TSIG definitions (RFC 2845).
362ac0c33Sjakob  *
4d3fecca9Ssthen  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob  *
662ac0c33Sjakob  * See LICENSE for the license.
762ac0c33Sjakob  *
862ac0c33Sjakob  */
962ac0c33Sjakob 
10*3efee2e1Sflorian #ifndef TSIG_H
11*3efee2e1Sflorian #define TSIG_H
1262ac0c33Sjakob 
1362ac0c33Sjakob #include <sys/types.h>
1462ac0c33Sjakob #include <sys/socket.h>
1562ac0c33Sjakob #include <netdb.h>
1662ac0c33Sjakob 
1762ac0c33Sjakob #include "buffer.h"
1862ac0c33Sjakob #include "dname.h"
1962ac0c33Sjakob 
2062ac0c33Sjakob #define TSIG_ERROR_NOERROR  0
2162ac0c33Sjakob #define TSIG_ERROR_BADSIG   16
2262ac0c33Sjakob #define TSIG_ERROR_BADKEY   17
2362ac0c33Sjakob #define TSIG_ERROR_BADTIME  18
2462ac0c33Sjakob 
2562ac0c33Sjakob typedef struct tsig_algorithm tsig_algorithm_type;
2662ac0c33Sjakob typedef struct tsig_key tsig_key_type;
2762ac0c33Sjakob typedef struct tsig_record tsig_record_type;
2862ac0c33Sjakob 
2962ac0c33Sjakob enum tsig_status
3062ac0c33Sjakob {
3162ac0c33Sjakob 	TSIG_NOT_PRESENT,
3262ac0c33Sjakob 	TSIG_OK,
3362ac0c33Sjakob 	TSIG_ERROR
3462ac0c33Sjakob };
3562ac0c33Sjakob typedef enum tsig_status tsig_status_type;
3662ac0c33Sjakob 
3762ac0c33Sjakob struct tsig_lookup_struct_table
3862ac0c33Sjakob {
3962ac0c33Sjakob 	uint8_t id;
4062ac0c33Sjakob 	const char* short_name;
4162ac0c33Sjakob };
4262ac0c33Sjakob typedef struct tsig_lookup_struct_table tsig_lookup_algorithm_table;
4362ac0c33Sjakob 
4462ac0c33Sjakob /*
4562ac0c33Sjakob  * A TSIG HMAC algorithm, such as hmac-md5.
4662ac0c33Sjakob  */
4762ac0c33Sjakob struct tsig_algorithm
4862ac0c33Sjakob {
4962ac0c33Sjakob 	/*
5062ac0c33Sjakob 	 * Short name of the algorithm, such as "hmac-md5".
5162ac0c33Sjakob 	 */
5262ac0c33Sjakob 	const char *short_name;
5362ac0c33Sjakob 
5462ac0c33Sjakob 	/*
5562ac0c33Sjakob 	 * Full wireformat name of the algorithm, such as
5662ac0c33Sjakob 	 * "hmac-md5.sig-alg.reg.int."
5762ac0c33Sjakob 	 */
5862ac0c33Sjakob 	const dname_type *wireformat_name;
5962ac0c33Sjakob 
6062ac0c33Sjakob 	/*
6162ac0c33Sjakob 	 * The maximum size of a digest generated by this algorithm.
6262ac0c33Sjakob 	 */
6362ac0c33Sjakob 	size_t maximum_digest_size;
6462ac0c33Sjakob 
6562ac0c33Sjakob 	/*
6662ac0c33Sjakob 	 * Algorithm implementation specific data.
6762ac0c33Sjakob 	 */
6862ac0c33Sjakob 	const void *data;
6962ac0c33Sjakob 
7062ac0c33Sjakob 	/*
7162ac0c33Sjakob 	 * Create a new HMAC context.
7262ac0c33Sjakob 	 */
7362ac0c33Sjakob 	void *(*hmac_create_context)(region_type *region);
7462ac0c33Sjakob 
7562ac0c33Sjakob 	/*
7662ac0c33Sjakob 	 * Initialize an HMAC context with the specified algorithm and
7762ac0c33Sjakob 	 * key.
7862ac0c33Sjakob 	 */
7962ac0c33Sjakob 	void  (*hmac_init_context)(void *context,
8062ac0c33Sjakob 				   tsig_algorithm_type *algorithm,
8162ac0c33Sjakob 				   tsig_key_type *key);
8262ac0c33Sjakob 
8362ac0c33Sjakob 	/*
8462ac0c33Sjakob 	 * Update the HMAC context with the specified data.
8562ac0c33Sjakob 	 */
8662ac0c33Sjakob 	void  (*hmac_update)(void *context, const void *data, size_t size);
8762ac0c33Sjakob 
8862ac0c33Sjakob 	/*
8962ac0c33Sjakob 	 * Generate the final digest.  DIGEST points to a buffer of at
9062ac0c33Sjakob 	 * least maximum_digest_size bytes.
9162ac0c33Sjakob 	 */
9262ac0c33Sjakob 	void  (*hmac_final)(void *context, uint8_t *digest, size_t *size);
9362ac0c33Sjakob };
9462ac0c33Sjakob 
9562ac0c33Sjakob /*
9662ac0c33Sjakob  * A TSIG key used to sign and verify packets.
9762ac0c33Sjakob  */
9862ac0c33Sjakob struct tsig_key
9962ac0c33Sjakob {
10062ac0c33Sjakob 	const dname_type *name;
10162ac0c33Sjakob 	size_t            size;
102d3fecca9Ssthen 	uint8_t		 *data;
10362ac0c33Sjakob };
10462ac0c33Sjakob 
10562ac0c33Sjakob struct tsig_record
10662ac0c33Sjakob {
10762ac0c33Sjakob 	tsig_status_type     status;
10862ac0c33Sjakob 	size_t               position;
10962ac0c33Sjakob 	size_t               response_count;
11062ac0c33Sjakob 	size_t               updates_since_last_prepare;
11162ac0c33Sjakob 	void                *context;
11262ac0c33Sjakob 	tsig_algorithm_type *algorithm;
11362ac0c33Sjakob 	tsig_key_type       *key;
11462ac0c33Sjakob 	size_t               prior_mac_size;
11562ac0c33Sjakob 	uint8_t             *prior_mac_data;
11662ac0c33Sjakob 
11762ac0c33Sjakob 	/* TSIG RR data is allocated in the rr_region.  */
11862ac0c33Sjakob 	region_type      *rr_region;
11962ac0c33Sjakob 	region_type	 *context_region;
12062ac0c33Sjakob 	const dname_type *key_name;
12162ac0c33Sjakob 	const dname_type *algorithm_name;
12262ac0c33Sjakob 	uint16_t          signed_time_high;
12362ac0c33Sjakob 	uint32_t          signed_time_low;
12462ac0c33Sjakob 	uint16_t          signed_time_fudge;
12562ac0c33Sjakob 	uint16_t          mac_size;
12662ac0c33Sjakob 	uint8_t          *mac_data;
12762ac0c33Sjakob 	uint16_t          original_query_id;
12862ac0c33Sjakob 	uint16_t          error_code;
12962ac0c33Sjakob 	uint16_t          other_size;
13062ac0c33Sjakob 	uint8_t          *other_data;
13162ac0c33Sjakob };
13262ac0c33Sjakob 
13362ac0c33Sjakob /*
13462ac0c33Sjakob  * Initialize the TSIG module (including TSIG implementation modules
13562ac0c33Sjakob  * such as tsig-openssl).
13662ac0c33Sjakob  */
13762ac0c33Sjakob int tsig_init(region_type *region);
13862ac0c33Sjakob 
13962ac0c33Sjakob /*
14062ac0c33Sjakob  * Add the specified key to the TSIG key table.
14162ac0c33Sjakob  */
14262ac0c33Sjakob void tsig_add_key(tsig_key_type *key);
143d3fecca9Ssthen void tsig_del_key(tsig_key_type *key);
14462ac0c33Sjakob 
14562ac0c33Sjakob /*
14662ac0c33Sjakob  * Add the specified algorithm to the TSIG algorithm table.
14762ac0c33Sjakob  */
14862ac0c33Sjakob void tsig_add_algorithm(tsig_algorithm_type *algorithm);
14962ac0c33Sjakob 
15062ac0c33Sjakob /*
15162ac0c33Sjakob  * Find an HMAC algorithm based on its short name.
15262ac0c33Sjakob  */
15362ac0c33Sjakob tsig_algorithm_type *tsig_get_algorithm_by_name(const char *name);
15462ac0c33Sjakob 
15562ac0c33Sjakob /*
15662ac0c33Sjakob  * Return a descriptive error message based on the TSIG error code.
15762ac0c33Sjakob  */
15862ac0c33Sjakob const char *tsig_error(int error_code);
15962ac0c33Sjakob 
16062ac0c33Sjakob /*
16162ac0c33Sjakob  * Create the tsig record internal structure. Allocs it.
16262ac0c33Sjakob  * Call init_record afterwards before doing more with it.
16362ac0c33Sjakob  *
16462ac0c33Sjakob  * The region is used to attach a cleanup function that destroys the tsig.
16562ac0c33Sjakob  */
16662ac0c33Sjakob void tsig_create_record(tsig_record_type* tsig,
16762ac0c33Sjakob 			region_type* region);
16862ac0c33Sjakob 
16962ac0c33Sjakob /*
17062ac0c33Sjakob  * Like tsig_create_record, with custom region settings.
17162ac0c33Sjakob  * The size params are used to customise the rr_region and context_region.
172d3fecca9Ssthen  * If region is NULL, no cleanup is attached to it.
17362ac0c33Sjakob  */
17462ac0c33Sjakob void tsig_create_record_custom(tsig_record_type* tsig,
17562ac0c33Sjakob 			region_type* region,
17662ac0c33Sjakob 			size_t chunk_size,
17762ac0c33Sjakob 			size_t large_object_size,
17862ac0c33Sjakob 			size_t initial_cleanup_size);
17962ac0c33Sjakob 
18062ac0c33Sjakob /*
181d3fecca9Ssthen  * Destroy tsig record internals (the main ptr is user alloced).
182d3fecca9Ssthen  * if region is nonNULL, removes cleanup.
183d3fecca9Ssthen  */
184d3fecca9Ssthen void tsig_delete_record(tsig_record_type* tsig, region_type* region);
185d3fecca9Ssthen 
186d3fecca9Ssthen /*
18762ac0c33Sjakob  * Call this before starting to analyze or signing a sequence of
18862ac0c33Sjakob  * packets.
18962ac0c33Sjakob  *
19062ac0c33Sjakob  * ALGORITHM and KEY are optional and are only needed if you want to
19162ac0c33Sjakob  * sign the initial query.  Otherwise the key and algorithm are looked
19262ac0c33Sjakob  * up in the algorithm and key table when a received TSIG RR is
19362ac0c33Sjakob  * processed.
19462ac0c33Sjakob  */
19562ac0c33Sjakob void tsig_init_record(tsig_record_type *data,
19662ac0c33Sjakob 		      tsig_algorithm_type *algorithm,
19762ac0c33Sjakob 		      tsig_key_type *key);
19862ac0c33Sjakob 
19962ac0c33Sjakob /*
20062ac0c33Sjakob  * Validate the TSIG RR key and algorithm from the TSIG RR.  Otherwise
20162ac0c33Sjakob  * update the TSIG error code.  The MAC itself is not validated.
20262ac0c33Sjakob  *
20362ac0c33Sjakob  * Returns non-zero if the key and algorithm could be validated.
20462ac0c33Sjakob  */
20562ac0c33Sjakob int tsig_from_query(tsig_record_type *tsig);
20662ac0c33Sjakob 
20762ac0c33Sjakob /*
20862ac0c33Sjakob  * Prepare TSIG for signing of a query.  This initializes TSIG with
20962ac0c33Sjakob  * the algorithm and key stored in the TSIG record.
21062ac0c33Sjakob  */
21162ac0c33Sjakob void tsig_init_query(tsig_record_type *tsig, uint16_t original_query_id);
21262ac0c33Sjakob 
21362ac0c33Sjakob /*
21462ac0c33Sjakob  * Prepare TSIG for performing an HMAC calculation.  If the TSIG
21562ac0c33Sjakob  * contains a prior HMAC it is inserted first into the hash
21662ac0c33Sjakob  * calculation.
21762ac0c33Sjakob  */
21862ac0c33Sjakob void tsig_prepare(tsig_record_type *tsig);
21962ac0c33Sjakob 
22062ac0c33Sjakob /*
22162ac0c33Sjakob  * Add the first LENGTH octets of PACKET to the TSIG hash, replacing
22262ac0c33Sjakob  * the PACKET's id with the original query id from TSIG.  If the query
22362ac0c33Sjakob  * is a response the TSIG response count is incremented.
22462ac0c33Sjakob  */
22562ac0c33Sjakob void tsig_update(tsig_record_type *tsig, buffer_type *packet, size_t length);
22662ac0c33Sjakob 
22762ac0c33Sjakob /*
22862ac0c33Sjakob  * Finalize the TSIG record by hashing the TSIG data.  If the TSIG
22962ac0c33Sjakob  * response count is greater than 1 only the timers are hashed.
23062ac0c33Sjakob  * Signed time is set to the current time.  The TSIG record can be
23162ac0c33Sjakob  * added to a packet using tsig_append_rr().
23262ac0c33Sjakob  *
23362ac0c33Sjakob  * The calculated MAC is also stored as the prior MAC, so it can be
23462ac0c33Sjakob  * used as a running MAC.
23562ac0c33Sjakob  */
23662ac0c33Sjakob void tsig_sign(tsig_record_type *tsig);
23762ac0c33Sjakob 
23862ac0c33Sjakob /*
23962ac0c33Sjakob  * Verify the calculated MAC against the MAC in the TSIG RR.
24062ac0c33Sjakob  *
24162ac0c33Sjakob  * The calculated MAC is also stored as the prior MAC, so it can be
24262ac0c33Sjakob  * used as a running MAC.
24362ac0c33Sjakob  */
24462ac0c33Sjakob int tsig_verify(tsig_record_type *tsig);
24562ac0c33Sjakob 
24662ac0c33Sjakob /*
24762ac0c33Sjakob  * Find the TSIG RR in QUERY and parse it if present.  Store the
24862ac0c33Sjakob  * parsed results in TSIG.
24962ac0c33Sjakob  *
25062ac0c33Sjakob  * Returns non-zero if no parsing error occurred, use the tsig->status
25162ac0c33Sjakob  * field to find out if the TSIG record was present.
25262ac0c33Sjakob  */
25362ac0c33Sjakob int tsig_find_rr(tsig_record_type *tsig, buffer_type *packet);
25462ac0c33Sjakob 
25562ac0c33Sjakob /*
25662ac0c33Sjakob  * Call this to analyze the TSIG RR starting at the current location
25762ac0c33Sjakob  * of PACKET. On success true is returned and the results are stored
25862ac0c33Sjakob  * in TSIG.
25962ac0c33Sjakob  *
26062ac0c33Sjakob  * Returns non-zero if no parsing error occurred, use the tsig->status
26162ac0c33Sjakob  * field to find out if the TSIG record was present.
26262ac0c33Sjakob  */
26362ac0c33Sjakob int tsig_parse_rr(tsig_record_type *tsig, buffer_type *packet);
26462ac0c33Sjakob 
26562ac0c33Sjakob /*
26662ac0c33Sjakob  * Append the TSIG record to the response PACKET.
26762ac0c33Sjakob  */
26862ac0c33Sjakob void tsig_append_rr(tsig_record_type *tsig, buffer_type *packet);
26962ac0c33Sjakob 
27062ac0c33Sjakob /*
27162ac0c33Sjakob  * The amount of space to reserve in the response for the TSIG data
27262ac0c33Sjakob  * (if required).
27362ac0c33Sjakob  */
27462ac0c33Sjakob size_t tsig_reserved_space(tsig_record_type *tsig);
27562ac0c33Sjakob 
27662ac0c33Sjakob /*
27762ac0c33Sjakob  * status or error_code must already be in error.
27862ac0c33Sjakob  * prepares content for error packet.
27962ac0c33Sjakob  */
28062ac0c33Sjakob void tsig_error_reply(tsig_record_type *tsig);
28162ac0c33Sjakob 
28262ac0c33Sjakob /*
28362ac0c33Sjakob  * compare tsig algorithm names case insensitive.
28462ac0c33Sjakob  */
28562ac0c33Sjakob int tsig_strlowercmp(const char* str1, const char* str2);
28662ac0c33Sjakob 
28762ac0c33Sjakob /*
28862ac0c33Sjakob  * cleanup tsig openssl stuff.
28962ac0c33Sjakob  */
29062ac0c33Sjakob void tsig_finalize(void);
29162ac0c33Sjakob 
292*3efee2e1Sflorian #endif /* TSIG_H */
293