diff options
Diffstat (limited to 'epan/dissectors/packet-ipsec.c')
-rw-r--r-- | epan/dissectors/packet-ipsec.c | 781 |
1 files changed, 453 insertions, 328 deletions
diff --git a/epan/dissectors/packet-ipsec.c b/epan/dissectors/packet-ipsec.c index b5b3bf1d..c8699dd8 100644 --- a/epan/dissectors/packet-ipsec.c +++ b/epan/dissectors/packet-ipsec.c @@ -73,6 +73,7 @@ ADD: Additional generic (non-checked) ICV length of 128, 192 and 256. #include <epan/uat.h> #include <wsutil/str_util.h> #include <wsutil/wsgcrypt.h> +#include <wsutil/pint.h> #include "packet-ipsec.h" #include "packet-ip.h" @@ -80,44 +81,45 @@ ADD: Additional generic (non-checked) ICV length of 128, 192 and 256. void proto_register_ipsec(void); void proto_reg_handoff_ipsec(void); -static int proto_ah = -1; -static int hf_ah_next_header = -1; -static int hf_ah_length = -1; -static int hf_ah_reserved = -1; -static int hf_ah_spi = -1; -static int hf_ah_iv = -1; -static int hf_ah_sequence = -1; -static int proto_esp = -1; -static int hf_esp_spi = -1; -static int hf_esp_iv = -1; -static int hf_esp_icv = -1; -static int hf_esp_icv_good = -1; -static int hf_esp_icv_bad = -1; -static int hf_esp_sequence = -1; -static int hf_esp_encrypted_data = -1; -static int hf_esp_decrypted_data = -1; -static int hf_esp_contained_data = -1; -static int hf_esp_pad = -1; -static int hf_esp_pad_len = -1; -static int hf_esp_protocol = -1; -static int hf_esp_sequence_analysis_expected_sn = -1; -static int hf_esp_sequence_analysis_previous_frame = -1; - -static int proto_ipcomp = -1; -static int hf_ipcomp_next_header = -1; -static int hf_ipcomp_flags = -1; -static int hf_ipcomp_cpi = -1; - -static gint ett_ah = -1; -static gint ett_esp = -1; -static gint ett_esp_icv = -1; -static gint ett_esp_decrypted_data = -1; -static gint ett_ipcomp = -1; - -static expert_field ei_esp_sequence_analysis_wrong_sequence_number = EI_INIT; - - -static gint exported_pdu_tap = -1; +static int proto_ah; +static int hf_ah_next_header; +static int hf_ah_length; +static int hf_ah_reserved; +static int hf_ah_spi; +static int hf_ah_iv; +static int hf_ah_sequence; +static int proto_esp; +static int hf_esp_spi; +static int hf_esp_iv; +static int hf_esp_icv; +static int hf_esp_icv_good; +static int hf_esp_icv_bad; +static int hf_esp_sequence; +static int hf_esp_encrypted_data; +static int hf_esp_decrypted_data; +static int hf_esp_contained_data; +static int hf_esp_pad; +static int hf_esp_pad_len; +static int hf_esp_protocol; +static int hf_esp_sequence_analysis_expected_sn; +static int hf_esp_sequence_analysis_previous_frame; + +static int proto_ipcomp; +static int hf_ipcomp_next_header; +static int hf_ipcomp_flags; +static int hf_ipcomp_cpi; + +static int ett_ah; +static int ett_esp; +static int ett_esp_icv; +static int ett_esp_decrypted_data; +static int ett_ipcomp; + +static expert_field ei_esp_sequence_analysis_wrong_sequence_number; +static expert_field ei_esp_pad_bogus; + + +static int exported_pdu_tap = -1; static dissector_handle_t ipcomp_handle; static capture_dissector_handle_t ah_cap_handle; @@ -175,6 +177,8 @@ static dissector_table_t ip_dissector_table; #define IPSEC_SA_WILDCARDS_ANY '*' /* the maximum number of bytes (10)(including the terminating nul character(11)) */ #define IPSEC_SPI_LEN_MAX 11 +#define IPSEC_SA_SN 32 +#define IPSEC_SA_ESN 64 /* well-known algorithm number (in CPI), from RFC2409 */ @@ -212,7 +216,7 @@ static const value_string esp_encryption_type_vals[] = { }; static const char * -esp_get_encr_algo_name(gint esp_encr_algo) +esp_get_encr_algo_name(int esp_encr_algo) { return esp_encryption_type_vals[esp_encr_algo].strptr; } @@ -237,7 +241,7 @@ static const value_string esp_authentication_type_vals[] = { }; static const char * -esp_get_auth_algo_name(gint esp_auth_algo) +esp_get_auth_algo_name(int esp_auth_algo) { return esp_authentication_type_vals[esp_auth_algo].strptr; } @@ -249,58 +253,61 @@ esp_get_auth_algo_name(gint esp_auth_algo) */ /* UAT entry structure. */ typedef struct { - guint8 protocol; - gchar *srcIP; - gchar *dstIP; - gchar *spi; - - guint8 encryption_algo; /* see values in esp_encryption_type_vals */ - gchar *encryption_key_string; - gchar *encryption_key; - gint encryption_key_length; - gboolean cipher_hd_created; + uint8_t protocol; + char *srcIP; + char *dstIP; + char *spi; + + uint8_t encryption_algo; /* see values in esp_encryption_type_vals */ + char *encryption_key_string; + char *encryption_key; + int encryption_key_length; + bool cipher_hd_created; gcry_cipher_hd_t cipher_hd; /* Key is stored here and closed with the SA */ - guint8 authentication_algo; /* see values in esp_authentication_type_vals */ - gchar *authentication_key_string; - gchar *authentication_key; - gint authentication_key_length; + uint8_t authentication_algo; /* see values in esp_authentication_type_vals */ + char *authentication_key_string; + char *authentication_key; + int authentication_key_length; + + uint8_t sn_length; + uint32_t sn_upper; } uat_esp_sa_record_t; -static uat_esp_sa_record_t *uat_esp_sa_records = NULL; +static uat_esp_sa_record_t *uat_esp_sa_records; /* Extra SA records that may be set programmatically */ /* 'records' array is now allocated on the heap */ #define MAX_EXTRA_SA_RECORDS 16 typedef struct extra_esp_sa_records_t { - guint num_records; + unsigned num_records; uat_esp_sa_record_t *records; } extra_esp_sa_records_t; static extra_esp_sa_records_t extra_esp_sa_records; -static uat_t * esp_uat = NULL; -static guint num_sa_uat = 0; +static uat_t * esp_uat; +static unsigned num_sa_uat; /* - Name : static gint compute_ascii_key(gchar **ascii_key, gchar *key) + Name : static int compute_ascii_key(char **ascii_key, char *key) Description : Allocate memory for the key and transform the key if it is hexadecimal Return : Return the key length Params: - - gchar **ascii_key : the resulting ascii key allocated here - - gchar *key : the key to compute + - char **ascii_key : the resulting ascii key allocated here + - char *key : the key to compute - char **err : an error string to report if the input is found to be invalid */ -static gint -compute_ascii_key(gchar **ascii_key, const gchar *key, char **err) +static int +compute_ascii_key(char **ascii_key, const char *key, char **err) { - guint key_len = 0, raw_key_len; - gint hex_digit; - guchar key_byte; - guint i, j; + unsigned key_len = 0, raw_key_len; + int hex_digit; + unsigned char key_byte; + unsigned i, j; if(key != NULL) { - raw_key_len = (guint)strlen(key); + raw_key_len = (unsigned)strlen(key); if((raw_key_len > 2) && (key[0] == '0') && ((key[1] == 'x') || (key[1] == 'X'))) { /* @@ -317,7 +324,7 @@ compute_ascii_key(gchar **ascii_key, const gchar *key, char **err) * number of characters even. */ key_len = (raw_key_len - 2) / 2 + 1; - *ascii_key = (gchar *) g_malloc ((key_len + 1)* sizeof(gchar)); + *ascii_key = (char *) g_malloc ((key_len + 1)* sizeof(char)); hex_digit = g_ascii_xdigit_value(key[i]); if (hex_digit == -1) { @@ -326,7 +333,7 @@ compute_ascii_key(gchar **ascii_key, const gchar *key, char **err) *err = ws_strdup_printf("Key %s begins with an invalid hex char (%c)", key, key[i]); return -1; /* not a valid hex digit */ } - (*ascii_key)[j] = (guchar)hex_digit; + (*ascii_key)[j] = (unsigned char)hex_digit; j++; i++; } @@ -337,7 +344,7 @@ compute_ascii_key(gchar **ascii_key, const gchar *key, char **err) * pair of hex digits as a single byte value. */ key_len = (raw_key_len - 2) / 2; - *ascii_key = (gchar *) g_malloc ((key_len + 1)* sizeof(gchar)); + *ascii_key = (char *) g_malloc ((key_len + 1)* sizeof(char)); } while(i < (raw_key_len -1)) @@ -352,7 +359,7 @@ compute_ascii_key(gchar **ascii_key, const gchar *key, char **err) key, key[i-1]); return -1; /* not a valid hex digit */ } - key_byte = ((guchar)hex_digit) << 4; + key_byte = ((unsigned char)hex_digit) << 4; hex_digit = g_ascii_xdigit_value(key[i]); i++; if (hex_digit == -1) @@ -362,7 +369,7 @@ compute_ascii_key(gchar **ascii_key, const gchar *key, char **err) *err = ws_strdup_printf("Key %s has an invalid hex char (%c)", key, key[i-1]); return -1; /* not a valid hex digit */ } - key_byte |= (guchar)hex_digit; + key_byte |= (unsigned char)hex_digit; (*ascii_key)[j] = key_byte; j++; } @@ -394,7 +401,7 @@ static bool uat_esp_sa_record_update_cb(void* r, char** err) { g_free(rec->encryption_key); if (rec->cipher_hd_created) { gcry_cipher_close(rec->cipher_hd); - rec->cipher_hd_created = FALSE; + rec->cipher_hd_created = false; } if (rec->encryption_key_string) { rec->encryption_key_length = compute_ascii_key(&rec->encryption_key, rec->encryption_key_string, err); @@ -419,7 +426,7 @@ static bool uat_esp_sa_record_update_cb(void* r, char** err) { /* TODO: check format of spi */ - /* Return TRUE only if *err has not been set by checking code. */ + /* Return true only if *err has not been set by checking code. */ return *err == NULL; } @@ -435,10 +442,12 @@ static void* uat_esp_sa_record_copy_cb(void* n, const void* o, size_t siz _U_) { new_rec->encryption_algo = old_rec->encryption_algo; new_rec->encryption_key_string = g_strdup(old_rec->encryption_key_string); new_rec->encryption_key = NULL; - new_rec->cipher_hd_created = FALSE; + new_rec->cipher_hd_created = false; new_rec->authentication_algo = old_rec->authentication_algo; new_rec->authentication_key_string = g_strdup(old_rec->authentication_key_string); new_rec->authentication_key = NULL; + new_rec->sn_length = old_rec->sn_length; + new_rec->sn_upper = old_rec->sn_upper; /* Parse keys as in an update */ char *err = NULL; @@ -463,18 +472,20 @@ static void uat_esp_sa_record_free_cb(void*r) { if (rec->cipher_hd_created) { gcry_cipher_close(rec->cipher_hd); - rec->cipher_hd_created = FALSE; + rec->cipher_hd_created = false; } } -UAT_VS_DEF(uat_esp_sa_records, protocol, uat_esp_sa_record_t, guint8, IPSEC_SA_IPV4, "IPv4") +UAT_VS_DEF(uat_esp_sa_records, protocol, uat_esp_sa_record_t, uint8_t, IPSEC_SA_IPV4, "IPv4") UAT_CSTRING_CB_DEF(uat_esp_sa_records, srcIP, uat_esp_sa_record_t) UAT_CSTRING_CB_DEF(uat_esp_sa_records, dstIP, uat_esp_sa_record_t) UAT_CSTRING_CB_DEF(uat_esp_sa_records, spi, uat_esp_sa_record_t) -UAT_VS_DEF(uat_esp_sa_records, encryption_algo, uat_esp_sa_record_t, guint8, 0, "FIXX") +UAT_VS_DEF(uat_esp_sa_records, encryption_algo, uat_esp_sa_record_t, uint8_t, 0, "FIXX") UAT_CSTRING_CB_DEF(uat_esp_sa_records, encryption_key_string, uat_esp_sa_record_t) -UAT_VS_DEF(uat_esp_sa_records, authentication_algo, uat_esp_sa_record_t, guint8, 0, "FIXX") +UAT_VS_DEF(uat_esp_sa_records, authentication_algo, uat_esp_sa_record_t, uint8_t, 0, "FIXX") UAT_CSTRING_CB_DEF(uat_esp_sa_records, authentication_key_string, uat_esp_sa_record_t) +UAT_VS_DEF(uat_esp_sa_records, sn_length, uat_esp_sa_record_t, uint8_t, IPSEC_SA_SN, "32-bit") +UAT_HEX_CB_DEF(uat_esp_sa_records, sn_upper, uat_esp_sa_record_t) /* Configure a new SA (programmatically, most likely from a private dissector). @@ -482,12 +493,12 @@ UAT_CSTRING_CB_DEF(uat_esp_sa_records, authentication_key_string, uat_esp_sa_rec in order to keep code paths common. Note that an attempt to match with these entries will be made *before* entries added through the UAT entry interface/file. */ -void esp_sa_record_add_from_dissector(guint8 protocol, const gchar *srcIP, const char *dstIP, - gchar *spi, - guint8 encryption_algo, /* values from esp_encryption_type_vals */ - const gchar *encryption_key, - guint8 authentication_algo, /* values from esp_authentication_type_vals */ - const gchar *authentication_key) +void esp_sa_record_add_from_dissector(uint8_t protocol, const char *srcIP, const char *dstIP, + char *spi, + uint8_t encryption_algo, /* values from esp_encryption_type_vals */ + const char *encryption_key, + uint8_t authentication_algo, /* values from esp_authentication_type_vals */ + const char *authentication_key) { uat_esp_sa_record_t* record = NULL; if (extra_esp_sa_records.num_records == 0) { @@ -514,13 +525,17 @@ void esp_sa_record_add_from_dissector(guint8 protocol, const gchar *srcIP, const record->encryption_algo = encryption_algo; record->encryption_key_string = g_strdup(encryption_key); record->encryption_key = NULL; - record->cipher_hd_created = FALSE; + record->cipher_hd_created = false; /* Authentication */ record->authentication_algo = authentication_algo; record->authentication_key_string = g_strdup(authentication_key); record->authentication_key = NULL; + /* XXX - Should we change the function so private dissectors pass this in? */ + record->sn_length = IPSEC_SA_SN; + record->sn_upper = 0; + /* Parse keys */ char *err = NULL; uat_esp_sa_record_update_cb(record, &err); @@ -534,10 +549,10 @@ void esp_sa_record_add_from_dissector(guint8 protocol, const gchar *srcIP, const /* Preference settings */ /* Default ESP payload decode to off */ -static gboolean g_esp_enable_encryption_decode = FALSE; +static bool g_esp_enable_encryption_decode; /* Default ESP payload Authentication Checking to off */ -static gboolean g_esp_enable_authentication_check = FALSE; +static bool g_esp_enable_authentication_check; /**************************************************/ /* Sequence number analysis */ @@ -545,26 +560,27 @@ static gboolean g_esp_enable_authentication_check = FALSE; /* SPI state, key is just 32-bit SPI */ typedef struct { - guint32 previousSequenceNumber; - guint32 previousFrameNum; + uint32_t firstValidSN; + uint32_t previousSequenceNumber; + uint32_t previousFrameNum; } spi_status; /* The sequence analysis SPI hash table. Maps SPI -> spi_status */ -static wmem_map_t *esp_sequence_analysis_hash = NULL; +static wmem_map_t *esp_sequence_analysis_hash; /* Results are stored here: framenum -> spi_status */ /* N.B. only store entries for out-of-order frames, if there is no entry for a given frame, it was found to be in-order */ -static wmem_map_t *esp_sequence_analysis_report_hash = NULL; +static wmem_map_t *esp_sequence_analysis_report_hash; /* During the first pass, update the SPI state. If the sequence numbers are out of order, add an entry to the report table */ -static void check_esp_sequence_info(guint32 spi, guint32 sequence_number, packet_info *pinfo) +static void check_esp_sequence_info(uint32_t spi, uint32_t sequence_number, packet_info *pinfo) { /* Do the table lookup */ spi_status *status = (spi_status*)wmem_map_lookup(esp_sequence_analysis_hash, - GUINT_TO_POINTER((guint)spi)); + GUINT_TO_POINTER((unsigned)spi)); if (status == NULL) { /* Create an entry for this SPI */ status = wmem_new0(wmem_file_scope(), spi_status); @@ -572,7 +588,7 @@ static void check_esp_sequence_info(guint32 spi, guint32 sequence_number, packet status->previousFrameNum = pinfo->num; /* And add it to the table */ - wmem_map_insert(esp_sequence_analysis_hash, GUINT_TO_POINTER((guint)spi), status); + wmem_map_insert(esp_sequence_analysis_hash, GUINT_TO_POINTER((unsigned)spi), status); } else { spi_status *frame_status; @@ -594,7 +610,7 @@ static void check_esp_sequence_info(guint32 spi, guint32 sequence_number, packet /* Check to see if there is a report stored for this frame. If there is, add it to the tree and report using expert info */ -static void show_esp_sequence_info(guint32 spi, guint32 sequence_number, +static void show_esp_sequence_info(uint32_t spi, uint32_t sequence_number, tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) { /* Look up this frame in the report table. */ @@ -643,10 +659,24 @@ static void show_esp_sequence_info(guint32 spi, guint32 sequence_number, (only works if payload is NULL encrypted and ESP payload decode is off or payload is NULL encrypted and the packet does not match a Security Association). */ -static gboolean g_esp_enable_null_encryption_decode_heuristic = FALSE; +static bool g_esp_enable_null_encryption_decode_heuristic; + +#define PADDING_RFC 0 +#define PADDING_ZERO 1 +#define PADDING_ANY 2 + +/* PADDING_RFC is chosen as 0 to be the default */ +static int g_esp_padding_type; + +static const enum_val_t esp_padding_vals[] = { + { "rfc", "RFC compliant padding only", PADDING_RFC }, + { "zero", "All-zero padding also permitted", PADDING_ZERO }, + { "any", "Any padding permitted", PADDING_ANY }, + { NULL, NULL, 0 } +}; /* Default to doing ESP sequence analysis */ -static gboolean g_esp_do_sequence_analysis = TRUE; +static bool g_esp_do_sequence_analysis = true; @@ -668,12 +698,12 @@ static int get_ipv6_suffix(char* ipv6_suffix, char *ipv6_address) int cpt_seg = 0; int j =0; int ipv6_len = 0; - gboolean found = FALSE; + bool found = false; ipv6_len = (int) strlen(ipv6_address); if(ipv6_len != 0) { - while ( (cpt_suffix < IPSEC_STRLEN_IPV6) && (ipv6_len - cpt -1 >= 0) && (found == FALSE)) + while ( (cpt_suffix < IPSEC_STRLEN_IPV6) && (ipv6_len - cpt -1 >= 0) && (found == false)) { if(ipv6_address[ipv6_len - cpt - 1] == ':') { @@ -688,14 +718,14 @@ static int get_ipv6_suffix(char* ipv6_suffix, char *ipv6_address) if(ipv6_len - cpt - 1 == 0) { /* Found a suffix */ - found = TRUE; + found = true; } else if(ipv6_address[ipv6_len - cpt - 2] == ':') { /* found a suffix */ cpt +=2; - found = TRUE; + found = true; } else @@ -758,9 +788,9 @@ get_full_ipv6_addr(char* ipv6_addr_expanded, char *ipv6_addr) int prefix_remaining = 0; int prefix_len = 0; int j = 0; - guint i = 0; - guint addr_byte = 0; - guint mask = IPSEC_IPV6_ADDR_LEN; + unsigned i = 0; + unsigned addr_byte = 0; + unsigned mask = IPSEC_IPV6_ADDR_LEN; char* mask_begin = NULL; @@ -829,7 +859,7 @@ get_full_ipv6_addr(char* ipv6_addr_expanded, char *ipv6_addr) /* - Name : static gboolean get_full_ipv4_addr(char* ipv4_addr_expanded, char *ipv4_addr) + Name : static bool get_full_ipv4_addr(char* ipv4_addr_expanded, char *ipv4_addr) Description : Get the extended IPv4 Address of an IPv4 Address Return : Return true if it can derive an IPv4 address. It does not mean that the previous one was valid. @@ -842,19 +872,19 @@ get_full_ipv6_addr(char* ipv6_addr_expanded, char *ipv6_addr) if IPv4 address is "*" the IPv4 expanded address will be "********" and the function will return 0 */ -static gboolean +static bool get_full_ipv4_addr(char* ipv4_address_expanded, char *ipv4_address) { char addr_byte_string_tmp[4]; char addr_byte_string[4]; - guint addr_byte = 0; - guint i = 0; - guint j = 0; - guint k = 0; - guint cpt = 0; - gboolean done_flag = FALSE; - guint mask = IPSEC_IPV4_ADDR_LEN; + unsigned addr_byte = 0; + unsigned i = 0; + unsigned j = 0; + unsigned k = 0; + unsigned cpt = 0; + bool done_flag = false; + unsigned mask = IPSEC_IPV4_ADDR_LEN; char* mask_begin = NULL; if((ipv4_address == NULL) || (strcmp(ipv4_address, "") == 0)) return done_flag; @@ -874,14 +904,14 @@ get_full_ipv4_addr(char* ipv4_address_expanded, char *ipv4_address) ipv4_address_expanded[i] = IPSEC_SA_WILDCARDS_ANY; } ipv4_address_expanded[IPSEC_STRLEN_IPV4] = '\0'; - done_flag = TRUE; + done_flag = true; } else { j = 0; cpt = 0; k = 0; - while((done_flag == FALSE) && (j <= strlen(ipv4_address)) && (cpt < IPSEC_STRLEN_IPV4)) + while((done_flag == false) && (j <= strlen(ipv4_address)) && (cpt < IPSEC_STRLEN_IPV4)) { if(j == strlen(ipv4_address)) { @@ -897,7 +927,7 @@ get_full_ipv4_addr(char* ipv4_address_expanded, char *ipv4_address) else { if (sscanf(addr_byte_string_tmp,"%u",&addr_byte) == EOF) - return FALSE; + return false; if(addr_byte < 16) snprintf(addr_byte_string,4,"0%X",addr_byte); @@ -909,7 +939,7 @@ get_full_ipv4_addr(char* ipv4_address_expanded, char *ipv4_address) cpt ++; } } - done_flag = TRUE; + done_flag = true; } else if(ipv4_address[j] == '.') @@ -926,7 +956,7 @@ get_full_ipv4_addr(char* ipv4_address_expanded, char *ipv4_address) else { if (sscanf(addr_byte_string_tmp,"%u",&addr_byte) == EOF) - return FALSE; + return false; if(addr_byte < 16) snprintf(addr_byte_string,4,"0%X",addr_byte); @@ -968,7 +998,7 @@ get_full_ipv4_addr(char* ipv4_address_expanded, char *ipv4_address) ipv4_address_expanded[i] = '*'; else { if(sscanf(ipv4_address_expanded + i, "%X", &addr_byte) == EOF) - return FALSE; + return false; addr_byte &= (0x0F << (4 * (i + 1) - mask)); addr_byte &= 0x0F; snprintf(ipv4_address_expanded + i, 4, "%X", addr_byte); @@ -982,44 +1012,44 @@ get_full_ipv4_addr(char* ipv4_address_expanded, char *ipv4_address) } /* - Name : static goolean filter_address_match(gchar *addr, gchar *filter, gint len, gint typ) + Name : static goolean filter_address_match(char *addr, char *filter, int len, int typ) Description : check the matching of an address with a filter - Return : Return TRUE if the filter and the address match + Return : Return true if the filter and the address match Params: - - gchar *addr : the address to check - - gchar *filter : the filter - - gint typ : the Address type : either IPv6 or IPv4 (IPSEC_SA_IPV6, IPSEC_SA_IPV4) + - char *addr : the address to check + - char *filter : the filter + - int typ : the Address type : either IPv6 or IPv4 (IPSEC_SA_IPV6, IPSEC_SA_IPV4) */ -static gboolean -filter_address_match(gchar *addr, gchar *filter, gint typ) +static bool +filter_address_match(char *addr, char *filter, int typ) { - guint i; + unsigned i; char addr_hex[IPSEC_STRLEN_IPV6 + 1]; char filter_hex[IPSEC_STRLEN_IPV6 + 1]; - guint addr_len; - guint filter_len; + unsigned addr_len; + unsigned filter_len; if (typ == IPSEC_SA_IPV4) { if (!get_full_ipv4_addr(addr_hex, addr)) - return FALSE; + return false; if (!get_full_ipv4_addr(filter_hex, filter)) - return FALSE; + return false; } else { if (get_full_ipv6_addr(addr_hex, addr)) - return FALSE; + return false; if (get_full_ipv6_addr(filter_hex, filter)) - return FALSE; + return false; } - addr_len = (guint)strlen(addr_hex); - filter_len = (guint)strlen(filter_hex); + addr_len = (unsigned)strlen(addr_hex); + filter_len = (unsigned)strlen(filter_hex); if((filter_len == 1) && (filter[0] == IPSEC_SA_WILDCARDS_ANY)){ - return TRUE; + return true; } if(addr_len != filter_len) - return FALSE; + return false; /* No length specified */ if( ((typ == IPSEC_SA_IPV6) && (filter_len == IPSEC_STRLEN_IPV6)) || @@ -1029,108 +1059,110 @@ filter_address_match(gchar *addr, gchar *filter, gint typ) for(i = 0; i < addr_len; i++) { if((filter_hex[i] != IPSEC_SA_WILDCARDS_ANY) && (filter_hex[i] != addr_hex[i])) - return FALSE; + return false; } - return TRUE; + return true; } else - return FALSE; - return TRUE; + return false; + return true; } /* - Name : static goolean filter_spi_match(gchar *spi, gchar *filter) + Name : static goolean filter_spi_match(char *spi, char *filter) Description : check the matching of a spi with a filter - Return : Return TRUE if the filter matches the spi. + Return : Return true if the filter matches the spi. Params: - - guint spi : the spi to check - - gchar *filter : the filter + - unsigned spi : the spi to check + - char *filter : the filter */ -static gboolean -filter_spi_match(guint spi, gchar *filter) +static bool +filter_spi_match(unsigned spi, char *filter) { - guint i; - guint filter_len = (guint)strlen(filter); + unsigned i; + unsigned filter_len = (unsigned)strlen(filter); /* "*" matches against anything */ if((filter_len == 1) && (filter[0] == IPSEC_SA_WILDCARDS_ANY)) - return TRUE; + return true; /* If the filter has a wildcard, treat SPI as a string */ if (strchr(filter, IPSEC_SA_WILDCARDS_ANY) != NULL) { - gchar spi_string[IPSEC_SPI_LEN_MAX]; + char spi_string[IPSEC_SPI_LEN_MAX]; snprintf(spi_string, IPSEC_SPI_LEN_MAX,"0x%08x", spi); /* Lengths need to match exactly... */ if(strlen(spi_string) != filter_len) - return FALSE; + return false; /* ... which means '*' can only appear in the last position of the filter? */ /* Start at 2, don't compare "0x" each time */ for(i = 2; filter[i]; i++) if((filter[i] != IPSEC_SA_WILDCARDS_ANY) && (filter[i] != spi_string[i])) - return FALSE; + return false; } else if (strtoul(filter, NULL, 0) != spi) { - return FALSE; + return false; } - return TRUE; + return true; } /* - Name : static goolean get_esp_sa(g_esp_sa_database *sad, gint protocol_typ, gchar *src, gchar *dst, guint spi, - gint *encryption_algo, - gint *authentication_algo, - gchar **encryption_key, - guint *encryption_key_len, - gchar **authentication_key, - guint *authentication_key_len, + Name : static goolean get_esp_sa(g_esp_sa_database *sad, int protocol_typ, char *src, char *dst, unsigned spi, + int *encryption_algo, + int *authentication_algo, + char **encryption_key, + unsigned *encryption_key_len, + char **authentication_key, + unsigned *authentication_key_len, gcry_cipher_hd_t **cipher_hd, - gboolean **cipher_hd_created + bool **cipher_hd_created Description : Give Encryption Algo, Key and Authentication Algo for a Packet if a corresponding SA is available in a Security Association database - Return: If the SA is not present, FALSE is then returned. + Return: If the SA is not present, false is then returned. Params: - g_esp_sa_database *sad : the Security Association Database - - gint *pt_protocol_typ : the protocol type - - gchar *src : the source address - - gchar *dst : the destination address - - gchar *spi : the spi of the SA - - gint *encryption_algo : the Encryption Algorithm to apply the packet - - gint *authentication_algo : the Authentication Algorithm to apply to the packet - - gchar **encryption_key : the Encryption Key to apply to the packet - - guint *encryption_key_len : the Encryption Key length to apply to the packet - - gchar **authentication_key : the Authentication Key to apply to the packet - - guint *authentication_key_len : the Authentication Key len to apply to the packet + - int *pt_protocol_typ : the protocol type + - char *src : the source address + - char *dst : the destination address + - char *spi : the spi of the SA + - int *encryption_algo : the Encryption Algorithm to apply the packet + - int *authentication_algo : the Authentication Algorithm to apply to the packet + - char **encryption_key : the Encryption Key to apply to the packet + - unsigned *encryption_key_len : the Encryption Key length to apply to the packet + - char **authentication_key : the Authentication Key to apply to the packet + - unsigned *authentication_key_len : the Authentication Key len to apply to the packet - gcry_cipher_hd_t **cipher_hd : pointer handle to be used for ciphering - - gboolean **cipher_hd_created: points to boolean indicating that cipher handle has - been created. If FALSE, should assign handle to - *cipher_hd and set this to TRUE. + - bool **cipher_hd_created: points to boolean indicating that cipher handle has + been created. If false, should assign handle to + *cipher_hd and set this to true. */ -static gboolean -get_esp_sa(gint protocol_typ, gchar *src, gchar *dst, guint spi, - gint *encryption_algo, - gint *authentication_algo, - gchar **encryption_key, - guint *encryption_key_len, - gchar **authentication_key, - guint *authentication_key_len, +static bool +get_esp_sa(int protocol_typ, char *src, char *dst, unsigned spi, + int *encryption_algo, + int *authentication_algo, + char **encryption_key, + unsigned *encryption_key_len, + char **authentication_key, + unsigned *authentication_key_len, gcry_cipher_hd_t **cipher_hd, - gboolean **cipher_hd_created + bool **cipher_hd_created, + uint8_t *sn_length, + uint32_t *sn_upper ) { - gboolean found = FALSE; - guint i, j; + bool found = false; + unsigned i, j; *cipher_hd = NULL; *cipher_hd_created = NULL; /* Check each known SA in turn */ - for (i = 0, j=0; (found == FALSE) && ((i < num_sa_uat) || (j < extra_esp_sa_records.num_records)); ) + for (i = 0, j=0; (found == false) && ((i < num_sa_uat) || (j < extra_esp_sa_records.num_records)); ) { /* Get the next record to try */ uat_esp_sa_record_t *record; @@ -1148,7 +1180,7 @@ get_esp_sa(gint protocol_typ, gchar *src, gchar *dst, guint spi, && filter_address_match(dst, record->dstIP, protocol_typ) && filter_spi_match(spi, record->spi)) { - found = TRUE; + found = true; *encryption_algo = record->encryption_algo; *authentication_algo = record->authentication_algo; @@ -1157,7 +1189,7 @@ get_esp_sa(gint protocol_typ, gchar *src, gchar *dst, guint spi, { /* Bad key; XXX - report this */ *authentication_key_len = 0; - found = FALSE; + found = false; } else { *authentication_key_len = record->authentication_key_length; @@ -1168,7 +1200,7 @@ get_esp_sa(gint protocol_typ, gchar *src, gchar *dst, guint spi, { /* Bad key; XXX - report this */ *encryption_key_len = 0; - found = FALSE; + found = false; } else { *encryption_key_len = record->encryption_key_length; @@ -1179,19 +1211,22 @@ get_esp_sa(gint protocol_typ, gchar *src, gchar *dst, guint spi, it opens the cipher_hd. */ *cipher_hd = &record->cipher_hd; *cipher_hd_created = &record->cipher_hd_created; + + *sn_length = record->sn_length; + *sn_upper = record->sn_upper; } } return found; } -static void ah_prompt(packet_info *pinfo, gchar *result) +static void ah_prompt(packet_info *pinfo, char *result) { snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IP protocol %u as", GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_ah, pinfo->curr_layer_num))); } -static gpointer ah_value(packet_info *pinfo) +static void *ah_value(packet_info *pinfo) { return p_get_proto_data(pinfo->pool, pinfo, proto_ah, pinfo->curr_layer_num); } @@ -1219,10 +1254,11 @@ static int esp_null_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *esp_tree) { int esp_packet_len, esp_pad_len, esp_icv_len, offset; - guint encapsulated_protocol; - guint32 saved_match_uint; - gboolean heur_ok; + unsigned encapsulated_protocol; + uint32_t saved_match_uint; + bool heur_ok; + proto_item *ti; tvbuff_t *next_tvb; dissector_handle_t dissector_handle; @@ -1246,8 +1282,8 @@ esp_null_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *esp_tree) if (tvb_bytes_exist(tvb, -(esp_icv_len + 2), 2)) { offset = esp_packet_len - (esp_icv_len + 2); - esp_pad_len = tvb_get_guint8(tvb, offset); - encapsulated_protocol = tvb_get_guint8(tvb, offset + 1); + esp_pad_len = tvb_get_uint8(tvb, offset); + encapsulated_protocol = tvb_get_uint8(tvb, offset + 1); dissector_handle = dissector_get_uint_handle(ip_dissector_table, encapsulated_protocol); if (dissector_handle == NULL) { continue; @@ -1255,15 +1291,29 @@ esp_null_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *esp_tree) if (ESP_HEADER_LEN + esp_pad_len > offset) { continue; } - heur_ok = TRUE; + heur_ok = true; for (int j=0; j < esp_pad_len; j++) { - if (tvb_get_guint8(tvb, offset - (j + 1)) != (esp_pad_len - j)) { - heur_ok = FALSE; + if (tvb_get_uint8(tvb, offset - (j + 1)) != (esp_pad_len - j)) { + heur_ok = false; break; } } if (!heur_ok) { - continue; + switch (g_esp_padding_type) { + case PADDING_RFC: + continue; + case PADDING_ZERO: + for (int j=0; j < esp_pad_len; j++) { + if (tvb_get_uint8(tvb, offset - (j + 1)) != 0) { + continue; + } + } + /* FALLTHROUGH */ + case PADDING_ANY: + break; + default: + continue; + } } saved_match_uint = pinfo->match_uint; @@ -1286,9 +1336,12 @@ esp_null_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *esp_tree) if (esp_tree) { if (esp_pad_len !=0) { - proto_tree_add_item(esp_tree, hf_esp_pad, + ti = proto_tree_add_item(esp_tree, hf_esp_pad, tvb, offset - esp_pad_len, esp_pad_len, ENC_NA); + if (!heur_ok) { + expert_add_info(pinfo, ti, &ei_esp_pad_bogus); + } } proto_tree_add_uint(esp_tree, hf_esp_pad_len, tvb, @@ -1308,18 +1361,18 @@ esp_null_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *esp_tree) return esp_icv_len; } -static gboolean -capture_ah(const guchar *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header) +static bool +capture_ah(const unsigned char *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header) { - guint8 nxt; + uint8_t nxt; int advance; if (!BYTES_ARE_IN_FRAME(offset, len, 2)) - return FALSE; + return false; nxt = pd[offset]; advance = 8 + ((pd[offset+1] - 1) << 2); if (!BYTES_ARE_IN_FRAME(offset, len, advance)) - return FALSE; + return false; offset += advance; return try_capture_dissector("ip.proto", nxt, pd, offset, len, cpinfo, pseudo_header); @@ -1330,20 +1383,20 @@ dissect_ah(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *ah_tree, *root_tree; proto_item *pi, *ti; - guint ah_nxt; /* Next header */ - guint8 ah_len; /* Length of header in 32bit words minus 2 */ - guint ah_hdr_len; /* Length of header in octets */ - guint ah_icv_len; /* Length of ICV header field in octets */ - guint32 ah_spi; /* Security parameter index */ + unsigned ah_nxt; /* Next header */ + uint8_t ah_len; /* Length of header in 32bit words minus 2 */ + unsigned ah_hdr_len; /* Length of header in octets */ + unsigned ah_icv_len; /* Length of ICV header field in octets */ + uint32_t ah_spi; /* Security parameter index */ tvbuff_t *next_tvb; dissector_handle_t dissector_handle; - guint32 saved_match_uint; + uint32_t saved_match_uint; col_set_str(pinfo->cinfo, COL_PROTOCOL, "AH"); col_clear(pinfo->cinfo, COL_INFO); - ah_nxt = tvb_get_guint8(tvb, 0); - ah_len = tvb_get_guint8(tvb, 1); + ah_nxt = tvb_get_uint8(tvb, 0); + ah_len = tvb_get_uint8(tvb, 1); ah_hdr_len = (ah_len + 2) * 4; ah_icv_len = ah_len ? (ah_len - 1) * 4 : 0; @@ -1398,49 +1451,49 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) proto_item *iv_item = NULL, *encr_data_item = NULL, *icv_item = NULL; /* Packet Variables related */ - gchar *ip_src = NULL; - gchar *ip_dst = NULL; + char *ip_src = NULL; + char *ip_dst = NULL; - guint32 spi = 0; - guint encapsulated_protocol = 0; - gboolean decrypt_dissect_ok = FALSE; + uint32_t spi = 0; + unsigned encapsulated_protocol = 0; + bool decrypt_dissect_ok = false; tvbuff_t *next_tvb; dissector_handle_t dissector_handle; - guint32 saved_match_uint; + uint32_t saved_match_uint; - gboolean null_encryption_decode_heuristic = FALSE; - guint8 *esp_iv = NULL; - guint8 *esp_encr_data = NULL; - guint8 *esp_decr_data = NULL; - guint8 *esp_icv = NULL; + bool null_encryption_decode_heuristic = false; + uint8_t *esp_iv = NULL; + uint8_t *esp_encr_data = NULL; + uint8_t *esp_decr_data = NULL; + uint8_t *esp_icv = NULL; tvbuff_t *tvb_decrypted = NULL; /* IPSEC encryption Variables related */ - gint protocol_typ = IPSEC_SA_UNKNOWN; - gint esp_encr_algo = IPSEC_ENCRYPT_NULL; - gint esp_auth_algo = IPSEC_AUTH_NULL; - gint icv_type = ICV_TYPE_UNCHECKED; - gchar *esp_encr_key = NULL; - gchar *esp_auth_key = NULL; - guint esp_encr_key_len = 0; - guint esp_auth_key_len = 0; + int protocol_typ = IPSEC_SA_UNKNOWN; + int esp_encr_algo = IPSEC_ENCRYPT_NULL; + int esp_auth_algo = IPSEC_AUTH_NULL; + int icv_type = ICV_TYPE_UNCHECKED; + char *esp_encr_key = NULL; + char *esp_auth_key = NULL; + unsigned esp_encr_key_len = 0; + unsigned esp_auth_key_len = 0; gcry_cipher_hd_t *cipher_hd; - gboolean *cipher_hd_created; - - gint offset = 0; - gint esp_packet_len = 0; - gint esp_iv_len = 0; - gint esp_block_len = 0; - gint esp_encr_data_len = 0; - gint esp_decr_data_len = 0; - gint esp_icv_len = 0; - gint esp_salt_len = 0; - gboolean decrypt_ok = FALSE; - gboolean decrypt_using_libgcrypt = FALSE; - gboolean icv_checked = FALSE; - gboolean icv_correct = FALSE; - gboolean sad_is_present = FALSE; - gint esp_pad_len = 0; + bool *cipher_hd_created; + + int offset = 0; + int esp_packet_len = 0; + int esp_iv_len = 0; + int esp_block_len = 0; + int esp_encr_data_len = 0; + int esp_decr_data_len = 0; + int esp_icv_len = 0; + int esp_salt_len = 0; + bool decrypt_ok = false; + bool decrypt_using_libgcrypt = false; + bool icv_checked = false; + bool icv_correct = false; + bool sad_is_present = false; + int esp_pad_len = 0; /* Variables for decryption and authentication checking used for libgrypt */ @@ -1450,11 +1503,13 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) int crypt_algo_libgcrypt = 0; int crypt_mode_libgcrypt = 0; int auth_algo_libgcrypt = 0; - gchar *esp_icv_expected = NULL; /* as readable hex string, for error messages */ + char *esp_icv_expected = NULL; /* as readable hex string, for error messages */ unsigned char ctr_block[16]; - guint32 sequence_number; + uint32_t sequence_number; + uint8_t sn_length = IPSEC_SA_SN; + uint32_t sn_upper = 0; /* * load the top pane info. This should be overwritten by @@ -1498,11 +1553,11 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) /* The SAD is not activated */ if(g_esp_enable_null_encryption_decode_heuristic && !g_esp_enable_encryption_decode) - null_encryption_decode_heuristic = TRUE; + null_encryption_decode_heuristic = true; if(g_esp_enable_encryption_decode || g_esp_enable_authentication_check) { - /* Get Source & Destination Addresses in gchar * with all the bytes available. */ + /* Get Source & Destination Addresses in char * with all the bytes available. */ if (pinfo->src.type == AT_IPv4){ protocol_typ = IPSEC_SA_IPV4; @@ -1511,8 +1566,8 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) } /* Create strings for src, dst addresses */ - ip_src = address_to_str(wmem_packet_scope(), &pinfo->src); - ip_dst = address_to_str(wmem_packet_scope(), &pinfo->dst); + ip_src = address_to_str(pinfo->pool, &pinfo->src); + ip_dst = address_to_str(pinfo->pool, &pinfo->dst); /* Get the SPI */ if (tvb_captured_length(tvb) >= 4) @@ -1529,7 +1584,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) if((sad_is_present = get_esp_sa(protocol_typ, ip_src, ip_dst, spi, &esp_encr_algo, &esp_auth_algo, &esp_encr_key, &esp_encr_key_len, &esp_auth_key, &esp_auth_key_len, - &cipher_hd, &cipher_hd_created))) + &cipher_hd, &cipher_hd_created, &sn_length, &sn_upper))) { switch(esp_auth_algo) @@ -1591,6 +1646,29 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) if(g_esp_enable_authentication_check) { + if (sn_length == IPSEC_SA_ESN && g_esp_do_sequence_analysis) { + spi_status *status = (spi_status*)wmem_map_lookup(esp_sequence_analysis_hash, + GUINT_TO_POINTER((unsigned)spi)); + /* We only support 2^32 - 1 frames (and only 2^31 - 1 in the Qt packet + * list), so at most we can overflow once. In a normal capture we + * expect half the frames to be from each direction, too. The proper + * method in RFC 4303 Appendix A involves storing valid sequence + * numbers at multiple points for subsequent passes to slide the window, + * but we shouldn't need to. */ + if (status && status->firstValidSN) { + const uint32_t window = 0x8000U; + if (status->firstValidSN >= window) { + if (sequence_number < (status->firstValidSN - window)) { + sn_upper++; + } + } else { + if (sequence_number >= (status->firstValidSN - window)) { + sn_upper--; + } + } + } + } + switch(esp_auth_algo) { case IPSEC_AUTH_HMAC_SHA1_96: @@ -1617,7 +1695,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) /* case IPSEC_AUTH_AES_XCBC_MAC_96: auth_algo_libgcrypt = - authentication_check_using_libgcrypt = TRUE; + authentication_check_using_libgcrypt = true; break; */ @@ -1679,7 +1757,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) if(icv_type == ICV_TYPE_HMAC) { /* Allocate buffer for ICV */ - esp_icv = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, esp_packet_len - esp_icv_len, esp_icv_len); + esp_icv = (uint8_t *)tvb_memdup(pinfo->pool, tvb, esp_packet_len - esp_icv_len, esp_icv_len); err = gcry_md_open (&md_hd, auth_algo_libgcrypt, GCRY_MD_FLAG_HMAC); if (err) @@ -1705,6 +1783,14 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) gcry_md_write (md_hd, tvb_get_ptr(tvb, 0, esp_packet_len - esp_icv_len), esp_packet_len - esp_icv_len); + if (sn_length == IPSEC_SA_ESN) { + uint8_t sn_bytes[4]; + phton32(sn_bytes, sn_upper); + for (int i = 0; i < 4; i++) { + gcry_md_putc(md_hd, sn_bytes[i]); + } + } + esp_icv_computed = gcry_md_read (md_hd, auth_algo_libgcrypt); if (esp_icv_computed == 0) { @@ -1714,12 +1800,12 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) } if(memcmp (esp_icv_computed, esp_icv, esp_icv_len) == 0) { - icv_checked = TRUE; - icv_correct = TRUE; + icv_checked = true; + icv_correct = true; } else { - icv_checked = TRUE; - icv_correct = FALSE; - esp_icv_expected = bytes_to_str(wmem_packet_scope(), esp_icv_computed, esp_icv_len); + icv_checked = true; + icv_correct = false; + esp_icv_expected = bytes_to_str(pinfo->pool, esp_icv_computed, esp_icv_len); } } @@ -1731,7 +1817,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) if(g_esp_enable_encryption_decode) { /* Deactivation of the Heuristic to decrypt using the NULL encryption algorithm since the packet is matching a SA */ - null_encryption_decode_heuristic = FALSE; + null_encryption_decode_heuristic = false; switch(esp_encr_algo) { @@ -1756,10 +1842,10 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) REPORT_DISSECTOR_BUG("<ESP Preferences> Error in Encryption Algorithm 3DES-CBC : Bad Keylen (got %u Bits, need %lu)\n", esp_encr_key_len * 8, (unsigned long) gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt) * 8); - decrypt_ok = FALSE; + decrypt_ok = false; } else - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; @@ -1779,23 +1865,23 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { case 128: crypt_algo_libgcrypt = GCRY_CIPHER_AES128; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; case 192: crypt_algo_libgcrypt = GCRY_CIPHER_AES192; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; case 256: crypt_algo_libgcrypt = GCRY_CIPHER_AES256; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; default: REPORT_DISSECTOR_BUG("<ESP Preferences> Error in Encryption Algorithm AES-CBC : Bad Keylen (%u Bits)\n", esp_encr_key_len * 8); - decrypt_ok = FALSE; + decrypt_ok = false; } break; @@ -1816,12 +1902,12 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { case 128: crypt_algo_libgcrypt = GCRY_CIPHER_CAST5; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; default: REPORT_DISSECTOR_BUG("<ESP Preferences> Error in Encryption Algorithm CAST5-CBC : Bad Keylen (%u Bits)\n", esp_encr_key_len * 8); - decrypt_ok = FALSE; + decrypt_ok = false; } break; @@ -1842,10 +1928,10 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { REPORT_DISSECTOR_BUG("<ESP Preferences> Error in Encryption Algorithm DES-CBC : Bad Keylen (%u Bits, need %lu)\n", esp_encr_key_len * 8, (unsigned long) gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt) * 8); - decrypt_ok = FALSE; + decrypt_ok = false; } else - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; @@ -1872,24 +1958,24 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { case 128: crypt_algo_libgcrypt = GCRY_CIPHER_AES128; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; case 192: crypt_algo_libgcrypt = GCRY_CIPHER_AES192; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; case 256: crypt_algo_libgcrypt = GCRY_CIPHER_AES256; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; default: REPORT_DISSECTOR_BUG("<ESP Preferences> Error in Encryption Algorithm %s : Bad Keylen (%u Bits)\n", (esp_encr_algo == IPSEC_ENCRYPT_AES_CTR) ? "AES-CTR" : "AES-GCM", esp_encr_key_len * 8); - decrypt_ok = FALSE; + decrypt_ok = false; } if (esp_encr_algo == IPSEC_ENCRYPT_AES_GCM) { @@ -1916,18 +2002,18 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { case 128: crypt_algo_libgcrypt = GCRY_CIPHER_TWOFISH128; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; case 256: crypt_algo_libgcrypt = GCRY_CIPHER_TWOFISH; - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; default: REPORT_DISSECTOR_BUG("<ESP Preferences> Error in Encryption Algorithm TWOFISH-CBC : Bad Keylen (%u Bits)\n", esp_encr_key_len * 8); - decrypt_ok = FALSE; + decrypt_ok = false; } break; @@ -1950,10 +2036,10 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { REPORT_DISSECTOR_BUG("<ESP Preferences> Error in Encryption Algorithm BLOWFISH-CBC : Bad Keylen (%u Bits, need %lu)\n", esp_encr_key_len * 8, (unsigned long) gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt) * 8); - decrypt_ok = FALSE; + decrypt_ok = false; } else - decrypt_using_libgcrypt = TRUE; + decrypt_using_libgcrypt = true; break; @@ -1965,11 +2051,11 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) /* Allocate buffer for decrypted data */ esp_decr_data_len = esp_encr_data_len - esp_icv_len; - esp_decr_data = (guint8 *)wmem_alloc(wmem_packet_scope(), esp_decr_data_len); + esp_decr_data = (uint8_t *)wmem_alloc(pinfo->pool, esp_decr_data_len); tvb_memcpy(tvb, esp_decr_data, ESP_HEADER_LEN, esp_decr_data_len); - decrypt_ok = TRUE; + decrypt_ok = true; break; } @@ -1993,7 +2079,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) iv_item = proto_tree_add_item(esp_tree, hf_esp_iv, tvb, offset, esp_iv_len, ENC_NA); proto_item_append_text(iv_item, " (%d bytes)", esp_iv_len); - esp_iv = (guchar *)tvb_memdup(wmem_packet_scope(), tvb, offset, esp_iv_len); + esp_iv = (unsigned char *)tvb_memdup(pinfo->pool, tvb, offset, esp_iv_len); offset += esp_iv_len; } @@ -2007,7 +2093,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) esp_encr_data_len, esp_get_encr_algo_name(esp_encr_algo)); - esp_encr_data = (guchar *)tvb_memdup(wmem_packet_scope(), tvb, offset, esp_encr_data_len); + esp_encr_data = (unsigned char *)tvb_memdup(pinfo->pool, tvb, offset, esp_encr_data_len); offset += esp_encr_data_len; /* @@ -2020,10 +2106,10 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) if (esp_block_len > 4 && esp_encr_data_len % esp_block_len != 0) { proto_item_append_text(encr_data_item, "[Invalid length, ciphertext should be a multiple of block size (%u)]", esp_block_len); - decrypt_using_libgcrypt = FALSE; + decrypt_using_libgcrypt = false; } else if (esp_encr_data_len % 4 != 0) { proto_item_append_text(encr_data_item, "[Invalid length, ciphertext should terminate at 4-byte boundary]"); - decrypt_using_libgcrypt = FALSE; + decrypt_using_libgcrypt = false; } } @@ -2048,7 +2134,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) /* * Allocate buffer for decrypted data. */ - esp_decr_data = (guchar*)wmem_alloc(pinfo->pool, esp_encr_data_len); + esp_decr_data = (unsigned char*)wmem_alloc(pinfo->pool, esp_encr_data_len); esp_decr_data_len = esp_encr_data_len; tvb_memcpy(tvb, esp_decr_data, ESP_HEADER_LEN, esp_encr_data_len); @@ -2063,7 +2149,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) else { /* OK, set the key */ - if (*cipher_hd_created == FALSE) + if (*cipher_hd_created == false) { err = gcry_cipher_setkey(*cipher_hd, esp_encr_key, esp_encr_key_len); @@ -2075,7 +2161,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) } /* Key is created and has its key set now */ - *cipher_hd_created = TRUE; + *cipher_hd_created = true; } } @@ -2119,9 +2205,17 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) if (g_esp_enable_authentication_check && icv_type == ICV_TYPE_AEAD) { /* Allocate buffer for ICV */ - esp_icv = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, esp_packet_len - esp_icv_len, esp_icv_len); + esp_icv = (uint8_t *)tvb_memdup(pinfo->pool, tvb, esp_packet_len - esp_icv_len, esp_icv_len); - err = gcry_cipher_authenticate(*cipher_hd, tvb_get_ptr(tvb, 0, ESP_HEADER_LEN), ESP_HEADER_LEN); + if (sn_length == IPSEC_SA_SN) { + err = gcry_cipher_authenticate(*cipher_hd, tvb_get_ptr(tvb, 0, ESP_HEADER_LEN), ESP_HEADER_LEN); + } else { + uint8_t *aad = wmem_alloc(pinfo->pool, ESP_HEADER_LEN + 4); + tvb_memcpy(tvb, aad, 0, 4); + phton32(&aad[4], sn_upper); + tvb_memcpy(tvb, &aad[ESP_HEADER_LEN], 4, ESP_HEADER_LEN); + err = gcry_cipher_authenticate(*cipher_hd, aad, ESP_HEADER_LEN + 4); + } if (err) { gcry_cipher_close(*cipher_hd); @@ -2144,20 +2238,20 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) else { /* Decryption has finished */ - decrypt_ok = TRUE; + decrypt_ok = true; if (g_esp_enable_authentication_check && icv_type == ICV_TYPE_AEAD) { - guchar *esp_icv_computed; - gint tag_len; + unsigned char *esp_icv_computed; + int tag_len; - tag_len = (gint)gcry_cipher_get_algo_blklen(crypt_algo_libgcrypt); + tag_len = (int)gcry_cipher_get_algo_blklen(crypt_algo_libgcrypt); if (tag_len < esp_icv_len) { fprintf (stderr, "<IPsec/ESP Dissector> Error in Algorithm %s, tag length (%d) is less than icv length (%d)\n", gcry_md_algo_name(crypt_algo_libgcrypt), tag_len, esp_icv_len); } - esp_icv_computed = (guchar *)wmem_alloc(wmem_packet_scope(), tag_len); + esp_icv_computed = (unsigned char *)wmem_alloc(pinfo->pool, tag_len); err = gcry_cipher_gettag(*cipher_hd, esp_icv_computed, tag_len); if (err) { gcry_cipher_close(*cipher_hd); @@ -2166,12 +2260,12 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) } if (memcmp(esp_icv_computed, esp_icv, esp_icv_len) == 0) { - icv_checked = TRUE; - icv_correct = TRUE; + icv_checked = true; + icv_correct = true; } else { - icv_checked = TRUE; - icv_correct = FALSE; - esp_icv_expected = bytes_to_str(wmem_packet_scope(), esp_icv_computed, esp_icv_len); + icv_checked = true; + icv_correct = false; + esp_icv_expected = bytes_to_str(pinfo->pool, esp_icv_computed, esp_icv_len); } } } @@ -2181,12 +2275,12 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) else if(g_esp_enable_null_encryption_decode_heuristic) { /* The packet does not belong to a Security Association */ - null_encryption_decode_heuristic = TRUE; + null_encryption_decode_heuristic = true; } if(decrypt_ok) { - tvb_decrypted = tvb_new_child_real_data(tvb, (guint8 *)wmem_memdup(pinfo->pool, esp_decr_data, esp_decr_data_len), + tvb_decrypted = tvb_new_child_real_data(tvb, (uint8_t *)wmem_memdup(pinfo->pool, esp_decr_data, esp_decr_data_len), esp_decr_data_len, esp_decr_data_len); add_new_data_source(pinfo, tvb_decrypted, "Decrypted Data"); @@ -2199,9 +2293,9 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) * we need to read to determine the encapsulated protocol */ if(tvb_bytes_exist(tvb_decrypted, esp_decr_data_len - 2, 2)) { - gint esp_contained_data_len; + int esp_contained_data_len; - esp_pad_len = tvb_get_guint8(tvb_decrypted, esp_decr_data_len - 2); + esp_pad_len = tvb_get_uint8(tvb_decrypted, esp_decr_data_len - 2); esp_contained_data_len = esp_decr_data_len - esp_pad_len - 2; if(esp_contained_data_len > 0) @@ -2210,7 +2304,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) proto_item_append_text(item, " (%d byte%s)", esp_contained_data_len, plurality(esp_contained_data_len, "", "s")); /* Get the encapsulated protocol */ - encapsulated_protocol = tvb_get_guint8(tvb_decrypted, esp_decr_data_len - 1); + encapsulated_protocol = tvb_get_uint8(tvb_decrypted, esp_decr_data_len - 1); dissector_handle = dissector_get_uint_handle(ip_dissector_table, encapsulated_protocol); if (dissector_handle) { @@ -2229,7 +2323,7 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) export_ipsec_pdu(dissector_handle, pinfo, next_tvb); call_dissector(dissector_handle, next_tvb, pinfo, tree); pinfo->match_uint = saved_match_uint; - decrypt_dissect_ok = TRUE; + decrypt_dissect_ok = true; } } } @@ -2305,17 +2399,24 @@ dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) if(icv_item != NULL) { - gboolean good = FALSE, bad = FALSE; + bool good = false, bad = false; icv_tree = proto_item_add_subtree(icv_item, ett_esp_icv); if(icv_checked) { if (icv_correct) { proto_item_append_text(icv_item, " [correct]"); - good = TRUE; + good = true; + if (sn_length == IPSEC_SA_ESN && g_esp_do_sequence_analysis) { + spi_status *status = (spi_status*)wmem_map_lookup(esp_sequence_analysis_hash, + GUINT_TO_POINTER((unsigned)spi)); + if (status && !status->firstValidSN) { + status->firstValidSN = sequence_number; + } + } } else { proto_item_append_text(icv_item, " [incorrect, should be %s]", esp_icv_expected); - bad = TRUE; + bad = true; } } else { proto_item_append_text(icv_item, " [unchecked]"); @@ -2339,10 +2440,10 @@ dissect_ipcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dissec { proto_tree *ipcomp_tree; proto_item *ti; - guint8 comp_nxt; /* Next Header */ - guint32 comp_cpi; /* Compression parameter index */ + uint8_t comp_nxt; /* Next Header */ + uint32_t comp_cpi; /* Compression parameter index */ dissector_handle_t dissector_handle; - guint32 saved_match_uint; + uint32_t saved_match_uint; tvbuff_t *data, *decomp; /* @@ -2352,7 +2453,7 @@ dissect_ipcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dissec col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPComp"); col_clear(pinfo->cinfo, COL_INFO); - comp_nxt = tvb_get_guint8(tvb, 0); + comp_nxt = tvb_get_uint8(tvb, 0); /* * populate a tree in the second pane with the status of the link layer @@ -2375,9 +2476,9 @@ dissect_ipcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dissec /* * try to uncompress as if it were DEFLATEd. With negotiated * CPIs, we don't know the algorithm beforehand; if we get it - * wrong, tvb_child_uncompress() returns NULL and nothing is displayed. + * wrong, tvb_child_uncompress_zlib() returns NULL and nothing is displayed. */ - decomp = tvb_child_uncompress(data, data, 0, tvb_captured_length(data)); + decomp = tvb_child_uncompress_zlib(data, data, 0, tvb_captured_length(data)); if (decomp) { add_new_data_source(pinfo, decomp, "IPcomp inflated data"); saved_match_uint = pinfo->match_uint; @@ -2398,7 +2499,7 @@ dissect_ipcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dissec static void ipsec_cleanup_protocol(void) { /* Free any SA records added by other dissectors */ - guint n; + unsigned n; for (n=0; n < extra_esp_sa_records.num_records; n++) { uat_esp_sa_record_free_cb(&(extra_esp_sa_records.records[n])); } @@ -2490,7 +2591,7 @@ proto_register_ipsec(void) "IP Payload Compression Protocol Compression Parameter Index", HFILL }}, }; - static gint *ett[] = { + static int *ett[] = { &ett_ah, &ett_esp, &ett_esp_icv, @@ -2499,7 +2600,8 @@ proto_register_ipsec(void) }; static ei_register_info ei[] = { - { &ei_esp_sequence_analysis_wrong_sequence_number, { "esp.sequence-analysis.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }} + { &ei_esp_sequence_analysis_wrong_sequence_number, { "esp.sequence-analysis.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }}, + { &ei_esp_pad_bogus, { "esp.pad.bogus", PI_PROTOCOL, PI_WARN, "Padding MUST increment starting with 1 [RFC 4303 2.4]", EXPFILL }} }; static const value_string esp_proto_type_vals[] = { @@ -2508,6 +2610,12 @@ proto_register_ipsec(void) { 0x00, NULL } }; + static const value_string esp_sn_length_vals[] = { + { IPSEC_SA_SN, "32-bit" }, + { IPSEC_SA_ESN, "64-bit" }, + { 0x00, NULL } + }; + static uat_field_t esp_uat_flds[] = { UAT_FLD_VS(uat_esp_sa_records, protocol, "Protocol", esp_proto_type_vals, "Protocol used"), UAT_FLD_CSTRING(uat_esp_sa_records, srcIP, "Src IP", "Source Address"), @@ -2517,6 +2625,8 @@ proto_register_ipsec(void) UAT_FLD_CSTRING(uat_esp_sa_records, encryption_key_string, "Encryption Key", "Encryption Key"), UAT_FLD_VS(uat_esp_sa_records, authentication_algo, "Authentication", esp_authentication_type_vals, "Authentication algorithm"), UAT_FLD_CSTRING(uat_esp_sa_records, authentication_key_string, "Authentication Key", "Authentication Key"), + UAT_FLD_VS(uat_esp_sa_records, sn_length, "SN", esp_sn_length_vals, "Sequence Number length"), + UAT_FLD_HEX(uat_esp_sa_records, sn_upper, "ESN High Bits", "Extended Sequence Number upper 32 bits (hex)"), UAT_END_FIELDS }; @@ -2558,6 +2668,17 @@ proto_register_ipsec(void) "Does not detect ENCR_NULL_AUTH_AES_GMAC (i.e. assumes 0 length IV)", &g_esp_enable_null_encryption_decode_heuristic); + prefs_register_enum_preference(esp_module, "padding", + "Padding type accepted", + "RFC 4303 2.4 requires that padding bytes, if present, MUST " + "be the monotonically increasing sequence 1, 2, 3, …. " + "Some implementations add non-compliant padding. " + "This option determines what, if any, non-compliant padding " + "the NULL encryption heuristic will allow. " + "WARNING: Allowing non-compliant padding can lead to " + "significant false positives.", + &g_esp_padding_type, esp_padding_vals, false); + prefs_register_bool_preference(esp_module, "do_esp_sequence_analysis", "Check sequence numbers of ESP frames", "Check that successive frames increase sequence number by 1 within an SPI. This should work OK when only one host is sending frames on an SPI", @@ -2576,7 +2697,7 @@ proto_register_ipsec(void) esp_uat = uat_new("ESP SAs", sizeof(uat_esp_sa_record_t), /* record size */ "esp_sa", /* filename */ - TRUE, /* from_profile */ + true, /* from_profile */ &uat_esp_sa_records, /* data_ptr */ &num_sa_uat, /* numitems_ptr */ UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */ @@ -2588,6 +2709,10 @@ proto_register_ipsec(void) NULL, /* reset callback */ esp_uat_flds); /* UAT field definitions */ + static const char *esp_uat_defaults_[] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "32-bit", "0" }; + uat_set_default_values(esp_uat, esp_uat_defaults_); + prefs_register_uat_preference(esp_module, "sa_table", "ESP SAs", |