summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ipsec.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-ipsec.c')
-rw-r--r--epan/dissectors/packet-ipsec.c781
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",