From 63910439f77b91848dda094ef6e90523e1f7efa6 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Fri, 13 Mar 2009 01:50:09 +0000 Subject: added command line option for auth tag length --- ChangeLog | 1 + doc/uanytun.8.txt | 10 +++++-- src/auth_algo.c | 31 +++++++++++++++------- src/auth_algo.h | 3 +++ src/encrypted_packet.c | 71 +++++++++++++++----------------------------------- src/encrypted_packet.h | 12 +++------ src/options.c | 16 ++++++++++++ src/options.h | 1 + src/uanytun.c | 4 +-- 9 files changed, 78 insertions(+), 71 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3728883..2e71168 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 2009.??.?? -- Version 0.3 +* the auth tag length can now be configured * added extended logging support (syslog, file stdout and stderr) * changed -n|--ifconfig parameter to new behavior tun and tap devices now use the same syntax diff --git a/doc/uanytun.8.txt b/doc/uanytun.8.txt index 01d191f..f979c84 100644 --- a/doc/uanytun.8.txt +++ b/doc/uanytun.8.txt @@ -36,6 +36,7 @@ SYNOPSIS [ *-A|--salt* ] [ *-c|--cipher* ] [ *-a|--auth-algo* ] +[ *-b|--auth-tag-length* ] DESCRIPTION ----------- @@ -298,9 +299,14 @@ Possible values: * *null* - no message authentication * *sha1* - HMAC-SHA1, default value -If HMAC-SHA1 is used, the packet length is increased by -10 bytes. These 10 bytes contain the authentication data. +If HMAC-SHA1 is used, the packet length is increased. The additional bytes +contain the authentication data. see *-b|--auth-tag-length* for more info. +-b|--auth-tag-length +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The number of bytes to use for the auth tag. This value defaults to 10 bytes +unless the *null* auth algo is used in which case it defaults to 0. EXAMPLES -------- diff --git a/src/auth_algo.c b/src/auth_algo.c index db57418..1cec7ba 100644 --- a/src/auth_algo.c +++ b/src/auth_algo.c @@ -43,17 +43,32 @@ #include #include +auth_algo_type_t auth_algo_get_type(const char* type) +{ + if(!strcmp(type, "null")) + return aa_null; + else if(!strcmp(type, "sha1")) + return aa_sha1; + + return aa_unknown; +} + +u_int32_t auth_algo_get_max_length(const char* type) +{ + switch(auth_algo_get_type(type)) { + case aa_null: return 0; + case aa_sha1: return SHA1_LENGTH; + default: return 0; + } +} + int auth_algo_init(auth_algo_t* aa, const char* type) { if(!aa) return -1; - aa->type_ = aa_unknown; - if(!strcmp(type, "null")) - aa->type_ = aa_null; - else if(!strcmp(type, "sha1")) - aa->type_ = aa_sha1; - else { + aa->type_ = auth_algo_get_type(type); + if(aa->type_ == aa_unknown) { log_printf(ERROR, "unknown auth algo type"); return -1; } @@ -174,7 +189,6 @@ void auth_algo_sha1_close(auth_algo_t* aa) void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_store_dir_t dir, encrypted_packet_t* packet) { - encrypted_packet_add_auth_tag(packet); if(!encrypted_packet_get_auth_tag_length(packet)) return; @@ -224,7 +238,7 @@ void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_store_di int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_store_dir_t dir, encrypted_packet_t* packet) { if(!encrypted_packet_get_auth_tag_length(packet)) - return 0; + return 1; if(!aa || !aa->params_) { log_printf(ERROR, "auth algo not initialized"); @@ -269,7 +283,6 @@ int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_store_di } int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length); - encrypted_packet_remove_auth_tag(packet); if(result) return 0; diff --git a/src/auth_algo.h b/src/auth_algo.h index 7202b47..1b0aa01 100644 --- a/src/auth_algo.h +++ b/src/auth_algo.h @@ -41,6 +41,7 @@ #include #endif #include "key_derivation.h" +#include "encrypted_packet.h" enum auth_algo_type_enum { aa_unknown, aa_null, aa_sha1 }; typedef enum auth_algo_type_enum auth_algo_type_t; @@ -52,6 +53,8 @@ struct auth_algo_struct { }; typedef struct auth_algo_struct auth_algo_t; +auth_algo_type_t auth_algo_get_type(const char* type); +u_int32_t auth_algo_get_max_length(const char* type); int auth_algo_init(auth_algo_t* aa, const char* type); void auth_algo_close(auth_algo_t* aa); diff --git a/src/encrypted_packet.c b/src/encrypted_packet.c index 151683f..53387f3 100644 --- a/src/encrypted_packet.c +++ b/src/encrypted_packet.c @@ -39,17 +39,24 @@ #include #include -void encrypted_packet_init(encrypted_packet_t* packet) +void encrypted_packet_init(encrypted_packet_t* packet, u_int32_t auth_tag_length) { if(!packet) return; memset (packet, 0, sizeof(*packet)); + if(auth_tag_length > (ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t))) + packet->auth_tag_length_ = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t); + else + packet->auth_tag_length_ = auth_tag_length; } -u_int32_t encrypted_packet_get_header_length() +u_int32_t encrypted_packet_get_minimum_length(encrypted_packet_t* packet) { - return sizeof(encrypted_packet_header_t); + if(!packet) + return 0; + + return (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_); } u_int8_t* encrypted_packet_get_packet(encrypted_packet_t* packet) @@ -65,7 +72,7 @@ u_int32_t encrypted_packet_get_length(encrypted_packet_t* packet) if(!packet) return 0; - return (packet->payload_length_ + sizeof(encrypted_packet_header_t)); + return (packet->payload_length_ + sizeof(encrypted_packet_header_t) + packet->auth_tag_length_); } void encrypted_packet_set_length(encrypted_packet_t* packet, u_int32_t len) @@ -74,20 +81,13 @@ void encrypted_packet_set_length(encrypted_packet_t* packet, u_int32_t len) return; if(len > ENCRYPTED_PACKET_SIZE_MAX) - len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t); - else if(len < sizeof(encrypted_packet_header_t)) + len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_; + else if(len < (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_)) len = 0; else - len -= sizeof(encrypted_packet_header_t); + len -= (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_); packet->payload_length_ = len; - - if(len >= ENCRYPTED_PACKET_AUTHTAG_SIZE) { - packet->auth_tag_ = packet->data_.buf_ + sizeof(encrypted_packet_header_t); - packet->auth_tag_ += packet->payload_length_ - ENCRYPTED_PACKET_AUTHTAG_SIZE; - } - else - packet->auth_tag_ = NULL; } u_int8_t* encrypted_packet_get_payload(encrypted_packet_t* packet) @@ -111,17 +111,10 @@ void encrypted_packet_set_payload_length(encrypted_packet_t* packet, u_int32_t l if(!packet) return; - if(len > ENCRYPTED_PACKET_SIZE_MAX || (len + sizeof(encrypted_packet_header_t)) > ENCRYPTED_PACKET_SIZE_MAX) - len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t); + if(len > (ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_)) + len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_; packet->payload_length_ = len; - - if(len >= ENCRYPTED_PACKET_AUTHTAG_SIZE) { - packet->auth_tag_ = packet->data_.buf_ + sizeof(encrypted_packet_header_t); - packet->auth_tag_ += packet->payload_length_ - ENCRYPTED_PACKET_AUTHTAG_SIZE; - } - else - packet->auth_tag_ = NULL; } u_int8_t* encrypted_packet_get_auth_portion(encrypted_packet_t* packet) @@ -137,46 +130,24 @@ u_int32_t encrypted_packet_get_auth_portion_length(encrypted_packet_t* packet) if(!packet) return 0; - u_int32_t len = packet->payload_length_ + sizeof(encrypted_packet_header_t); - - if(!packet->auth_tag_) - return len; - - return (len > ENCRYPTED_PACKET_AUTHTAG_SIZE) ? (len - ENCRYPTED_PACKET_AUTHTAG_SIZE) : 0; + return packet->payload_length_ + sizeof(encrypted_packet_header_t); } u_int8_t* encrypted_packet_get_auth_tag(encrypted_packet_t* packet) { - if(!packet) + if(!packet || !packet->auth_tag_length_) return NULL; - return packet->auth_tag_; + return (packet->data_.buf_ + sizeof(encrypted_packet_header_t) + packet->payload_length_); } u_int32_t encrypted_packet_get_auth_tag_length(encrypted_packet_t* packet) -{ - if(!packet || !packet->auth_tag_) - return 0; - - return ENCRYPTED_PACKET_AUTHTAG_SIZE; -} - -void encrypted_packet_add_auth_tag(encrypted_packet_t* packet) { if(!packet) - return; - - encrypted_packet_set_payload_length(packet, packet->payload_length_ + ENCRYPTED_PACKET_AUTHTAG_SIZE); -} - -void encrypted_packet_remove_auth_tag(encrypted_packet_t* packet) -{ - if(!packet || !packet->auth_tag_) - return; + return 0; - packet->auth_tag_ = NULL; - packet->payload_length_ = (packet->payload_length_ > ENCRYPTED_PACKET_AUTHTAG_SIZE) ? packet->payload_length_ - ENCRYPTED_PACKET_AUTHTAG_SIZE: 0; + return packet->auth_tag_length_; } diff --git a/src/encrypted_packet.h b/src/encrypted_packet.h index 2e6c1b7..e9cdc59 100644 --- a/src/encrypted_packet.h +++ b/src/encrypted_packet.h @@ -36,12 +36,11 @@ #define _ENCRYPTED_PACKET_H_ #define ENCRYPTED_PACKET_SIZE_MAX 1600 -#define ENCRYPTED_PACKET_AUTHTAG_SIZE 10 #define PAYLOAD_TYPE_TAP 0x6558 #define PAYLOAD_TYPE_TUN 0x0000 #define PAYLOAD_TYPE_TUN4 0x0800 -#define PAYLOAD_TYPE_TUN6 0x86DD +#define PAYLOAD_TYPE_TUN6 0x86DD struct __attribute__ ((__packed__)) encrypted_packet_header_struct { seq_nr_t seq_nr_; @@ -52,7 +51,7 @@ typedef struct encrypted_packet_header_struct encrypted_packet_header_t; struct encrypted_packet_struct { u_int32_t payload_length_; - u_int8_t* auth_tag_; + u_int32_t auth_tag_length_; union __attribute__ ((__packed__)) { u_int8_t buf_[ENCRYPTED_PACKET_SIZE_MAX]; encrypted_packet_header_t header_; @@ -60,9 +59,9 @@ struct encrypted_packet_struct { }; typedef struct encrypted_packet_struct encrypted_packet_t; -void encrypted_packet_init(encrypted_packet_t* packet); +void encrypted_packet_init(encrypted_packet_t* packet, u_int32_t auth_tag_length); -u_int32_t encrypted_packet_get_header_length(); +u_int32_t encrypted_packet_get_minimum_length(encrypted_packet_t* packet); u_int8_t* encrypted_packet_get_packet(encrypted_packet_t* packet); u_int32_t encrypted_packet_get_length(encrypted_packet_t* packet); @@ -78,9 +77,6 @@ u_int32_t encrypted_packet_get_auth_portion_length(encrypted_packet_t* packet); u_int8_t* encrypted_packet_get_auth_tag(encrypted_packet_t* packet); u_int32_t encrypted_packet_get_auth_tag_length(encrypted_packet_t* packet); -void encrypted_packet_add_auth_tag(encrypted_packet_t* packet); -void encrypted_packet_remove_auth_tag(encrypted_packet_t* packet); - seq_nr_t encrypted_packet_get_seq_nr(encrypted_packet_t* packet); void encrypted_packet_set_seq_nr(encrypted_packet_t* packet, seq_nr_t seq_nr); diff --git a/src/options.c b/src/options.c index f15d6b8..09265da 100644 --- a/src/options.c +++ b/src/options.c @@ -43,6 +43,10 @@ #include "log.h" +#ifndef NO_CRYPT +#include "auth_algo.h" +#endif + #define PARSE_BOOL_PARAM(SHORT, LONG, VALUE) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ VALUE = 1; @@ -257,6 +261,7 @@ int options_parse(options_t* opt, int argc, char* argv[]) PARSE_HEXSTRING_PARAM_SEC("-A","--salt", opt->salt_) PARSE_STRING_PARAM("-c","--cipher", opt->cipher_) PARSE_STRING_PARAM("-a","--auth-algo", opt->auth_algo_) + PARSE_INT_PARAM("-b","--auth-tag-length", opt->auth_tag_length_) #endif else return i; @@ -294,6 +299,13 @@ void options_parse_post(options_t* opt) !strcmp(opt->kd_prf_, "null")) { log_printf(WARNING, "using NULL key derivation with encryption and or authentication enabled!"); } + + u_int32_t tag_len_max = auth_algo_get_max_length(opt->auth_algo_); + if(!tag_len_max) opt->auth_tag_length_ = 0; + else if(tag_len_max < opt->auth_tag_length_) { + log_printf(WARNING, "%s auth algo can't generate tags of length %d, using maximum tag length(%d)", opt->auth_algo_, opt->auth_tag_length_, tag_len_max); + opt->auth_tag_length_ = tag_len_max; + } #endif if(!(opt->dev_name_) && !(opt->dev_type_)) @@ -331,8 +343,10 @@ void options_default(options_t* opt) opt->passphrase_ = NULL; opt->cipher_ = strdup("aes-ctr"); opt->auth_algo_ = strdup("sha1"); + opt->auth_tag_length_ = 10; #else opt->cipher_ = strdup("null"); + opt->auth_tag_length_ = 0; #endif opt->anytun02_compat_ = 0; opt->key_.buf_ = NULL; @@ -426,6 +440,7 @@ void options_print_usage() printf(" [-A|--salt] master salt to use for encryption\n"); printf(" [-c|--cipher] payload encryption algorithm\n"); printf(" [-a|--auth-algo] message authentication algorithm\n"); + printf(" [-b|--auth-tag-length] length of the auth tag\n"); #endif } @@ -464,6 +479,7 @@ void options_print(options_t* opt) printf("cipher: '%s'\n", opt->cipher_); #ifndef NO_CRYPT printf("auth_algo: '%s'\n", opt->auth_algo_); + printf("auth_tag_length: %d\n", opt->auth_tag_length_); printf("kd_prf: '%s'\n", opt->kd_prf_); printf("ld_kdr: %d\n", opt->ld_kdr_); printf("passphrase: '%s'\n", opt->passphrase_); diff --git a/src/options.h b/src/options.h index 688a50d..cfac90d 100644 --- a/src/options.h +++ b/src/options.h @@ -74,6 +74,7 @@ struct options_struct { char* passphrase_; #endif int anytun02_compat_; + u_int32_t auth_tag_length_; buffer_t key_; buffer_t salt_; }; diff --git a/src/uanytun.c b/src/uanytun.c index 5c81dc9..72a0fab 100644 --- a/src/uanytun.c +++ b/src/uanytun.c @@ -189,7 +189,7 @@ int process_sock_data(tun_device_t* dev, udp_socket_t* sock, options_t* opt, pla log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno)); return 0; } - else if(len < encrypted_packet_get_header_length()) { + else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) { log_printf(WARNING, "received packet is to short"); return 0; } @@ -249,7 +249,7 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) plain_packet_t plain_packet; plain_packet_init(&plain_packet); encrypted_packet_t encrypted_packet; - encrypted_packet_init(&encrypted_packet); + encrypted_packet_init(&encrypted_packet, opt->auth_tag_length_); seq_nr_t seq_nr = 0; fd_set readfds; -- cgit v1.2.3