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