1999-03-29 02:21:34 +00:00
|
|
|
/* packet-ipsec.c
|
2002-08-28 21:04:11 +00:00
|
|
|
* Routines for IPsec/IPComp packet disassembly
|
1999-03-29 02:21:34 +00:00
|
|
|
*
|
2006-05-21 04:49:01 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
1999-03-29 02:21:34 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
2006-08-09 02:00:05 +00:00
|
|
|
*
|
1999-03-29 02:21:34 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1999-03-29 02:21:34 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1999-03-29 02:21:34 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-06-28 22:56:06 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
1999-03-29 02:21:34 +00:00
|
|
|
*/
|
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
|
2006-04-13 22:26:13 +00:00
|
|
|
Addon: ESP Decryption and Authentication Checking
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
Frederic ROUDAUT (frederic.roudaut@free.fr)
|
|
|
|
Copyright 2006 Frederic ROUDAUT
|
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
- Decrypt ESP Payload for the following Algorithms defined in RFC 4305:
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
Encryption Algorithm
|
|
|
|
--------------------
|
|
|
|
NULL
|
|
|
|
TripleDES-CBC [RFC2451] : keylen 192 bits.
|
|
|
|
AES-CBC with 128-bit keys [RFC3602] : keylen 128 and 192/256 bits.
|
|
|
|
AES-CTR [RFC3686] : keylen 160/224/288 bits. The remaining 32 bits will be used as nonce.
|
|
|
|
DES-CBC [RFC2405] : keylen 64 bits
|
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
- Add ESP Payload Decryption support for the following Encryption Algorithms :
|
|
|
|
BLOWFISH-CBC : keylen 128 bits.
|
|
|
|
TWOFISH-CBC : keylen 128/256 bits.
|
2009-03-25 18:04:30 +00:00
|
|
|
CAST5-CBC : keylen 128
|
2006-04-13 22:26:13 +00:00
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
- Check ESP Authentication for the following Algorithms defined in RFC 4305:
|
2006-04-13 22:26:13 +00:00
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
Authentication Algorithm
|
2006-03-27 16:25:35 +00:00
|
|
|
------------------------
|
2006-08-09 02:00:05 +00:00
|
|
|
NULL
|
2006-04-13 22:26:13 +00:00
|
|
|
HMAC-SHA1-96 [RFC2404] : any keylen
|
|
|
|
HMAC-MD5-96 [RFC2403] : any keylen
|
2006-08-09 02:00:05 +00:00
|
|
|
AES-XCBC-MAC-96 [RFC3566] : Not available because no implementation found.
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
- Add ESP Authentication checking for the following Authentication Algorithm :
|
2006-04-13 22:26:13 +00:00
|
|
|
HMAC-SHA256 : any keylen
|
2009-03-25 18:04:30 +00:00
|
|
|
HMAC-RIPEMD160-96 [RFC2857] : any keylen
|
2009-07-16 19:57:15 +00:00
|
|
|
|
|
|
|
- Added/Modified Authentication checking (David Dahlberg <dahlberg@fgan.de>):
|
|
|
|
CHG: HMAC-SHA256 is now HMAC-SHA-256-96 [draft-ietf-ipsec-ciph-sha-256-00]
|
|
|
|
-> It is implemented this way in USAGI/KAME (Linux/BSD).
|
|
|
|
ADD: HMAC-SHA-256-128 [RFC4868]
|
2009-12-21 21:06:01 +00:00
|
|
|
ICV length of HMAC-SHA-256 was changed in draft-ietf-ipsec-ciph-sha-256-01
|
2009-07-16 19:57:15 +00:00
|
|
|
to 128 bit. This is "SHOULD" be the standard now!
|
|
|
|
ADD: Additional generic (non-checked) ICV length of 128, 192 and 256.
|
|
|
|
This follows RFC 4868 for the SHA-256+ family.
|
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2011-05-20 19:00:09 +00:00
|
|
|
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
2004-08-06 19:57:49 +00:00
|
|
|
#include <epan/addr_resolv.h>
|
2004-09-29 00:52:45 +00:00
|
|
|
#include <epan/ipproto.h>
|
2004-09-27 22:55:15 +00:00
|
|
|
#include <epan/prefs.h>
|
2014-09-09 22:26:31 +00:00
|
|
|
#include <epan/expert.h>
|
2013-06-18 23:01:46 +00:00
|
|
|
#include <epan/tap.h>
|
|
|
|
#include <epan/exported_pdu.h>
|
2000-07-08 10:46:23 +00:00
|
|
|
|
2006-09-08 07:32:13 +00:00
|
|
|
/* If you want to be able to decrypt or Check Authentication of ESP packets you MUST define this : */
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2014-04-30 17:25:12 +00:00
|
|
|
#include <stdio.h>
|
2011-06-02 07:11:26 +00:00
|
|
|
#include <epan/uat.h>
|
2013-02-21 18:23:29 +00:00
|
|
|
#include <wsutil/wsgcrypt.h>
|
2006-08-09 02:00:05 +00:00
|
|
|
#endif /* HAVE_LIBGCRYPT */
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
#include "packet-ipsec.h"
|
|
|
|
|
2013-12-14 12:45:57 +00:00
|
|
|
void proto_register_ipsec(void);
|
|
|
|
void proto_reg_handoff_ipsec(void);
|
strcasecmp(), strncasecmp(), g_strcasecmp(), and g_strncasecmp() delenda
est. Use g_ascii_strcasecmp() and g_ascii_strncasecmp(), and supply our
own versions if they're missing from GLib (as is the case with GLib
1.x).
In the code to build the list of named fields for Diameter, don't use
g_strdown(); do our own g_ascii_-style upper-case to lower-case mapping
in the hash function and use g_ascii_strcasecmp() in the compare
function.
We do this because there is no guarantee that toupper(), tolower(), and
functions that use them will, for example, map between "I" and "i" in
all locales; in Turkish locales, for example, there are, in both
upper case and lower case, versions of "i" with and without a dot, and
the upper-case version of "i" is "I"-with-a-dot and the lower-case
version of "I" is "i"-without-a-dot. This causes strings that should
match not to match.
This finishes fixing bug 2010 - an earlier checkin prevented the crash
(as there are other ways to produce the same crash, e.g. a bogus
dictionary.xml file), but didn't fix the case-insensitive string matching.
svn path=/trunk/; revision=23623
2007-11-27 18:52:51 +00:00
|
|
|
|
2006-04-13 22:26:13 +00:00
|
|
|
static int proto_ah = -1;
|
2014-11-01 20:55:25 +00:00
|
|
|
static int hf_ah_next_header = -1;
|
|
|
|
static int hf_ah_length = -1;
|
1999-10-11 12:37:50 +00:00
|
|
|
static int hf_ah_spi = -1;
|
2006-09-12 09:53:10 +00:00
|
|
|
static int hf_ah_iv = -1;
|
1999-10-11 12:37:50 +00:00
|
|
|
static int hf_ah_sequence = -1;
|
1999-07-29 05:47:07 +00:00
|
|
|
static int proto_esp = -1;
|
1999-10-11 12:37:50 +00:00
|
|
|
static int hf_esp_spi = -1;
|
2006-09-12 09:53:10 +00:00
|
|
|
static int hf_esp_iv = -1;
|
2012-10-11 20:38:39 +00:00
|
|
|
static int hf_esp_icv_good = -1;
|
|
|
|
static int hf_esp_icv_bad = -1;
|
1999-10-11 12:37:50 +00:00
|
|
|
static int hf_esp_sequence = -1;
|
2014-11-01 20:55:25 +00:00
|
|
|
static int hf_esp_pad = -1;
|
2006-04-13 22:26:13 +00:00
|
|
|
static int hf_esp_pad_len = -1;
|
2004-11-12 10:03:53 +00:00
|
|
|
static int hf_esp_protocol = -1;
|
2014-11-01 20:55:25 +00:00
|
|
|
static int hf_esp_authentication_data = -1;
|
2014-09-09 22:26:31 +00:00
|
|
|
static int hf_esp_sequence_analysis_expected_sn = -1;
|
|
|
|
static int hf_esp_sequence_analysis_previous_frame = -1;
|
|
|
|
|
1999-10-15 05:30:43 +00:00
|
|
|
static int proto_ipcomp = -1;
|
2014-11-01 20:55:25 +00:00
|
|
|
static int hf_ipcomp_next_header = -1;
|
1999-10-15 05:46:18 +00:00
|
|
|
static int hf_ipcomp_flags = -1;
|
1999-10-15 05:30:43 +00:00
|
|
|
static int hf_ipcomp_cpi = -1;
|
1999-07-29 05:47:07 +00:00
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint ett_ah = -1;
|
|
|
|
static gint ett_esp = -1;
|
2012-10-11 20:38:39 +00:00
|
|
|
static gint ett_esp_icv = -1;
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint ett_ipcomp = -1;
|
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
static expert_field ei_esp_sequence_analysis_wrong_sequence_number = EI_INIT;
|
|
|
|
|
|
|
|
|
2013-06-18 23:01:46 +00:00
|
|
|
static gint exported_pdu_tap = -1;
|
|
|
|
|
2001-11-26 04:52:51 +00:00
|
|
|
static dissector_handle_t data_handle;
|
|
|
|
|
2003-04-29 17:24:35 +00:00
|
|
|
static dissector_table_t ip_dissector_table;
|
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2006-03-27 16:25:35 +00:00
|
|
|
/* Encryption algorithms defined in RFC 4305 */
|
|
|
|
#define IPSEC_ENCRYPT_NULL 0
|
|
|
|
#define IPSEC_ENCRYPT_3DES_CBC 1
|
|
|
|
#define IPSEC_ENCRYPT_AES_CBC 2
|
|
|
|
#define IPSEC_ENCRYPT_AES_CTR 3
|
2006-08-09 02:00:05 +00:00
|
|
|
#define IPSEC_ENCRYPT_DES_CBC 4
|
2006-03-27 16:25:35 +00:00
|
|
|
#define IPSEC_ENCRYPT_BLOWFISH_CBC 5
|
|
|
|
#define IPSEC_ENCRYPT_TWOFISH_CBC 6
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2009-03-25 18:04:30 +00:00
|
|
|
/* Encryption algorithm defined in RFC 2144 */
|
|
|
|
#define IPSEC_ENCRYPT_CAST5_CBC 7
|
|
|
|
|
2013-02-25 22:19:15 +00:00
|
|
|
/* Encryption algorithm defined in RFC 4106 */
|
|
|
|
#define IPSEC_ENCRYPT_AES_GCM 8
|
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
/* Authentication algorithms defined in RFC 4305 */
|
|
|
|
#define IPSEC_AUTH_NULL 0
|
|
|
|
#define IPSEC_AUTH_HMAC_SHA1_96 1
|
2009-07-16 19:57:15 +00:00
|
|
|
#define IPSEC_AUTH_HMAC_SHA256_96 2
|
|
|
|
#define IPSEC_AUTH_HMAC_SHA256_128 3
|
2012-10-22 12:34:01 +00:00
|
|
|
#define IPSEC_AUTH_HMAC_SHA384_192 4
|
|
|
|
#define IPSEC_AUTH_HMAC_SHA512_256 5
|
|
|
|
#define IPSEC_AUTH_HMAC_MD5_96 6
|
|
|
|
#define IPSEC_AUTH_HMAC_RIPEMD160_96 7
|
2006-04-13 22:26:13 +00:00
|
|
|
/* define IPSEC_AUTH_AES_XCBC_MAC_96 6 */
|
2013-12-08 02:27:52 +00:00
|
|
|
#define IPSEC_AUTH_ANY_64BIT 8
|
|
|
|
#define IPSEC_AUTH_ANY_96BIT 9
|
|
|
|
#define IPSEC_AUTH_ANY_128BIT 10
|
|
|
|
#define IPSEC_AUTH_ANY_192BIT 11
|
|
|
|
#define IPSEC_AUTH_ANY_256BIT 12
|
1999-10-15 05:30:43 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
#define IPSEC_IPV6_ADDR_LEN 128
|
|
|
|
#define IPSEC_IPV4_ADDR_LEN 32
|
|
|
|
#define IPSEC_STRLEN_IPV6 32
|
|
|
|
#define IPSEC_STRLEN_IPV4 8
|
|
|
|
#define IPSEC_SA_IPV4 1
|
|
|
|
#define IPSEC_SA_IPV6 2
|
|
|
|
#define IPSEC_SA_UNKNOWN -1
|
|
|
|
#define IPSEC_SA_WILDCARDS_ANY '*'
|
2011-10-26 21:42:45 +00:00
|
|
|
/* the maximum number of bytes (10)(including the terminating nul character(11)) */
|
|
|
|
#define IPSEC_SPI_LEN_MAX 11
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2011-06-02 07:11:26 +00:00
|
|
|
/* well-known algorithm number (in CPI), from RFC2409 */
|
2014-04-30 17:25:12 +00:00
|
|
|
#define IPCOMP_OUI 1 /* vendor specific */
|
|
|
|
#define IPCOMP_DEFLATE 2 /* RFC2394 */
|
|
|
|
#define IPCOMP_LZS 3 /* RFC2395 */
|
|
|
|
#define IPCOMP_MAX 4
|
2011-06-02 07:11:26 +00:00
|
|
|
|
|
|
|
|
1999-10-15 05:30:43 +00:00
|
|
|
static const value_string cpi2val[] = {
|
2006-03-27 16:25:35 +00:00
|
|
|
{ IPCOMP_OUI, "OUI" },
|
|
|
|
{ IPCOMP_DEFLATE, "DEFLATE" },
|
|
|
|
{ IPCOMP_LZS, "LZS" },
|
|
|
|
{ 0, NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
struct newah {
|
2014-04-30 17:25:12 +00:00
|
|
|
guint8 ah_nxt; /* Next Header */
|
|
|
|
guint8 ah_len; /* Length of data + 1, in 32bit */
|
|
|
|
guint16 ah_reserve; /* Reserved for future use */
|
|
|
|
guint32 ah_spi; /* Security parameter index */
|
|
|
|
guint32 ah_seq; /* Sequence number field */
|
|
|
|
/* variable size, 32bit bound*/ /* Authentication data */
|
2006-03-27 16:25:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct newesp {
|
2014-04-30 17:25:12 +00:00
|
|
|
guint32 esp_spi; /* ESP */
|
|
|
|
guint32 esp_seq; /* Sequence number */
|
|
|
|
/*variable size*/ /* (IV and) Payload data */
|
|
|
|
/*variable size*/ /* padding */
|
|
|
|
/*8bit*/ /* pad size */
|
|
|
|
/*8bit*/ /* next header */
|
|
|
|
/*8bit*/ /* next header */
|
|
|
|
/*variable size, 32bit bound*/ /* Authentication data */
|
2006-03-27 16:25:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ipcomp {
|
2014-04-30 17:25:12 +00:00
|
|
|
guint8 comp_nxt; /* Next Header */
|
|
|
|
guint8 comp_flags; /* Must be zero */
|
|
|
|
guint16 comp_cpi; /* Compression parameter index */
|
1999-10-15 05:30:43 +00:00
|
|
|
};
|
|
|
|
|
2014-04-28 23:42:42 +00:00
|
|
|
struct ah_header_data {
|
|
|
|
proto_tree *next_tree;
|
|
|
|
guint8 nxt; /* Next Header */
|
|
|
|
};
|
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2011-06-02 07:11:26 +00:00
|
|
|
/*-------------------------------------
|
|
|
|
* UAT for ESP
|
|
|
|
*-------------------------------------
|
|
|
|
*/
|
|
|
|
/* UAT entry structure. */
|
|
|
|
typedef struct {
|
2014-04-30 17:25:12 +00:00
|
|
|
guint8 protocol;
|
|
|
|
gchar *srcIP;
|
|
|
|
gchar *dstIP;
|
|
|
|
gchar *spi;
|
|
|
|
|
|
|
|
guint8 encryption_algo;
|
|
|
|
gchar *encryption_key_string;
|
|
|
|
gchar *encryption_key;
|
|
|
|
gint encryption_key_length;
|
|
|
|
gboolean cipher_hd_created;
|
|
|
|
gcry_cipher_hd_t cipher_hd; /* Key is stored here and closed with the SA */
|
|
|
|
|
|
|
|
guint8 authentication_algo;
|
|
|
|
gchar *authentication_key_string;
|
|
|
|
gchar *authentication_key;
|
|
|
|
gint authentication_key_length;
|
2011-06-02 07:11:26 +00:00
|
|
|
} uat_esp_sa_record_t;
|
|
|
|
|
|
|
|
static uat_esp_sa_record_t *uat_esp_sa_records = NULL;
|
|
|
|
|
2014-05-12 21:30:14 +00:00
|
|
|
/* Extra SA records that may be set programmatically */
|
|
|
|
/* 'records' array is now allocated on the heap */
|
|
|
|
#define MAX_EXTRA_SA_RECORDS 16
|
2014-04-28 21:29:53 +00:00
|
|
|
typedef struct extra_esp_sa_records_t {
|
2014-04-30 17:25:12 +00:00
|
|
|
guint num_records;
|
2014-05-12 21:30:14 +00:00
|
|
|
uat_esp_sa_record_t *records;
|
2014-04-28 21:29:53 +00:00
|
|
|
} extra_esp_sa_records_t;
|
|
|
|
static extra_esp_sa_records_t extra_esp_sa_records;
|
|
|
|
|
2011-06-02 07:11:26 +00:00
|
|
|
static uat_t * esp_uat = NULL;
|
|
|
|
static guint num_sa_uat = 0;
|
|
|
|
|
2014-04-28 21:29:53 +00:00
|
|
|
/*
|
|
|
|
Name : static gint compute_ascii_key(gchar **ascii_key, gchar *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
|
|
|
|
*/
|
|
|
|
static gint
|
|
|
|
compute_ascii_key(gchar **ascii_key, const gchar *key)
|
|
|
|
{
|
|
|
|
guint key_len = 0;
|
|
|
|
gint hex_digit;
|
|
|
|
guchar key_byte;
|
|
|
|
guint i, j;
|
2011-06-02 07:11:26 +00:00
|
|
|
|
2014-04-28 21:29:53 +00:00
|
|
|
if(key != NULL)
|
|
|
|
{
|
|
|
|
if((strlen(key) > 2) && (key[0] == '0') && ((key[1] == 'x') || (key[1] == 'X')))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Key begins with "0x" or "0X"; skip that and treat the rest
|
|
|
|
* as a sequence of hex digits.
|
|
|
|
*/
|
2014-04-30 17:25:12 +00:00
|
|
|
i = 2; /* first character after "0[Xx]" */
|
2014-04-28 21:29:53 +00:00
|
|
|
j = 0;
|
|
|
|
if(strlen(key) %2 == 1)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Key has an odd number of characters; we act as if the
|
|
|
|
* first character had a 0 in front of it, making the
|
|
|
|
* number of characters even.
|
|
|
|
*/
|
|
|
|
key_len = ((guint) strlen(key) - 2) / 2 + 1;
|
|
|
|
*ascii_key = (gchar *) g_malloc ((key_len + 1)* sizeof(gchar));
|
|
|
|
hex_digit = g_ascii_xdigit_value(key[i]);
|
|
|
|
i++;
|
|
|
|
if (hex_digit == -1)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-04-28 21:29:53 +00:00
|
|
|
g_free(*ascii_key);
|
2014-04-30 17:25:12 +00:00
|
|
|
*ascii_key = NULL;
|
|
|
|
return -1; /* not a valid hex digit */
|
|
|
|
}
|
2014-04-28 21:29:53 +00:00
|
|
|
(*ascii_key)[j] = (guchar)hex_digit;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Key has an even number of characters, so we treat each
|
|
|
|
* pair of hex digits as a single byte value.
|
|
|
|
*/
|
|
|
|
key_len = ((guint) strlen(key) - 2) / 2;
|
|
|
|
*ascii_key = (gchar *) g_malloc ((key_len + 1)* sizeof(gchar));
|
|
|
|
}
|
2011-06-02 07:11:26 +00:00
|
|
|
|
2014-04-28 21:29:53 +00:00
|
|
|
while(i < (strlen(key) -1))
|
|
|
|
{
|
|
|
|
hex_digit = g_ascii_xdigit_value(key[i]);
|
|
|
|
i++;
|
|
|
|
if (hex_digit == -1)
|
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
g_free(*ascii_key);
|
|
|
|
*ascii_key = NULL;
|
|
|
|
return -1; /* not a valid hex digit */
|
|
|
|
}
|
2014-04-28 21:29:53 +00:00
|
|
|
key_byte = ((guchar)hex_digit) << 4;
|
|
|
|
hex_digit = g_ascii_xdigit_value(key[i]);
|
|
|
|
i++;
|
|
|
|
if (hex_digit == -1)
|
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
g_free(*ascii_key);
|
|
|
|
*ascii_key = NULL;
|
|
|
|
return -1; /* not a valid hex digit */
|
|
|
|
}
|
2014-04-28 21:29:53 +00:00
|
|
|
key_byte |= (guchar)hex_digit;
|
|
|
|
(*ascii_key)[j] = key_byte;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
(*ascii_key)[j] = '\0';
|
|
|
|
}
|
2011-06-02 07:11:26 +00:00
|
|
|
|
2014-04-28 21:29:53 +00:00
|
|
|
else if((strlen(key) == 2) && (key[0] == '0') && ((key[1] == 'x') || (key[1] == 'X')))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
key_len = (guint) strlen(key);
|
|
|
|
*ascii_key = g_strdup(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return key_len;
|
|
|
|
}
|
2011-10-27 19:20:39 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
static void uat_esp_sa_record_update_cb(void* r, char** err _U_) {
|
2014-04-30 17:25:12 +00:00
|
|
|
uat_esp_sa_record_t* rec = (uat_esp_sa_record_t *)r;
|
2011-06-02 07:11:26 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Compute keys & lengths once and for all */
|
|
|
|
if (rec->encryption_key_string) {
|
|
|
|
rec->encryption_key_length = compute_ascii_key(&rec->encryption_key, rec->encryption_key_string);
|
2014-05-12 21:30:14 +00:00
|
|
|
rec->cipher_hd_created = FALSE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rec->encryption_key_length = 0;
|
|
|
|
rec->encryption_key = NULL;
|
|
|
|
}
|
2011-06-02 07:11:26 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
if (rec->authentication_key_string) {
|
|
|
|
rec->authentication_key_length = compute_ascii_key(&rec->authentication_key, rec->authentication_key_string);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rec->authentication_key_length = 0;
|
|
|
|
rec->authentication_key = NULL;
|
|
|
|
}
|
2011-06-02 07:11:26 +00:00
|
|
|
}
|
2014-04-28 21:29:53 +00:00
|
|
|
|
|
|
|
static void* uat_esp_sa_record_copy_cb(void* n, const void* o, size_t siz _U_) {
|
2014-04-30 17:25:12 +00:00
|
|
|
uat_esp_sa_record_t* new_rec = (uat_esp_sa_record_t *)n;
|
|
|
|
const uat_esp_sa_record_t* old_rec = (const uat_esp_sa_record_t *)o;
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Copy UAT fields */
|
|
|
|
new_rec->srcIP = (old_rec->srcIP) ? g_strdup(old_rec->srcIP) : NULL;
|
|
|
|
new_rec->dstIP = (old_rec->dstIP) ? g_strdup(old_rec->dstIP) : NULL;
|
|
|
|
new_rec->spi = (old_rec->spi) ? g_strdup(old_rec->spi) : NULL;
|
|
|
|
new_rec->encryption_key_string = (old_rec->encryption_key_string) ? g_strdup(old_rec->encryption_key_string) : NULL;
|
|
|
|
new_rec->authentication_key_string = (old_rec->authentication_key_string) ? g_strdup(old_rec->authentication_key_string) : NULL;
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Parse keys as in an update */
|
|
|
|
uat_esp_sa_record_update_cb(new_rec, NULL);
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
return new_rec;
|
2014-04-28 21:29:53 +00:00
|
|
|
}
|
|
|
|
|
2011-06-02 07:11:26 +00:00
|
|
|
static void uat_esp_sa_record_free_cb(void*r) {
|
2014-04-30 17:25:12 +00:00
|
|
|
uat_esp_sa_record_t* rec = (uat_esp_sa_record_t*)r;
|
|
|
|
|
|
|
|
g_free(rec->srcIP);
|
|
|
|
g_free(rec->dstIP);
|
|
|
|
g_free(rec->spi);
|
|
|
|
g_free(rec->encryption_key_string);
|
|
|
|
g_free(rec->encryption_key);
|
|
|
|
g_free(rec->authentication_key_string);
|
|
|
|
g_free(rec->authentication_key);
|
|
|
|
|
|
|
|
if (rec->cipher_hd_created) {
|
|
|
|
gcry_cipher_close(rec->cipher_hd);
|
|
|
|
rec->cipher_hd_created = FALSE;
|
|
|
|
}
|
2011-06-02 07:11:26 +00:00
|
|
|
}
|
|
|
|
|
2013-03-12 06:40:13 +00:00
|
|
|
UAT_VS_DEF(uat_esp_sa_records, protocol, uat_esp_sa_record_t, guint8, IPSEC_SA_IPV4, "IPv4")
|
2011-06-02 07:11:26 +00:00
|
|
|
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)
|
2013-03-12 06:40:13 +00:00
|
|
|
UAT_VS_DEF(uat_esp_sa_records, encryption_algo, uat_esp_sa_record_t, guint8, 0, "FIXX")
|
2014-04-28 21:29:53 +00:00
|
|
|
UAT_CSTRING_CB_DEF(uat_esp_sa_records, encryption_key_string, uat_esp_sa_record_t)
|
2013-03-12 06:40:13 +00:00
|
|
|
UAT_VS_DEF(uat_esp_sa_records, authentication_algo, uat_esp_sa_record_t, guint8, 0, "FIXX")
|
2014-04-28 21:29:53 +00:00
|
|
|
UAT_CSTRING_CB_DEF(uat_esp_sa_records, authentication_key_string, uat_esp_sa_record_t)
|
|
|
|
|
|
|
|
|
|
|
|
/* Configure a new SA (programmatically, most likely from a private dissector).
|
|
|
|
The arugments here are deliberately in the same string formats as the UAT fields
|
|
|
|
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, const gchar *encryption_key,
|
|
|
|
guint8 authentication_algo, const gchar *authentication_key)
|
|
|
|
{
|
|
|
|
uat_esp_sa_record_t* record = NULL;
|
2014-05-12 21:30:14 +00:00
|
|
|
if (extra_esp_sa_records.num_records == 0) {
|
2014-05-13 05:10:01 +00:00
|
|
|
extra_esp_sa_records.records = (uat_esp_sa_record_t *)g_malloc(sizeof(uat_esp_sa_record_t)*MAX_EXTRA_SA_RECORDS);
|
2014-05-12 21:30:14 +00:00
|
|
|
}
|
2014-04-28 21:29:53 +00:00
|
|
|
if (extra_esp_sa_records.num_records < MAX_EXTRA_SA_RECORDS) {
|
|
|
|
record = &extra_esp_sa_records.records[extra_esp_sa_records.num_records++];
|
|
|
|
}
|
|
|
|
else {
|
2014-05-12 21:30:14 +00:00
|
|
|
/* No room left!! */
|
|
|
|
fprintf(stderr, "<IPsec/ESP Dissector> Failed to add UE as already have max (%u) configured\n",
|
|
|
|
MAX_EXTRA_SA_RECORDS);
|
2014-04-28 21:29:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy key fields */
|
|
|
|
record->protocol = protocol;
|
|
|
|
record->srcIP = g_strdup(srcIP);
|
|
|
|
record->dstIP = g_strdup(dstIP);
|
|
|
|
record->spi = g_strdup(spi);
|
|
|
|
|
|
|
|
/* Encryption */
|
|
|
|
record->encryption_algo = encryption_algo;
|
|
|
|
record->encryption_key_string = g_strdup(encryption_key);
|
|
|
|
|
|
|
|
/* Authentication */
|
|
|
|
record->authentication_algo = authentication_algo;
|
|
|
|
if (authentication_key) {
|
|
|
|
record->authentication_key_string = g_strdup(authentication_key);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
record->authentication_key_string = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse keys */
|
|
|
|
uat_esp_sa_record_update_cb(record, NULL);
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-09-12 13:56:29 +00:00
|
|
|
/*************************************/
|
|
|
|
/* Preference settings */
|
|
|
|
|
|
|
|
/* Default ESP payload decode to off */
|
|
|
|
static gboolean g_esp_enable_encryption_decode = FALSE;
|
|
|
|
|
|
|
|
/* Default ESP payload Authentication Checking to off */
|
|
|
|
static gboolean g_esp_enable_authentication_check = FALSE;
|
|
|
|
#endif
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
/**************************************************/
|
|
|
|
/* Sequence number analysis */
|
|
|
|
|
|
|
|
/* SPI state, key is just 32-bit SPI */
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
guint32 previousSequenceNumber;
|
|
|
|
guint32 previousFrameNum;
|
|
|
|
} spi_status;
|
|
|
|
|
|
|
|
/* The sequence analysis SPI hash table.
|
|
|
|
Maps SPI -> spi_status */
|
|
|
|
static GHashTable *esp_sequence_analysis_hash = NULL;
|
|
|
|
|
|
|
|
/* Equal keys */
|
|
|
|
static gint word_equal(gconstpointer v, gconstpointer v2)
|
|
|
|
{
|
|
|
|
/* Key fits in 4 bytes, so just compare pointers! */
|
|
|
|
return (v == v2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute a hash value for a given key. */
|
|
|
|
static guint word_hash_func(gconstpointer v)
|
|
|
|
{
|
|
|
|
/* Just use pointer, as the fields are all in this value */
|
|
|
|
return GPOINTER_TO_UINT(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Results are stored here: framenum -> spi_status */
|
2014-09-11 16:27:08 +00:00
|
|
|
/* 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 */
|
2014-09-09 22:26:31 +00:00
|
|
|
static GHashTable *esp_sequence_analysis_report_hash = NULL;
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
/* Do the table lookup */
|
|
|
|
spi_status *status = (spi_status*)g_hash_table_lookup(esp_sequence_analysis_hash,
|
|
|
|
GUINT_TO_POINTER((guint)spi));
|
|
|
|
if (status == NULL) {
|
|
|
|
/* Create an entry for this SPI */
|
|
|
|
status = wmem_new0(wmem_file_scope(), spi_status);
|
|
|
|
status->previousSequenceNumber = sequence_number;
|
|
|
|
status->previousFrameNum = pinfo->fd->num;
|
|
|
|
|
|
|
|
/* And add it to the table */
|
|
|
|
g_hash_table_insert(esp_sequence_analysis_hash, GUINT_TO_POINTER((guint)spi), status);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
spi_status *frame_status;
|
|
|
|
|
|
|
|
/* Entry already existed, so check that we got the sequence number we expected. */
|
|
|
|
if (sequence_number != status->previousSequenceNumber+1) {
|
|
|
|
/* Create report entry */
|
|
|
|
frame_status = wmem_new0(wmem_file_scope(), spi_status);
|
|
|
|
/* Copy what was expected */
|
|
|
|
*frame_status = *status;
|
|
|
|
/* And add it into the report table */
|
|
|
|
g_hash_table_insert(esp_sequence_analysis_report_hash, GUINT_TO_POINTER(pinfo->fd->num), frame_status);
|
|
|
|
}
|
|
|
|
/* Adopt this setting as 'current' regardless of whether expected */
|
|
|
|
status->previousSequenceNumber = sequence_number;
|
|
|
|
status->previousFrameNum = pinfo->fd->num;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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,
|
|
|
|
tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
|
|
|
|
{
|
|
|
|
/* Look up this frame in the report table. */
|
|
|
|
spi_status *status = (spi_status*)g_hash_table_lookup(esp_sequence_analysis_report_hash,
|
|
|
|
GUINT_TO_POINTER(pinfo->fd->num));
|
|
|
|
if (status != NULL) {
|
|
|
|
proto_item *sn_ti, *frame_ti;
|
|
|
|
|
|
|
|
/* Expected sequence number */
|
|
|
|
sn_ti = proto_tree_add_uint(tree, hf_esp_sequence_analysis_expected_sn,
|
|
|
|
tvb, 0, 0, status->previousSequenceNumber+1);
|
|
|
|
if (sequence_number > (status->previousSequenceNumber+1)) {
|
|
|
|
proto_item_append_text(sn_ti, " (%u SNs missing)",
|
|
|
|
sequence_number - (status->previousSequenceNumber+1));
|
|
|
|
}
|
|
|
|
PROTO_ITEM_SET_GENERATED(sn_ti);
|
|
|
|
|
|
|
|
/* Link back to previous frame for SPI */
|
|
|
|
frame_ti = proto_tree_add_uint(tree, hf_esp_sequence_analysis_previous_frame,
|
|
|
|
tvb, 0, 0, status->previousFrameNum);
|
|
|
|
PROTO_ITEM_SET_GENERATED(frame_ti);
|
|
|
|
|
|
|
|
/* Expert info */
|
|
|
|
if (sequence_number == status->previousSequenceNumber) {
|
|
|
|
expert_add_info_format(pinfo, sn_ti, &ei_esp_sequence_analysis_wrong_sequence_number,
|
|
|
|
"Wrong Sequence Number for SPI %08x - %u repeated",
|
|
|
|
spi, sequence_number);
|
|
|
|
}
|
|
|
|
else if (sequence_number > status->previousSequenceNumber+1) {
|
|
|
|
expert_add_info_format(pinfo, sn_ti, &ei_esp_sequence_analysis_wrong_sequence_number,
|
|
|
|
"Wrong Sequence Number for SPI %08x - %u missing",
|
|
|
|
spi,
|
|
|
|
sequence_number - (status->previousSequenceNumber+1));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
expert_add_info_format(pinfo, sn_ti, &ei_esp_sequence_analysis_wrong_sequence_number,
|
|
|
|
"Wrong Sequence Number for SPI %08x - %u less than expected",
|
|
|
|
spi,
|
|
|
|
(status->previousSequenceNumber+1) - sequence_number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
/*
|
|
|
|
Default ESP payload heuristic decode to off
|
|
|
|
(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).
|
|
|
|
*/
|
2006-03-27 16:25:35 +00:00
|
|
|
static gboolean g_esp_enable_null_encryption_decode_heuristic = FALSE;
|
|
|
|
|
2014-09-11 16:27:08 +00:00
|
|
|
/* Default to doing ESP sequence analysis */
|
2014-09-09 22:26:31 +00:00
|
|
|
static gboolean g_esp_do_sequence_analysis = TRUE;
|
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
/* Place AH payload in sub tree */
|
|
|
|
static gboolean g_ah_payload_in_subtree = FALSE;
|
|
|
|
|
1999-03-29 02:21:34 +00:00
|
|
|
#ifndef offsetof
|
2014-04-30 17:25:12 +00:00
|
|
|
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
1999-03-29 02:21:34 +00:00
|
|
|
#endif
|
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2011-06-02 07:11:26 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2011-06-02 07:46:08 +00:00
|
|
|
#if 0
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
/*
|
2006-03-27 16:25:35 +00:00
|
|
|
Name : static int get_ipv6_suffix(char* ipv6_suffix, char *ipv6_address)
|
|
|
|
Description : Get the extended IPv6 Suffix of an IPv6 Address
|
|
|
|
Return : Return the number of char of the IPv6 address suffix parsed
|
2006-08-09 02:00:05 +00:00
|
|
|
Params:
|
|
|
|
- char *ipv6_address : the valid ipv6 address to parse in char *
|
2006-03-27 16:25:35 +00:00
|
|
|
- char *ipv6_suffix : the ipv6 suffix associated in char *
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
ex: if IPv6 address is "3ffe::1" the IPv6 suffix will be "0001" and the function will return 3
|
|
|
|
*/
|
|
|
|
static int get_ipv6_suffix(char* ipv6_suffix, char *ipv6_address)
|
2001-02-28 06:37:29 +00:00
|
|
|
{
|
2006-03-27 16:25:35 +00:00
|
|
|
char suffix[IPSEC_STRLEN_IPV6 + 1];
|
|
|
|
int cpt = 0;
|
|
|
|
int cpt_suffix = 0;
|
|
|
|
int cpt_seg = 0;
|
|
|
|
int j =0;
|
|
|
|
int ipv6_len = 0;
|
|
|
|
gboolean found = FALSE;
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2009-12-21 21:06:01 +00:00
|
|
|
ipv6_len = (int) strlen(ipv6_address);
|
2006-08-09 02:00:05 +00:00
|
|
|
if(ipv6_len == 0)
|
2006-03-27 16:25:35 +00:00
|
|
|
{
|
|
|
|
/* Found a suffix */
|
2006-08-09 02:00:05 +00:00
|
|
|
found = TRUE;
|
2006-03-27 16:25:35 +00:00
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
else
|
|
|
|
{
|
2006-03-27 16:25:35 +00:00
|
|
|
while ( (cpt_suffix < IPSEC_STRLEN_IPV6) && (ipv6_len - cpt -1 >= 0) && (found == FALSE))
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
|
|
|
if(ipv6_address[ipv6_len - cpt - 1] == ':')
|
|
|
|
{
|
|
|
|
/* Add some 0 to the prefix; */
|
|
|
|
for(j = cpt_seg; j < 4; j++)
|
|
|
|
{
|
|
|
|
suffix[IPSEC_STRLEN_IPV6 -1 -cpt_suffix] = '0';
|
|
|
|
cpt_suffix ++;
|
|
|
|
}
|
|
|
|
cpt_seg = 0;
|
|
|
|
|
|
|
|
if(ipv6_len - cpt - 1 == 0)
|
|
|
|
{
|
|
|
|
/* Found a suffix */
|
|
|
|
found = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(ipv6_address[ipv6_len - cpt - 2] == ':')
|
|
|
|
{
|
|
|
|
/* found a suffix */
|
|
|
|
cpt +=2;
|
|
|
|
found = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cpt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-10-20 08:48:56 +00:00
|
|
|
suffix[IPSEC_STRLEN_IPV6 -1 -cpt_suffix] = g_ascii_toupper(ipv6_address[ipv6_len - cpt - 1]);
|
2014-04-30 17:25:12 +00:00
|
|
|
cpt_seg ++;
|
|
|
|
cpt_suffix ++;
|
|
|
|
cpt++;
|
|
|
|
}
|
|
|
|
}
|
2001-02-28 06:37:29 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
if(cpt_suffix % 4 != 0)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
|
|
|
for(j = cpt_seg; j < 4; j++)
|
|
|
|
{
|
|
|
|
suffix[IPSEC_STRLEN_IPV6 -1 -cpt_suffix] = '0';
|
|
|
|
cpt_suffix ++;
|
|
|
|
}
|
|
|
|
cpt_seg = 0;
|
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
for(j = 0 ; j < cpt_suffix ; j ++)
|
2006-08-09 02:00:05 +00:00
|
|
|
{
|
2006-03-27 16:25:35 +00:00
|
|
|
suffix[j] = suffix[j + IPSEC_STRLEN_IPV6 - cpt_suffix] ;
|
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
|
|
|
suffix[j] = '\0';
|
2006-03-27 16:25:35 +00:00
|
|
|
memcpy(ipv6_suffix,suffix,j + 1);
|
|
|
|
return cpt;
|
|
|
|
}
|
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
/*
|
2006-03-27 16:25:35 +00:00
|
|
|
Name : static int get_full_ipv6_addr(char* ipv6_addr_expanded, char *ipv6_addr)
|
|
|
|
Description : Get the extended IPv6 Address of an IPv6 Address
|
|
|
|
Return : Return the remaining number of char of the IPv6 address parsed
|
2006-08-09 02:00:05 +00:00
|
|
|
Params:
|
|
|
|
- char *ipv6_addr : the valid ipv6 address to parse in char *
|
2006-03-27 16:25:35 +00:00
|
|
|
- char *ipv6_addr_expansed : the expanded ipv6 address associated in char *
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2009-12-21 21:06:01 +00:00
|
|
|
ex: if IPv6 address is "3ffe::1" the IPv6 expanded address
|
2009-08-26 19:30:44 +00:00
|
|
|
will be "3FFE0000000000000000000000000001" and the function will return 0
|
2009-12-21 21:06:01 +00:00
|
|
|
if IPV6 address is "3ffe::*" the IPv6 expanded address
|
2009-08-26 19:30:44 +00:00
|
|
|
will be "3FFE000000000000000000000000****" and the function will return 0
|
2006-03-27 16:25:35 +00:00
|
|
|
*/
|
2006-08-09 02:00:05 +00:00
|
|
|
static int
|
2006-03-27 16:25:35 +00:00
|
|
|
get_full_ipv6_addr(char* ipv6_addr_expanded, char *ipv6_addr)
|
|
|
|
{
|
|
|
|
char suffix[IPSEC_STRLEN_IPV6 + 1];
|
|
|
|
char prefix[IPSEC_STRLEN_IPV6 + 1];
|
2006-08-09 02:00:05 +00:00
|
|
|
char *prefix_addr;
|
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
int suffix_cpt = 0;
|
|
|
|
int suffix_len = 0;
|
|
|
|
int prefix_remaining = 0;
|
|
|
|
int prefix_len = 0;
|
|
|
|
int j = 0;
|
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
if((ipv6_addr == NULL) || (strcmp(ipv6_addr, "") == 0)) return -1;
|
|
|
|
if((strlen(ipv6_addr) == 1) && (ipv6_addr[0] == IPSEC_SA_WILDCARDS_ANY))
|
|
|
|
{
|
|
|
|
for(j = 0; j <= IPSEC_STRLEN_IPV6; j++)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
|
|
|
ipv6_addr_expanded[j] = IPSEC_SA_WILDCARDS_ANY;
|
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
ipv6_addr_expanded[IPSEC_STRLEN_IPV6] = '\0';
|
|
|
|
return 0;
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
suffix_cpt = get_ipv6_suffix(suffix,ipv6_addr);
|
2009-12-21 21:06:01 +00:00
|
|
|
suffix_len = (int) strlen(suffix);
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
if(suffix_len < IPSEC_STRLEN_IPV6)
|
|
|
|
{
|
2015-01-11 00:04:06 +00:00
|
|
|
prefix_addr = wmem_strndup(wmem_packet_scope(), ipv6_addr,strlen(ipv6_addr) - suffix_cpt);
|
2006-03-27 16:25:35 +00:00
|
|
|
prefix_remaining = get_ipv6_suffix(prefix,prefix_addr);
|
2009-12-21 21:06:01 +00:00
|
|
|
prefix_len = (int) strlen(prefix);
|
2006-03-27 16:25:35 +00:00
|
|
|
memcpy(ipv6_addr_expanded,prefix,prefix_len);
|
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
for(j = 0; j <= IPSEC_STRLEN_IPV6 - prefix_len - suffix_len; j++)
|
|
|
|
{
|
|
|
|
ipv6_addr_expanded[j + prefix_len] = '0';
|
2001-02-28 06:37:29 +00:00
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
memcpy(ipv6_addr_expanded + IPSEC_STRLEN_IPV6 - suffix_len, suffix,suffix_len + 1);
|
|
|
|
|
|
|
|
if(suffix_len < IPSEC_STRLEN_IPV6)
|
2006-08-09 02:00:05 +00:00
|
|
|
return (prefix_len - prefix_remaining);
|
|
|
|
else
|
2009-12-21 21:06:01 +00:00
|
|
|
return (int) strlen(ipv6_addr) - suffix_cpt;
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
/*
|
2006-03-27 16:25:35 +00:00
|
|
|
Name : static gboolean get_full_ipv4_addr(char* ipv4_addr_expanded, char *ipv4_addr)
|
|
|
|
Description : Get the extended IPv4 Address of an IPv4 Address
|
2009-12-21 21:06:01 +00:00
|
|
|
Return : Return true if it can derive an IPv4 address. It does not mean that
|
2009-08-26 19:30:44 +00:00
|
|
|
the previous one was valid.
|
2006-08-09 02:00:05 +00:00
|
|
|
Params:
|
|
|
|
- char *ipv4_addr : the valid ipv4 address to parse in char *
|
2006-03-27 16:25:35 +00:00
|
|
|
- char *ipv4_addr_expansed : the expanded ipv4 address associated in char *
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2009-08-26 19:30:44 +00:00
|
|
|
ex: if IPv4 address is "190.*.*.1" the IPv4 expanded address will be "BE****01" and
|
|
|
|
the function will return 0
|
2009-12-21 21:06:01 +00:00
|
|
|
if IPv4 address is "*" the IPv4 expanded address will be "********" and
|
2009-08-26 19:30:44 +00:00
|
|
|
the function will return 0
|
2006-03-27 16:25:35 +00:00
|
|
|
*/
|
2006-08-09 02:00:05 +00:00
|
|
|
static gboolean
|
2010-01-18 21:49:47 +00:00
|
|
|
get_full_ipv4_addr(char* ipv4_address_expanded, char *ipv4_address)
|
2000-06-05 03:21:03 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
char addr_byte_string_tmp[4];
|
|
|
|
char addr_byte_string[4];
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
guint addr_byte = 0;
|
|
|
|
guint i = 0;
|
|
|
|
guint j = 0;
|
|
|
|
guint k = 0;
|
|
|
|
guint cpt = 0;
|
|
|
|
gboolean done_flag = FALSE;
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
if((ipv4_address == NULL) || (strcmp(ipv4_address, "") == 0)) return done_flag;
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
if((strlen(ipv4_address) == 1) && (ipv4_address[0] == IPSEC_SA_WILDCARDS_ANY))
|
|
|
|
{
|
|
|
|
for(i = 0; i <= IPSEC_STRLEN_IPV4; i++)
|
2006-03-27 16:25:35 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
ipv4_address_expanded[i] = IPSEC_SA_WILDCARDS_ANY;
|
|
|
|
}
|
|
|
|
ipv4_address_expanded[IPSEC_STRLEN_IPV4] = '\0';
|
|
|
|
done_flag = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
j = 0;
|
|
|
|
cpt = 0;
|
|
|
|
k = 0;
|
|
|
|
while((done_flag == FALSE) && (j <= strlen(ipv4_address)) && (cpt < IPSEC_STRLEN_IPV4))
|
|
|
|
{
|
|
|
|
if(j == strlen(ipv4_address))
|
|
|
|
{
|
|
|
|
addr_byte_string_tmp[k] = '\0';
|
|
|
|
if((strlen(addr_byte_string_tmp) == 1) && (addr_byte_string_tmp[0] == IPSEC_SA_WILDCARDS_ANY))
|
|
|
|
{
|
|
|
|
for(i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
ipv4_address_expanded[cpt] = IPSEC_SA_WILDCARDS_ANY;
|
|
|
|
cpt ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2011-10-27 15:38:32 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
sscanf(addr_byte_string_tmp,"%u",&addr_byte);
|
|
|
|
if(addr_byte < 16) g_snprintf(addr_byte_string,4,"0%X",addr_byte);
|
|
|
|
else g_snprintf(addr_byte_string,4,"%X",addr_byte);
|
|
|
|
for(i = 0; i < strlen(addr_byte_string); i++)
|
|
|
|
{
|
|
|
|
ipv4_address_expanded[cpt] = addr_byte_string[i];
|
|
|
|
cpt ++;
|
|
|
|
}
|
2011-10-27 15:38:32 +00:00
|
|
|
}
|
|
|
|
done_flag = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
else if(ipv4_address[j] == '.')
|
|
|
|
{
|
|
|
|
addr_byte_string_tmp[k] = '\0';
|
|
|
|
if((strlen(addr_byte_string_tmp) == 1) && (addr_byte_string_tmp[0] == IPSEC_SA_WILDCARDS_ANY))
|
|
|
|
{
|
|
|
|
for(i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
ipv4_address_expanded[cpt] = IPSEC_SA_WILDCARDS_ANY;
|
|
|
|
cpt ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sscanf(addr_byte_string_tmp,"%u",&addr_byte);
|
|
|
|
if(addr_byte < 16) g_snprintf(addr_byte_string,4,"0%X",addr_byte);
|
|
|
|
else g_snprintf(addr_byte_string,4,"%X",addr_byte);
|
|
|
|
for(i = 0; i < strlen(addr_byte_string); i++)
|
|
|
|
{
|
|
|
|
ipv4_address_expanded[cpt] = addr_byte_string[i];
|
|
|
|
cpt ++;
|
|
|
|
}
|
|
|
|
}
|
2011-10-27 15:38:32 +00:00
|
|
|
k = 0;
|
2014-04-30 17:25:12 +00:00
|
|
|
j++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(k >= 3)
|
2011-10-27 15:38:32 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Incorrect IPv4 Address. Erase previous Values in the Byte. (LRU mechanism) */
|
|
|
|
addr_byte_string_tmp[0] = ipv4_address[j];
|
|
|
|
k = 1;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
addr_byte_string_tmp[k] = ipv4_address[j];
|
|
|
|
k++;
|
|
|
|
j++;
|
2011-10-27 15:38:32 +00:00
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2011-10-27 15:38:32 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
ipv4_address_expanded[cpt] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
return done_flag;
|
2006-03-27 16:25:35 +00:00
|
|
|
}
|
2011-06-02 07:46:08 +00:00
|
|
|
#endif
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
/*
|
2010-01-18 21:49:47 +00:00
|
|
|
Name : static goolean filter_address_match(gchar *addr, gchar *filter, gint len, gint typ)
|
2006-08-09 02:00:05 +00:00
|
|
|
Description : check the matching of an address with a filter
|
|
|
|
Return : Return TRUE if the filter and the address match
|
|
|
|
Params:
|
2010-01-18 21:49:47 +00:00
|
|
|
- gchar *addr : the address to check
|
2006-03-27 16:25:35 +00:00
|
|
|
- gchar *filter : the filter
|
|
|
|
- gint typ : the Address type : either IPv6 or IPv4 (IPSEC_SA_IPV6, IPSEC_SA_IPV4)
|
|
|
|
*/
|
2006-08-09 02:00:05 +00:00
|
|
|
static gboolean
|
2011-06-02 07:11:26 +00:00
|
|
|
filter_address_match(gchar *addr, gchar *filter, gint typ)
|
2006-03-27 16:25:35 +00:00
|
|
|
{
|
2011-06-02 07:11:26 +00:00
|
|
|
guint i;
|
2006-03-27 16:25:35 +00:00
|
|
|
guint filter_tmp = 0;
|
|
|
|
guint addr_tmp = 0;
|
|
|
|
char filter_string_tmp[3];
|
|
|
|
char addr_string_tmp[3];
|
2014-04-28 21:29:53 +00:00
|
|
|
guint addr_len;
|
2011-06-02 07:11:26 +00:00
|
|
|
guint filter_len = (guint)strlen(filter);
|
|
|
|
|
2014-04-28 21:29:53 +00:00
|
|
|
if((filter_len == 1) && (filter[0] == IPSEC_SA_WILDCARDS_ANY))
|
2012-10-16 14:31:14 +00:00
|
|
|
return TRUE;
|
2014-04-28 21:29:53 +00:00
|
|
|
|
|
|
|
addr_len = (guint)strlen(addr);
|
|
|
|
if(addr_len != filter_len)
|
2014-04-30 17:25:12 +00:00
|
|
|
return FALSE;
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
/* No length specified */
|
2014-04-28 21:29:53 +00:00
|
|
|
if( ((typ == IPSEC_SA_IPV6) && (filter_len > IPSEC_IPV6_ADDR_LEN)) ||
|
|
|
|
((typ == IPSEC_SA_IPV4) && (filter_len > IPSEC_IPV4_ADDR_LEN)))
|
2011-06-02 07:11:26 +00:00
|
|
|
{
|
2014-04-28 21:29:53 +00:00
|
|
|
/* Filter is longer than address can be... */
|
2011-06-02 07:11:26 +00:00
|
|
|
for(i = 0; i < addr_len; i++)
|
|
|
|
{
|
2011-10-21 02:10:19 +00:00
|
|
|
if((filter[i] != IPSEC_SA_WILDCARDS_ANY) && (filter[i] != addr[i]))
|
2011-06-02 07:11:26 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
return TRUE;
|
2011-06-02 07:11:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for(i = 0; i < (filter_len/4); i++)
|
|
|
|
{
|
2011-10-21 02:10:19 +00:00
|
|
|
if((filter[i] != IPSEC_SA_WILDCARDS_ANY) && (filter[i] != addr[i]))
|
2011-06-02 07:11:26 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-10-21 02:10:19 +00:00
|
|
|
if(filter[i] == IPSEC_SA_WILDCARDS_ANY)
|
2011-06-02 07:11:26 +00:00
|
|
|
return TRUE;
|
|
|
|
else if (filter_len % 4 != 0)
|
|
|
|
{
|
|
|
|
/* take the end of the Netmask/Prefixlen into account */
|
|
|
|
filter_string_tmp[0] = filter[i];
|
|
|
|
filter_string_tmp[1] = '\0';
|
|
|
|
addr_string_tmp[0] = addr[i];
|
|
|
|
addr_string_tmp[1] = '\0';
|
|
|
|
|
|
|
|
sscanf(filter_string_tmp,"%x",&filter_tmp);
|
|
|
|
sscanf(addr_string_tmp,"%x",&addr_tmp);
|
|
|
|
for(i = 0; i < (filter_len % 4); i++)
|
|
|
|
{
|
|
|
|
if(((filter_tmp >> (4 -i -1)) & 1) != ((addr_tmp >> (4 -i -1)) & 1))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
return TRUE;
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
/*
|
2006-03-27 16:25:35 +00:00
|
|
|
Name : static goolean filter_spi_match(gchar *spi, gchar *filter)
|
2006-08-09 02:00:05 +00:00
|
|
|
Description : check the matching of a spi with a filter
|
2014-04-28 21:29:53 +00:00
|
|
|
Return : Return TRUE if the filter matches the spi.
|
2006-08-09 02:00:05 +00:00
|
|
|
Params:
|
2006-03-27 16:25:35 +00:00
|
|
|
- gchar *spi : the spi to check
|
|
|
|
- gchar *filter : the filter
|
|
|
|
*/
|
2006-08-09 02:00:05 +00:00
|
|
|
static gboolean
|
2006-03-27 16:25:35 +00:00
|
|
|
filter_spi_match(gchar *spi, gchar *filter)
|
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
guint i;
|
|
|
|
guint filter_len = (guint)strlen(filter);
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* "*" matches against anything */
|
|
|
|
if((filter_len == 1) && (filter[0] == IPSEC_SA_WILDCARDS_ANY))
|
|
|
|
return TRUE;
|
|
|
|
/* Otherwise lengths need to match exactly... */
|
|
|
|
else if(strlen(spi) != filter_len)
|
|
|
|
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[i]))
|
2011-06-02 07:11:26 +00:00
|
|
|
return FALSE;
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
return TRUE;
|
2006-03-27 16:25:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
/*
|
2006-03-27 16:25:35 +00:00
|
|
|
Name : static goolean get_esp_sa(g_esp_sa_database *sad, gint protocol_typ, gchar *src, gchar *dst, gint spi,
|
2014-04-30 17:25:12 +00:00
|
|
|
gint *encryption_algo,
|
|
|
|
gint *authentication_algo,
|
|
|
|
gchar **encryption_key,
|
|
|
|
guint *encryption_key_len,
|
|
|
|
gchar **authentication_key,
|
2014-05-12 21:30:14 +00:00
|
|
|
guint *authentication_key_len,
|
|
|
|
gcry_cipher_hd_t **cipher_hd,
|
|
|
|
gboolean **cipher_hd_created
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
Description : Give Encryption Algo, Key and Authentification 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.
|
2006-08-09 02:00:05 +00:00
|
|
|
Params:
|
|
|
|
- g_esp_sa_database *sad : the Security Association Database
|
2006-03-27 16:25:35 +00:00
|
|
|
- gint *pt_protocol_typ : the protocol type
|
2006-08-09 02:00:05 +00:00
|
|
|
- gchar *src : the source address
|
|
|
|
- gchar *dst : the destination address
|
2006-03-27 16:25:35 +00:00
|
|
|
- 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
|
2006-09-08 07:32:13 +00:00
|
|
|
- gchar **encryption_key : the Encryption Key to apply to the packet
|
2007-04-13 05:44:57 +00:00
|
|
|
- guint *encryption_key_len : the Encryption Key length to apply to the packet
|
2006-09-08 07:32:13 +00:00
|
|
|
- gchar **authentication_key : the Authentication Key to apply to the packet
|
|
|
|
- guint *authentication_key_len : the Authentication Key len to apply to the packet
|
2014-05-12 21:30:14 +00:00
|
|
|
- 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.
|
2006-09-08 07:32:13 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
*/
|
|
|
|
static gboolean
|
2011-06-02 07:11:26 +00:00
|
|
|
get_esp_sa(gint protocol_typ, gchar *src, gchar *dst, gint spi,
|
2014-04-30 17:25:12 +00:00
|
|
|
gint *encryption_algo,
|
|
|
|
gint *authentication_algo,
|
|
|
|
gchar **encryption_key,
|
|
|
|
guint *encryption_key_len,
|
|
|
|
gchar **authentication_key,
|
|
|
|
guint *authentication_key_len,
|
|
|
|
gcry_cipher_hd_t **cipher_hd,
|
|
|
|
gboolean **cipher_hd_created
|
|
|
|
)
|
2006-08-09 02:00:05 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
gboolean found = FALSE;
|
|
|
|
guint i, j;
|
|
|
|
gchar spi_string[IPSEC_SPI_LEN_MAX];
|
2011-06-02 07:11:26 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
g_snprintf(spi_string, IPSEC_SPI_LEN_MAX,"0x%08x", spi);
|
2011-06-02 07:11:26 +00:00
|
|
|
|
2014-08-02 14:45:28 +00:00
|
|
|
*cipher_hd = NULL;
|
|
|
|
*cipher_hd_created = NULL;
|
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Check each known SA in turn */
|
|
|
|
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;
|
|
|
|
if (j < extra_esp_sa_records.num_records) {
|
|
|
|
/* Extra ones checked first */
|
|
|
|
record = &extra_esp_sa_records.records[j++];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Then UAT ones */
|
|
|
|
record = &uat_esp_sa_records[i++];
|
|
|
|
}
|
|
|
|
|
|
|
|
if((protocol_typ == record->protocol)
|
|
|
|
&& filter_address_match(src, record->srcIP, protocol_typ)
|
|
|
|
&& filter_address_match(dst, record->dstIP, protocol_typ)
|
|
|
|
&& filter_spi_match(spi_string, record->spi))
|
|
|
|
{
|
|
|
|
found = TRUE;
|
|
|
|
|
|
|
|
*encryption_algo = record->encryption_algo;
|
|
|
|
*authentication_algo = record->authentication_algo;
|
|
|
|
*authentication_key = record->authentication_key;
|
|
|
|
if (record->authentication_key_length == -1)
|
|
|
|
{
|
|
|
|
/* Bad key; XXX - report this */
|
|
|
|
*authentication_key_len = 0;
|
|
|
|
found = FALSE;
|
2014-04-28 21:29:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-04-30 17:25:12 +00:00
|
|
|
*authentication_key_len = record->authentication_key_length;
|
2014-04-28 21:29:53 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
*encryption_key = record->encryption_key;
|
|
|
|
if (record->encryption_key_length == -1)
|
2011-06-02 07:11:26 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Bad key; XXX - report this */
|
|
|
|
*encryption_key_len = 0;
|
|
|
|
found = FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*encryption_key_len = record->encryption_key_length;
|
2011-06-02 07:11:26 +00:00
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Tell the caller whether cypher_hd has been created yet and a pointer.
|
|
|
|
Pass pointer to created flag so that caller can set if/when
|
|
|
|
it opens the cypher_hd. */
|
|
|
|
*cipher_hd = &record->cipher_hd;
|
|
|
|
*cipher_hd_created = &record->cipher_hd_created;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
2006-03-27 16:25:35 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-18 23:01:46 +00:00
|
|
|
static void
|
|
|
|
export_ipsec_pdu(dissector_handle_t dissector_handle, packet_info *pinfo, tvbuff_t *tvb)
|
|
|
|
{
|
|
|
|
if (have_tap_listener(exported_pdu_tap)) {
|
|
|
|
exp_pdu_data_t *exp_pdu_data;
|
2014-04-18 14:43:36 +00:00
|
|
|
guint8 tags = EXP_PDU_TAG_IP_SRC_BIT | EXP_PDU_TAG_IP_DST_BIT | EXP_PDU_TAG_SRC_PORT_BIT |
|
|
|
|
EXP_PDU_TAG_DST_PORT_BIT | EXP_PDU_TAG_ORIG_FNO_BIT;
|
2013-06-18 23:01:46 +00:00
|
|
|
|
|
|
|
exp_pdu_data = load_export_pdu_tags(pinfo, dissector_handle_get_dissector_name(dissector_handle), -1,
|
2014-04-18 14:43:36 +00:00
|
|
|
&tags, 1);
|
2013-06-18 23:01:46 +00:00
|
|
|
|
2014-03-18 22:01:22 +00:00
|
|
|
exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
|
|
|
|
exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
|
2013-06-18 23:01:46 +00:00
|
|
|
exp_pdu_data->pdu_tvb = tvb;
|
|
|
|
|
|
|
|
tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-28 23:42:42 +00:00
|
|
|
static int
|
|
|
|
dissect_ah_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
2006-03-27 16:25:35 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
proto_tree *ah_tree;
|
|
|
|
proto_item *ti;
|
|
|
|
struct newah ah;
|
|
|
|
int advance;
|
|
|
|
struct ah_header_data* header_data;
|
|
|
|
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "AH");
|
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
|
|
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&ah, 0, sizeof(ah));
|
|
|
|
advance = (int)sizeof(ah) + ((ah.ah_len - 1) << 2);
|
|
|
|
|
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "AH (SPI=0x%08x)",
|
|
|
|
(guint32)g_ntohl(ah.ah_spi));
|
|
|
|
|
|
|
|
header_data = (struct ah_header_data*)p_get_proto_data(pinfo->pool, pinfo, proto_ah, 0 );
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
if (tree) {
|
|
|
|
/* !!! specify length */
|
|
|
|
ti = proto_tree_add_item(tree, proto_ah, tvb, 0, advance, ENC_NA);
|
|
|
|
ah_tree = proto_item_add_subtree(ti, ett_ah);
|
|
|
|
|
2014-11-01 20:55:25 +00:00
|
|
|
proto_tree_add_uint_format_value(ah_tree, hf_ah_next_header, tvb,
|
2014-04-30 17:25:12 +00:00
|
|
|
offsetof(struct newah, ah_nxt), 1,
|
2014-11-01 20:55:25 +00:00
|
|
|
ah.ah_nxt, "%s (0x%02x)",
|
2014-04-30 17:25:12 +00:00
|
|
|
ipprotostr(ah.ah_nxt), ah.ah_nxt);
|
2014-11-01 20:55:25 +00:00
|
|
|
proto_tree_add_uint(ah_tree, hf_ah_length, tvb,
|
2014-04-30 17:25:12 +00:00
|
|
|
offsetof(struct newah, ah_len), 1,
|
2014-11-01 20:55:25 +00:00
|
|
|
(ah.ah_len + 2) << 2);
|
2014-04-30 17:25:12 +00:00
|
|
|
proto_tree_add_uint(ah_tree, hf_ah_spi, tvb,
|
|
|
|
offsetof(struct newah, ah_spi), 4,
|
|
|
|
(guint32)g_ntohl(ah.ah_spi));
|
|
|
|
proto_tree_add_uint(ah_tree, hf_ah_sequence, tvb,
|
|
|
|
offsetof(struct newah, ah_seq), 4,
|
|
|
|
(guint32)g_ntohl(ah.ah_seq));
|
|
|
|
proto_tree_add_item(ah_tree, hf_ah_iv, tvb,
|
|
|
|
sizeof(ah), (ah.ah_len) ? (ah.ah_len - 1) << 2 : 0,
|
|
|
|
ENC_NA);
|
|
|
|
|
|
|
|
if (header_data != NULL) {
|
|
|
|
/* Decide where to place next protocol decode */
|
|
|
|
if (g_ah_payload_in_subtree) {
|
|
|
|
header_data->next_tree = ah_tree;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
header_data->next_tree = tree;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2014-04-28 23:42:42 +00:00
|
|
|
if (header_data != NULL)
|
2014-04-30 17:25:12 +00:00
|
|
|
header_data->next_tree = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (header_data != NULL)
|
|
|
|
header_data->nxt = ah.ah_nxt;
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* start of the new header (could be a extension header) */
|
|
|
|
return advance;
|
2000-06-05 03:21:03 +00:00
|
|
|
}
|
|
|
|
|
2014-04-28 23:42:42 +00:00
|
|
|
static void
|
|
|
|
dissect_ah(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
struct ah_header_data header_data = {NULL, 0};
|
|
|
|
tvbuff_t *next_tvb;
|
|
|
|
int advance;
|
|
|
|
dissector_handle_t dissector_handle;
|
|
|
|
guint32 saved_match_uint;
|
|
|
|
|
|
|
|
/* "pass" ah_header_data to header dissector. This is done
|
|
|
|
indirectly to prevent conflicts with IPv6 dissector */
|
|
|
|
p_add_proto_data(pinfo->pool, pinfo, proto_ah, 0, &header_data);
|
|
|
|
|
|
|
|
advance = dissect_ah_header(tvb, pinfo, tree, NULL);
|
|
|
|
|
|
|
|
p_remove_proto_data(pinfo->pool, pinfo, proto_ah, 0);
|
|
|
|
|
|
|
|
next_tvb = tvb_new_subset_remaining(tvb, advance);
|
|
|
|
|
|
|
|
if (g_ah_payload_in_subtree) {
|
|
|
|
col_set_writable(pinfo->cinfo, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do lookup with the subdissector table */
|
|
|
|
saved_match_uint = pinfo->match_uint;
|
|
|
|
dissector_handle = dissector_get_uint_handle(ip_dissector_table, header_data.nxt);
|
|
|
|
if (dissector_handle) {
|
|
|
|
pinfo->match_uint = header_data.nxt;
|
|
|
|
} else {
|
|
|
|
dissector_handle = data_handle;
|
|
|
|
}
|
|
|
|
export_ipsec_pdu(dissector_handle, pinfo, next_tvb);
|
|
|
|
call_dissector(dissector_handle, next_tvb, pinfo, header_data.next_tree);
|
|
|
|
pinfo->match_uint = saved_match_uint;
|
|
|
|
}
|
2006-04-13 22:26:13 +00:00
|
|
|
|
2006-08-09 02:00:05 +00:00
|
|
|
/*
|
2011-10-27 15:38:32 +00:00
|
|
|
Name : dissect_esp_authentication(proto_tree *tree, tvbuff_t *tvb, gint len, gint esp_auth_len, guint8 *authenticator_data_computed,
|
|
|
|
gboolean authentication_ok, gboolean authentication_checking_ok)
|
|
|
|
Description : used to print Authenticator field when linked with libgcrypt. Print the expected authenticator value
|
|
|
|
if requested and if it is wrong.
|
|
|
|
Return : void
|
|
|
|
Params:
|
|
|
|
- proto_tree *tree : the current tree
|
|
|
|
- tvbuff_t *tvb : the tvbuffer
|
|
|
|
- gint len : length of the data availabale in tvbuff
|
|
|
|
- gint esp_auth_len : size of authenticator field
|
|
|
|
- guint8 *authenticator_data_computed : give the authenticator computed (only needed when authentication_ok and !authentication_checking_ok
|
|
|
|
- gboolean authentication_ok : set to true if the authentication checking has been run successfully
|
|
|
|
- gboolean authentication_checking_ok : set to true if the authentication was the one expected
|
2006-04-13 22:26:13 +00:00
|
|
|
*/
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2006-04-13 22:26:13 +00:00
|
|
|
static void
|
2006-08-09 02:00:05 +00:00
|
|
|
dissect_esp_authentication(proto_tree *tree, tvbuff_t *tvb, gint len, gint esp_auth_len, guint8 *authenticator_data_computed,
|
2011-10-27 15:38:32 +00:00
|
|
|
gboolean authentication_ok, gboolean authentication_checking_ok)
|
2006-04-13 22:26:13 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
proto_item *item;
|
|
|
|
proto_tree *icv_tree;
|
|
|
|
gboolean good = FALSE, bad = FALSE;
|
|
|
|
|
|
|
|
if(esp_auth_len == 0)
|
|
|
|
{
|
2014-06-29 13:13:51 +00:00
|
|
|
icv_tree = proto_tree_add_subtree(tree, tvb, len, 0,
|
|
|
|
ett_esp_icv, NULL, "NULL Authentication");
|
2014-04-30 17:25:12 +00:00
|
|
|
good = TRUE;
|
|
|
|
}
|
2012-10-11 20:38:39 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Make sure we have the auth trailer data */
|
|
|
|
else if(tvb_bytes_exist(tvb, len - esp_auth_len, esp_auth_len))
|
|
|
|
{
|
|
|
|
if((authentication_ok) && (authentication_checking_ok))
|
2006-04-13 22:26:13 +00:00
|
|
|
{
|
2014-06-29 13:13:51 +00:00
|
|
|
icv_tree = proto_tree_add_subtree(tree, tvb, len - esp_auth_len, esp_auth_len,
|
|
|
|
ett_esp_icv, NULL, "Authentication Data [correct]");
|
2014-04-30 17:25:12 +00:00
|
|
|
good = TRUE;
|
2006-04-13 22:26:13 +00:00
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
else if((authentication_ok) && (!authentication_checking_ok))
|
2006-04-13 22:26:13 +00:00
|
|
|
{
|
2014-06-29 13:13:51 +00:00
|
|
|
icv_tree = proto_tree_add_subtree_format(tree, tvb, len - esp_auth_len, esp_auth_len,
|
|
|
|
ett_esp_icv, NULL, "Authentication Data [incorrect, should be 0x%s]", authenticator_data_computed);
|
2014-04-30 17:25:12 +00:00
|
|
|
bad = TRUE;
|
2011-10-27 15:38:32 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
g_free(authenticator_data_computed);
|
2006-04-13 22:26:13 +00:00
|
|
|
}
|
2012-10-11 20:38:39 +00:00
|
|
|
|
2014-06-29 13:13:51 +00:00
|
|
|
else
|
|
|
|
icv_tree = proto_tree_add_subtree(tree, tvb, len - esp_auth_len, esp_auth_len,
|
|
|
|
ett_esp_icv, NULL, "Authentication Data");
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Truncated so just display what we have */
|
2014-06-29 13:13:51 +00:00
|
|
|
icv_tree = proto_tree_add_subtree(tree, tvb, len - esp_auth_len, esp_auth_len - (len - tvb_length(tvb)),
|
|
|
|
ett_esp_icv, NULL, "Authentication Data (truncated)");
|
2014-04-30 17:25:12 +00:00
|
|
|
bad = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
item = proto_tree_add_boolean(icv_tree, hf_esp_icv_good,
|
|
|
|
tvb, len - esp_auth_len, esp_auth_len, good);
|
|
|
|
PROTO_ITEM_SET_GENERATED(item);
|
2012-10-11 20:38:39 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
item = proto_tree_add_boolean(icv_tree, hf_esp_icv_bad,
|
|
|
|
tvb, len - esp_auth_len, esp_auth_len, bad);
|
|
|
|
PROTO_ITEM_SET_GENERATED(item);
|
2006-04-13 22:26:13 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2000-04-20 07:05:58 +00:00
|
|
|
static void
|
2001-02-28 06:37:29 +00:00
|
|
|
dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
1999-03-29 02:21:34 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
proto_tree *esp_tree = NULL;
|
|
|
|
proto_item *ti;
|
|
|
|
struct newesp esp;
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
gint len = 0;
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2014-04-30 17:25:12 +00:00
|
|
|
gint i;
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Packet Variables related */
|
|
|
|
gchar *ip_src = NULL;
|
|
|
|
gchar *ip_dst = NULL;
|
2006-03-27 16:25:35 +00:00
|
|
|
#endif
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2014-09-12 13:56:29 +00:00
|
|
|
guint32 spi = 0;
|
2014-04-30 17:25:12 +00:00
|
|
|
guint encapsulated_protocol = 0;
|
|
|
|
gboolean decrypt_dissect_ok = FALSE;
|
|
|
|
tvbuff_t *next_tvb;
|
|
|
|
dissector_handle_t dissector_handle;
|
|
|
|
guint32 saved_match_uint;
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2014-04-30 17:25:12 +00:00
|
|
|
gboolean null_encryption_decode_heuristic = FALSE;
|
|
|
|
guint8 *decrypted_data = NULL;
|
|
|
|
guint8 *authenticator_data = NULL;
|
|
|
|
guint8 *esp_data = NULL;
|
|
|
|
tvbuff_t *tvb_decrypted;
|
|
|
|
|
|
|
|
/* IPSEC encryption Variables related */
|
|
|
|
gint protocol_typ = IPSEC_SA_UNKNOWN;
|
|
|
|
gint esp_crypt_algo = IPSEC_ENCRYPT_NULL;
|
|
|
|
gint esp_auth_algo = IPSEC_AUTH_NULL;
|
|
|
|
gchar *esp_crypt_key = NULL;
|
|
|
|
gchar *esp_auth_key = NULL;
|
|
|
|
guint esp_crypt_key_len = 0;
|
|
|
|
guint esp_auth_key_len = 0;
|
|
|
|
gcry_cipher_hd_t *cipher_hd;
|
|
|
|
gboolean *cipher_hd_created;
|
|
|
|
|
|
|
|
gint esp_iv_len = 0;
|
|
|
|
gint esp_auth_len = 0;
|
|
|
|
gint decrypted_len = 0;
|
|
|
|
gboolean decrypt_ok = FALSE;
|
|
|
|
gboolean decrypt_using_libgcrypt = FALSE;
|
|
|
|
gboolean authentication_check_using_hmac_libgcrypt = FALSE;
|
|
|
|
gboolean authentication_ok = FALSE;
|
|
|
|
gboolean authentication_checking_ok = FALSE;
|
|
|
|
gboolean sad_is_present = FALSE;
|
2006-03-27 16:25:35 +00:00
|
|
|
#endif
|
2014-04-30 17:25:12 +00:00
|
|
|
gint esp_pad_len = 0;
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Variables for decryption and authentication checking used for libgrypt */
|
|
|
|
int decrypted_len_alloc = 0;
|
|
|
|
gcry_md_hd_t md_hd;
|
|
|
|
int md_len = 0;
|
|
|
|
gcry_error_t err = 0;
|
|
|
|
int crypt_algo_libgcrypt = 0;
|
|
|
|
int crypt_mode_libgcrypt = 0;
|
|
|
|
int auth_algo_libgcrypt = 0;
|
|
|
|
unsigned char *authenticator_data_computed = NULL;
|
|
|
|
unsigned char *authenticator_data_computed_md;
|
2011-10-27 15:38:32 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
unsigned char ctr_block[16];
|
2014-09-12 13:56:29 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
guint32 sequence_number;
|
2011-10-27 15:38:32 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/*
|
|
|
|
* load the top pane info. This should be overwritten by
|
|
|
|
* the next protocol in the stack
|
|
|
|
*/
|
2006-04-13 22:26:13 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESP");
|
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
tvb_memcpy(tvb, (guint8 *)&esp, 0, sizeof(esp));
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "ESP (SPI=0x%08x)",
|
|
|
|
(guint32)g_ntohl(esp.esp_spi));
|
2006-08-09 02:00:05 +00:00
|
|
|
|
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/*
|
|
|
|
* populate a tree in the second pane with the status of the link layer
|
|
|
|
* (ie none)
|
|
|
|
*/
|
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
|
|
|
|
spi = (guint32)g_ntohl(esp.esp_spi);
|
|
|
|
sequence_number = (guint32)g_ntohl(esp.esp_seq);
|
|
|
|
len = 0, encapsulated_protocol = 0;
|
|
|
|
decrypt_dissect_ok = FALSE;
|
|
|
|
|
|
|
|
ti = proto_tree_add_item(tree, proto_esp, tvb, 0, -1, ENC_NA);
|
|
|
|
esp_tree = proto_item_add_subtree(ti, ett_esp);
|
|
|
|
proto_tree_add_uint(esp_tree, hf_esp_spi, tvb,
|
|
|
|
offsetof(struct newesp, esp_spi), 4,
|
|
|
|
(guint32)g_ntohl(esp.esp_spi));
|
|
|
|
proto_tree_add_uint(esp_tree, hf_esp_sequence, tvb,
|
|
|
|
offsetof(struct newesp, esp_seq), 4,
|
|
|
|
sequence_number);
|
|
|
|
|
|
|
|
/* Sequence number analysis */
|
|
|
|
if (g_esp_do_sequence_analysis) {
|
|
|
|
if (!pinfo->fd->flags.visited) {
|
|
|
|
check_esp_sequence_info(spi, sequence_number, pinfo);
|
|
|
|
}
|
|
|
|
show_esp_sequence_info(spi, sequence_number,
|
|
|
|
tvb, esp_tree, pinfo);
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
|
2011-10-27 15:38:32 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2014-04-30 17:25:12 +00:00
|
|
|
/* The SAD is not activated */
|
|
|
|
if(g_esp_enable_null_encryption_decode_heuristic &&
|
|
|
|
!g_esp_enable_encryption_decode)
|
|
|
|
null_encryption_decode_heuristic = TRUE;
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
if(g_esp_enable_encryption_decode || g_esp_enable_authentication_check)
|
|
|
|
{
|
|
|
|
/* Get Source & Destination Addresses in gchar * with all the bytes available. */
|
|
|
|
|
|
|
|
if (pinfo->src.type == AT_IPv4){
|
|
|
|
protocol_typ = IPSEC_SA_IPV4;
|
|
|
|
}else if (pinfo->src.type == AT_IPv6){
|
|
|
|
protocol_typ = IPSEC_SA_IPV6;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Get the SPI */
|
|
|
|
if (tvb_length(tvb) >= 4)
|
|
|
|
{
|
|
|
|
spi = tvb_get_ntohl(tvb, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
PARSE the SAD and fill it. It may take some time since it will
|
|
|
|
be called every times an ESP Payload is found.
|
|
|
|
*/
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if((sad_is_present = get_esp_sa(protocol_typ, ip_src, ip_dst, spi,
|
|
|
|
&esp_crypt_algo, &esp_auth_algo,
|
|
|
|
&esp_crypt_key, &esp_crypt_key_len, &esp_auth_key, &esp_auth_key_len,
|
|
|
|
&cipher_hd, &cipher_hd_created)))
|
2011-10-27 15:38:32 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Get length of whole ESP packet. */
|
|
|
|
len = tvb_reported_length(tvb);
|
|
|
|
|
|
|
|
switch(esp_auth_algo)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_AUTH_NULL:
|
|
|
|
esp_auth_len = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_AUTH_ANY_64BIT:
|
|
|
|
esp_auth_len = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_AUTH_HMAC_SHA256_128:
|
|
|
|
case IPSEC_AUTH_ANY_128BIT:
|
|
|
|
esp_auth_len = 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_AUTH_HMAC_SHA512_256:
|
|
|
|
case IPSEC_AUTH_ANY_256BIT:
|
|
|
|
esp_auth_len = 32;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_AUTH_HMAC_SHA384_192:
|
|
|
|
case IPSEC_AUTH_ANY_192BIT:
|
|
|
|
esp_auth_len = 24;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_AUTH_HMAC_SHA1_96:
|
|
|
|
case IPSEC_AUTH_HMAC_SHA256_96:
|
|
|
|
/* case IPSEC_AUTH_AES_XCBC_MAC_96: */
|
|
|
|
case IPSEC_AUTH_HMAC_MD5_96:
|
|
|
|
case IPSEC_AUTH_HMAC_RIPEMD160_96:
|
|
|
|
case IPSEC_AUTH_ANY_96BIT:
|
|
|
|
default:
|
|
|
|
esp_auth_len = 12;
|
|
|
|
break;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2011-10-27 15:38:32 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if(g_esp_enable_authentication_check)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
|
|
|
switch(esp_auth_algo)
|
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_AUTH_HMAC_SHA1_96:
|
|
|
|
/*
|
|
|
|
RFC 2404 : HMAC-SHA-1-96 is a secret key algorithm.
|
|
|
|
While no fixed key length is specified in [RFC-2104],
|
|
|
|
for use with either ESP or AH a fixed key length of
|
|
|
|
160-bits MUST be supported. Key lengths other than
|
|
|
|
160-bits MUST NOT be supported (i.e. only 160-bit keys
|
|
|
|
are to be used by HMAC-SHA-1-96). A key length of
|
|
|
|
160-bits was chosen based on the recommendations in
|
|
|
|
[RFC-2104] (i.e. key lengths less than the
|
|
|
|
authenticator length decrease security strength and
|
|
|
|
keys longer than the authenticator length do not
|
|
|
|
significantly increase security strength).
|
|
|
|
*/
|
|
|
|
auth_algo_libgcrypt = GCRY_MD_SHA1;
|
|
|
|
authentication_check_using_hmac_libgcrypt = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
break;
|
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_AUTH_NULL:
|
|
|
|
authentication_check_using_hmac_libgcrypt = FALSE;
|
|
|
|
authentication_checking_ok = TRUE;
|
|
|
|
authentication_ok = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
break;
|
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/*
|
|
|
|
case IPSEC_AUTH_AES_XCBC_MAC_96:
|
|
|
|
auth_algo_libgcrypt =
|
|
|
|
authentication_check_using_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
|
|
|
|
case IPSEC_AUTH_HMAC_SHA256_96:
|
2014-04-30 17:25:12 +00:00
|
|
|
case IPSEC_AUTH_HMAC_SHA256_128:
|
2014-10-21 17:38:25 +00:00
|
|
|
auth_algo_libgcrypt = GCRY_MD_SHA256;
|
|
|
|
authentication_check_using_hmac_libgcrypt = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
break;
|
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_AUTH_HMAC_SHA384_192:
|
|
|
|
auth_algo_libgcrypt = GCRY_MD_SHA384;
|
|
|
|
authentication_check_using_hmac_libgcrypt = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
break;
|
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_AUTH_HMAC_SHA512_256:
|
|
|
|
auth_algo_libgcrypt = GCRY_MD_SHA512;
|
|
|
|
authentication_check_using_hmac_libgcrypt = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_AUTH_HMAC_MD5_96:
|
2014-10-21 17:38:25 +00:00
|
|
|
/*
|
|
|
|
RFC 2403 : HMAC-MD5-96 is a secret key algorithm.
|
|
|
|
While no fixed key length is specified in [RFC-2104],
|
|
|
|
for use with either ESP or AH a fixed key length of
|
|
|
|
128-bits MUST be supported. Key lengths other than
|
|
|
|
128-bits MUST NOT be supported (i.e. only 128-bit keys
|
|
|
|
are to be used by HMAC-MD5-96). A key length of
|
|
|
|
128-bits was chosen based on the recommendations in
|
|
|
|
[RFC-2104] (i.e. key lengths less than the
|
|
|
|
authenticator length decrease security strength and
|
|
|
|
keys longer than the authenticator length do not
|
|
|
|
significantly increase security strength).
|
|
|
|
*/
|
|
|
|
auth_algo_libgcrypt = GCRY_MD_MD5;
|
|
|
|
authentication_check_using_hmac_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
case IPSEC_AUTH_HMAC_RIPEMD160_96:
|
2014-10-21 17:38:25 +00:00
|
|
|
/*
|
|
|
|
RFC 2857 : HMAC-RIPEMD-160-96 produces a 160-bit
|
|
|
|
authenticator value. This 160-bit value can be
|
|
|
|
truncated as described in RFC2104. For use with
|
|
|
|
either ESP or AH, a truncated value using the first
|
|
|
|
96 bits MUST be supported.
|
|
|
|
*/
|
|
|
|
auth_algo_libgcrypt = GCRY_MD_RMD160;
|
|
|
|
authentication_check_using_hmac_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_AUTH_ANY_64BIT:
|
2014-04-30 17:25:12 +00:00
|
|
|
case IPSEC_AUTH_ANY_96BIT:
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_AUTH_ANY_128BIT:
|
|
|
|
case IPSEC_AUTH_ANY_192BIT:
|
|
|
|
case IPSEC_AUTH_ANY_256BIT:
|
2014-04-30 17:25:12 +00:00
|
|
|
default:
|
2014-10-21 17:38:25 +00:00
|
|
|
authentication_ok = FALSE;
|
|
|
|
authentication_check_using_hmac_libgcrypt = FALSE;
|
2014-04-30 17:25:12 +00:00
|
|
|
break;
|
2014-10-21 17:38:25 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2011-10-27 15:38:32 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if((authentication_check_using_hmac_libgcrypt) && (!authentication_ok))
|
2011-10-27 15:38:32 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
|
|
|
|
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Allocate Buffers for Authenticator Field */
|
|
|
|
authenticator_data = (guint8 *) g_malloc0 (( esp_auth_len + 1) * sizeof(guint8));
|
|
|
|
tvb_memcpy(tvb, authenticator_data, len - esp_auth_len, esp_auth_len);
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
esp_data = (guint8 *) g_malloc0 (( len - esp_auth_len + 1) * sizeof(guint8));
|
|
|
|
tvb_memcpy(tvb, esp_data, 0, len - esp_auth_len);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
err = gcry_md_open (&md_hd, auth_algo_libgcrypt, GCRY_MD_FLAG_HMAC);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "<IPsec/ESP Dissector> Error in Algorithm %s, gcry_md_open failed: %s\n",
|
|
|
|
gcry_md_algo_name(auth_algo_libgcrypt), gpg_strerror (err));
|
2014-04-30 17:25:12 +00:00
|
|
|
authentication_ok = FALSE;
|
2014-10-21 17:38:25 +00:00
|
|
|
g_free(authenticator_data);
|
|
|
|
g_free(esp_data);
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
else
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
md_len = gcry_md_get_algo_dlen (auth_algo_libgcrypt);
|
|
|
|
if (md_len < 1 || md_len < esp_auth_len)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
fprintf (stderr, "<IPsec/ESP Dissector> Error in Algorithm %s, grcy_md_get_algo_dlen failed: %d\n",
|
|
|
|
gcry_md_algo_name(auth_algo_libgcrypt), md_len);
|
2014-04-30 17:25:12 +00:00
|
|
|
authentication_ok = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
gcry_md_setkey( md_hd, esp_auth_key, esp_auth_key_len );
|
|
|
|
|
|
|
|
gcry_md_write (md_hd, esp_data, len - esp_auth_len);
|
|
|
|
|
|
|
|
authenticator_data_computed_md = gcry_md_read (md_hd, auth_algo_libgcrypt);
|
|
|
|
if (authenticator_data_computed_md == 0)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
fprintf (stderr, "<IPsec/ESP Dissector> Error in Algorithm %s, gcry_md_read failed\n",
|
|
|
|
gcry_md_algo_name(auth_algo_libgcrypt));
|
2014-04-30 17:25:12 +00:00
|
|
|
authentication_ok = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
if(memcmp (authenticator_data_computed_md, authenticator_data, esp_auth_len))
|
|
|
|
{
|
|
|
|
unsigned char authenticator_data_computed_car[3];
|
|
|
|
authenticator_data_computed = (guint8 *) g_malloc (( esp_auth_len * 2 + 1) * sizeof(guint8));
|
|
|
|
for (i = 0; i < esp_auth_len; i++)
|
|
|
|
{
|
|
|
|
g_snprintf((char *)authenticator_data_computed_car, 3,
|
|
|
|
"%02X", authenticator_data_computed_md[i] & 0xFF);
|
|
|
|
authenticator_data_computed[i*2] = authenticator_data_computed_car[0];
|
|
|
|
authenticator_data_computed[i*2 + 1] = authenticator_data_computed_car[1];
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
authenticator_data_computed[esp_auth_len * 2] ='\0';
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
authentication_ok = TRUE;
|
|
|
|
authentication_checking_ok = FALSE;
|
2011-10-27 15:38:32 +00:00
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
2011-10-27 15:38:32 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
authentication_ok = TRUE;
|
|
|
|
authentication_checking_ok = TRUE;
|
2011-10-27 15:38:32 +00:00
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
|
|
|
|
gcry_md_close (md_hd);
|
|
|
|
g_free(authenticator_data);
|
|
|
|
g_free(esp_data);
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
2011-10-27 15:38:32 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
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;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
switch(esp_crypt_algo)
|
|
|
|
{
|
|
|
|
case IPSEC_ENCRYPT_3DES_CBC :
|
|
|
|
/* RFC 2451 says :
|
|
|
|
3DES CBC uses a key of 192 bits.
|
|
|
|
The first 3DES key is taken from the first 64 bits,
|
|
|
|
the second from the next 64 bits, and the third
|
|
|
|
from the last 64 bits.
|
|
|
|
Implementations MUST take into consideration the
|
|
|
|
parity bits when initially accepting a new set of
|
|
|
|
keys. Each of the three keys is really 56 bits in
|
|
|
|
length with the extra 8 bits used for parity. */
|
|
|
|
|
|
|
|
/* Fix parameters for 3DES-CBC */
|
|
|
|
esp_iv_len = 8;
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_3DES;
|
|
|
|
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC;
|
|
|
|
|
|
|
|
decrypted_len = len - (int)sizeof(struct newesp);
|
|
|
|
|
|
|
|
if (decrypted_len <= 0)
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
else
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
if(decrypted_len % esp_iv_len == 0)
|
|
|
|
decrypted_len_alloc = decrypted_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len_alloc = (decrypted_len / esp_iv_len) * esp_iv_len + esp_iv_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (esp_crypt_key_len != gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt))
|
|
|
|
{
|
|
|
|
fprintf (stderr, "<ESP Preferences> Error in Encryption Algorithm 3DES-CBC : Bad Keylen (got %i Bits, need %lu)\n",
|
|
|
|
esp_crypt_key_len * 8,
|
|
|
|
(unsigned long) gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt) * 8);
|
|
|
|
decrypt_ok = FALSE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
else
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
2011-06-02 07:11:26 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_ENCRYPT_AES_CBC :
|
|
|
|
/* RFC 3602 says :
|
|
|
|
AES supports three key sizes: 128 bits, 192 bits,
|
|
|
|
and 256 bits. The default key size is 128 bits,
|
|
|
|
and all implementations MUST support this key size.
|
|
|
|
Implementations MAY also support key sizes of 192
|
|
|
|
bits and 256 bits. */
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Fix parameters for AES-CBC */
|
|
|
|
esp_iv_len = 16;
|
|
|
|
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len = len - (int)sizeof(struct newesp);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (decrypted_len <= 0)
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(decrypted_len % esp_iv_len == 0)
|
|
|
|
decrypted_len_alloc = decrypted_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len_alloc = (decrypted_len / esp_iv_len) * esp_iv_len + esp_iv_len;
|
|
|
|
|
|
|
|
switch(esp_crypt_key_len * 8)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
case 128:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_AES128;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case 192:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_AES192;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 256:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_AES256;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf (stderr, "<ESP Preferences> Error in Encryption Algorithm AES-CBC : Bad Keylen (%i Bits)\n",
|
|
|
|
esp_crypt_key_len * 8);
|
|
|
|
decrypt_ok = FALSE;
|
2014-04-28 21:29:53 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_ENCRYPT_CAST5_CBC :
|
|
|
|
/* RFC 2144 says :
|
|
|
|
The CAST-128 encryption algorithm has been designed to allow a key
|
|
|
|
size that can vary from 40 bits to 128 bits, in 8-bit increments
|
|
|
|
(that is, the allowable key sizes are 40, 48, 56, 64, ..., 112, 120,
|
|
|
|
and 128 bits.
|
|
|
|
We support only 128 bits. */
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Fix parameters for CAST5-CBC */
|
|
|
|
esp_iv_len = 8;
|
|
|
|
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len = len - (int)sizeof(struct newesp);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (decrypted_len <= 0)
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(decrypted_len % esp_iv_len == 0)
|
|
|
|
decrypted_len_alloc = decrypted_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len_alloc = (decrypted_len / esp_iv_len) * esp_iv_len + esp_iv_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
switch(esp_crypt_key_len * 8)
|
|
|
|
{
|
|
|
|
case 128:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_CAST5;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf (stderr, "<ESP Preferences> Error in Encryption Algorithm CAST5-CBC : Bad Keylen (%i Bits)\n",
|
|
|
|
esp_crypt_key_len * 8);
|
|
|
|
decrypt_ok = FALSE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_ENCRYPT_DES_CBC :
|
|
|
|
/* RFC 2405 says :
|
|
|
|
DES-CBC is a symmetric secret key algorithm.
|
|
|
|
The key size is 64-bits.
|
|
|
|
[It is commonly known as a 56-bit key as the key
|
|
|
|
has 56 significant bits; the least significant
|
|
|
|
bit in every byte is the parity bit.] */
|
|
|
|
|
|
|
|
/* Fix parameters for DES-CBC */
|
|
|
|
esp_iv_len = 8;
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_DES;
|
|
|
|
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC;
|
|
|
|
decrypted_len = len - (int)sizeof(struct newesp);
|
|
|
|
|
|
|
|
if (decrypted_len <= 0)
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(decrypted_len % esp_iv_len == 0)
|
|
|
|
decrypted_len_alloc = decrypted_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len_alloc = (decrypted_len / esp_iv_len) * esp_iv_len + esp_iv_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (esp_crypt_key_len != gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt))
|
|
|
|
{
|
|
|
|
fprintf (stderr, "<ESP Preferences> Error in Encryption Algorithm DES-CBC : Bad Keylen (%i Bits, need %lu)\n",
|
|
|
|
esp_crypt_key_len * 8, (unsigned long) gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt) * 8);
|
|
|
|
decrypt_ok = FALSE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
else
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_ENCRYPT_AES_CTR :
|
|
|
|
case IPSEC_ENCRYPT_AES_GCM :
|
|
|
|
/* RFC 3686 says :
|
|
|
|
AES supports three key sizes: 128 bits, 192 bits,
|
|
|
|
and 256 bits. The default key size is 128 bits,
|
|
|
|
and all implementations MUST support this key
|
|
|
|
size. Implementations MAY also support key sizes
|
|
|
|
of 192 bits and 256 bits. The remaining 32 bits
|
|
|
|
will be used as nonce. */
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Fix parameters for AES-CTR */
|
|
|
|
esp_iv_len = 8;
|
|
|
|
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CTR;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len = len - (int)sizeof(struct newesp);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (decrypted_len <= 0)
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(decrypted_len % esp_iv_len == 0)
|
|
|
|
decrypted_len_alloc = decrypted_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len_alloc = (decrypted_len / esp_iv_len) * esp_iv_len + esp_iv_len;
|
|
|
|
|
|
|
|
switch(esp_crypt_key_len * 8)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
case 160:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_AES128;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case 224:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_AES192;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 288:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_AES256;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf (stderr, "<ESP Preferences> Error in Encryption Algorithm AES-CTR / AES-GCM : Bad Keylen (%i Bits)\n",
|
|
|
|
esp_crypt_key_len * 8);
|
|
|
|
decrypt_ok = FALSE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_ENCRYPT_TWOFISH_CBC :
|
|
|
|
/* Twofish is a 128-bit block cipher developed by
|
|
|
|
Counterpane Labs that accepts a variable-length
|
|
|
|
key up to 256 bits.
|
|
|
|
We will only accept key sizes of 128 and 256 bits.
|
|
|
|
*/
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Fix parameters for TWOFISH-CBC */
|
|
|
|
esp_iv_len = 16;
|
|
|
|
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC;
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len = len - (int)sizeof(struct newesp);
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (decrypted_len <= 0)
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(decrypted_len % esp_iv_len == 0)
|
|
|
|
decrypted_len_alloc = decrypted_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len_alloc = (decrypted_len / esp_iv_len) * esp_iv_len + esp_iv_len;
|
|
|
|
|
|
|
|
switch(esp_crypt_key_len * 8)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
case 128:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_TWOFISH128;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case 256:
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_TWOFISH;
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf (stderr, "<ESP Preferences> Error in Encryption Algorithm TWOFISH-CBC : Bad Keylen (%i Bits)\n",
|
|
|
|
esp_crypt_key_len * 8);
|
|
|
|
decrypt_ok = FALSE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
break;
|
2011-10-27 15:38:32 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_ENCRYPT_BLOWFISH_CBC :
|
|
|
|
/* Bruce Schneier of Counterpane Systems developed
|
|
|
|
the Blowfish block cipher algorithm.
|
|
|
|
RFC 2451 shows that Blowfish uses key sizes from
|
|
|
|
40 to 448 bits. The Default size is 128 bits.
|
|
|
|
We will only accept key sizes of 128 bits, because
|
|
|
|
libgrypt only accept this key size.
|
|
|
|
*/
|
2014-04-28 21:29:53 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Fix parameters for BLOWFISH-CBC */
|
|
|
|
esp_iv_len = 8;
|
|
|
|
crypt_algo_libgcrypt = GCRY_CIPHER_BLOWFISH;
|
|
|
|
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len = len - (int)sizeof(struct newesp);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (decrypted_len <= 0)
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(decrypted_len % esp_iv_len == 0)
|
|
|
|
decrypted_len_alloc = decrypted_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_len_alloc = (decrypted_len / esp_iv_len) * esp_iv_len + esp_iv_len;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (esp_crypt_key_len != gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt))
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
fprintf (stderr, "<ESP Preferences> Error in Encryption Algorithm BLOWFISH-CBC : Bad Keylen (%i Bits, need %lu)\n",
|
|
|
|
esp_crypt_key_len * 8, (unsigned long) gcry_cipher_get_algo_keylen (crypt_algo_libgcrypt) * 8);
|
|
|
|
decrypt_ok = FALSE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
else
|
|
|
|
decrypt_using_libgcrypt = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
break;
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
case IPSEC_ENCRYPT_NULL :
|
|
|
|
default :
|
|
|
|
/* Fix parameters */
|
|
|
|
esp_iv_len = 0;
|
|
|
|
decrypted_len = len - (int)sizeof(struct newesp);
|
|
|
|
|
|
|
|
if (decrypted_len <= 0)
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
else
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
|
|
|
/* Allocate Buffers for Encrypted and Decrypted data */
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypted_data = (guint8 *) g_malloc ((decrypted_len + 1)* sizeof(guint8));
|
|
|
|
tvb_memcpy(tvb, decrypted_data , sizeof(struct newesp), decrypted_len);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
decrypt_ok = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (decrypt_using_libgcrypt)
|
|
|
|
{
|
|
|
|
/* Allocate Buffers for Encrypted and Decrypted data */
|
|
|
|
decrypted_data = (guint8 *) g_malloc ((decrypted_len_alloc + esp_iv_len)* sizeof(guint8));
|
|
|
|
tvb_memcpy(tvb, decrypted_data, sizeof(struct newesp), decrypted_len);
|
|
|
|
|
|
|
|
/* (Lazily) create the cipher_hd */
|
|
|
|
if (!(*cipher_hd_created)) {
|
|
|
|
err = gcry_cipher_open(cipher_hd, crypt_algo_libgcrypt, crypt_mode_libgcrypt, 0);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "<IPsec/ESP Dissector> Error in Algorithm %s Mode %d, grcy_open_cipher failed: %s\n",
|
|
|
|
gcry_cipher_algo_name(crypt_algo_libgcrypt), crypt_mode_libgcrypt, gpg_strerror(err));
|
|
|
|
g_free(decrypted_data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* OK, set the key */
|
|
|
|
if (*cipher_hd_created == FALSE)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
if (crypt_mode_libgcrypt == GCRY_CIPHER_MODE_CTR)
|
2014-04-28 21:29:53 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Counter mode key includes a 4 byte, (32 bit), nonce following the key */
|
|
|
|
err = gcry_cipher_setkey(*cipher_hd, esp_crypt_key, esp_crypt_key_len - 4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err = gcry_cipher_setkey(*cipher_hd, esp_crypt_key, esp_crypt_key_len);
|
2014-04-28 21:29:53 +00:00
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "<IPsec/ESP Dissector> Error in Algorithm %s Mode %d, gcry_cipher_setkey(key_len=%d) failed: %s\n",
|
|
|
|
gcry_cipher_algo_name(crypt_algo_libgcrypt), crypt_mode_libgcrypt, esp_crypt_key_len, gpg_strerror (err));
|
|
|
|
gcry_cipher_close(*cipher_hd);
|
|
|
|
g_free(decrypted_data);
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
|
|
|
|
/* Key is created and has its key set now */
|
|
|
|
*cipher_hd_created = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Now try to decrypt */
|
|
|
|
if (crypt_mode_libgcrypt == GCRY_CIPHER_MODE_CTR)
|
|
|
|
{
|
|
|
|
/* Set CTR first */
|
|
|
|
memset(ctr_block, 0, 16);
|
|
|
|
memcpy(ctr_block, esp_crypt_key + esp_crypt_key_len - 4, 4);
|
|
|
|
memcpy(ctr_block + 4, decrypted_data, 8);
|
|
|
|
ctr_block[15] = 1;
|
|
|
|
if (esp_crypt_algo == IPSEC_ENCRYPT_AES_GCM) {
|
|
|
|
ctr_block[15]++;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
err = gcry_cipher_setctr(*cipher_hd, ctr_block, 16);
|
|
|
|
if (!err)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
err = gcry_cipher_decrypt(*cipher_hd, decrypted_data + esp_iv_len, decrypted_len_alloc, NULL, 0);
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err = gcry_cipher_decrypt(*cipher_hd, decrypted_data, decrypted_len_alloc + esp_iv_len, NULL, 0);
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "<IPsec/ESP Dissector> Error in Algorithm %s, Mode %d, gcry_cipher_decrypt failed: %s\n",
|
|
|
|
gcry_cipher_algo_name(crypt_algo_libgcrypt), crypt_mode_libgcrypt, gpg_strerror (err));
|
|
|
|
gcry_cipher_close(*cipher_hd);
|
|
|
|
g_free(decrypted_data);
|
|
|
|
decrypt_ok = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Copy back the Authentication which was not encrypted */
|
|
|
|
if(decrypted_len >= esp_auth_len)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
tvb_memcpy(tvb, decrypted_data+decrypted_len-esp_auth_len, (gint)(sizeof(struct newesp)+decrypted_len-esp_auth_len), esp_auth_len);
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Decryption has finished */
|
|
|
|
decrypt_ok = TRUE;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
|
|
|
else if(g_esp_enable_null_encryption_decode_heuristic)
|
|
|
|
{
|
|
|
|
/* The packet does not belong to a Security Association */
|
|
|
|
null_encryption_decode_heuristic = TRUE;
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if(decrypt_ok && (decrypted_len > esp_iv_len))
|
|
|
|
{
|
|
|
|
tvb_decrypted = tvb_new_child_real_data(tvb, (guint8 *)g_memdup(decrypted_data+sizeof(guint8)*esp_iv_len,
|
|
|
|
decrypted_len - esp_iv_len),
|
|
|
|
decrypted_len - esp_iv_len, decrypted_len - esp_iv_len);
|
|
|
|
g_free(decrypted_data);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
add_new_data_source(pinfo, tvb_decrypted, "Decrypted Data");
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Handler to free the Decrypted Data Buffer. */
|
|
|
|
tvb_set_free_cb(tvb_decrypted,g_free);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if(tvb_bytes_exist(tvb, 8, esp_iv_len))
|
|
|
|
{
|
|
|
|
if(esp_iv_len > 0)
|
|
|
|
proto_tree_add_item(esp_tree, hf_esp_iv, tvb, 8, esp_iv_len, ENC_NA);
|
|
|
|
}
|
|
|
|
else
|
2014-11-01 20:55:25 +00:00
|
|
|
{
|
|
|
|
proto_tree_add_bytes_format(esp_tree, hf_esp_iv, tvb, 8, -1, NULL, "IV (truncated)");
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Make sure the packet is not truncated before the fields
|
|
|
|
* we need to read to determine the encapsulated protocol */
|
|
|
|
if(tvb_bytes_exist(tvb_decrypted, decrypted_len - esp_iv_len - esp_auth_len - 2, 2))
|
|
|
|
{
|
|
|
|
esp_pad_len = tvb_get_guint8(tvb_decrypted, decrypted_len - esp_iv_len - esp_auth_len - 2);
|
2014-04-30 17:25:12 +00:00
|
|
|
|
2014-10-21 17:38:25 +00:00
|
|
|
if(decrypted_len - esp_iv_len - esp_auth_len - esp_pad_len - 2 >= 0)
|
2014-04-28 21:29:53 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
/* Get the encapsulated protocol */
|
|
|
|
encapsulated_protocol = tvb_get_guint8(tvb_decrypted, decrypted_len - esp_iv_len - esp_auth_len - 1);
|
|
|
|
|
|
|
|
dissector_handle = dissector_get_uint_handle(ip_dissector_table, encapsulated_protocol);
|
|
|
|
if (dissector_handle) {
|
|
|
|
saved_match_uint = pinfo->match_uint;
|
|
|
|
pinfo->match_uint = encapsulated_protocol;
|
|
|
|
next_tvb = tvb_new_subset_length(tvb_decrypted, 0,
|
|
|
|
decrypted_len - esp_auth_len - esp_pad_len - esp_iv_len - 2);
|
|
|
|
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;
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
2014-04-28 21:29:53 +00:00
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(decrypt_dissect_ok)
|
|
|
|
{
|
|
|
|
if(esp_tree)
|
2014-04-30 17:25:12 +00:00
|
|
|
{
|
2014-10-21 17:38:25 +00:00
|
|
|
if(esp_pad_len !=0)
|
2014-11-01 20:55:25 +00:00
|
|
|
proto_tree_add_item(esp_tree, hf_esp_pad,
|
2014-10-21 17:38:25 +00:00
|
|
|
tvb_decrypted,
|
|
|
|
decrypted_len - esp_iv_len - esp_auth_len - 2 - esp_pad_len,
|
2014-11-01 20:55:25 +00:00
|
|
|
esp_pad_len, ENC_NA);
|
2014-10-21 17:38:25 +00:00
|
|
|
|
|
|
|
proto_tree_add_uint(esp_tree, hf_esp_pad_len, tvb_decrypted,
|
|
|
|
decrypted_len - esp_iv_len - esp_auth_len - 2, 1,
|
|
|
|
esp_pad_len);
|
|
|
|
|
|
|
|
proto_tree_add_uint_format(esp_tree, hf_esp_protocol, tvb_decrypted,
|
|
|
|
decrypted_len - esp_iv_len - esp_auth_len - 1, 1,
|
|
|
|
encapsulated_protocol,
|
|
|
|
"Next header: %s (0x%02x)",
|
|
|
|
ipprotostr(encapsulated_protocol), encapsulated_protocol);
|
|
|
|
|
|
|
|
dissect_esp_authentication(esp_tree,
|
|
|
|
tvb_decrypted,
|
|
|
|
decrypted_len - esp_iv_len,
|
|
|
|
esp_auth_len,
|
|
|
|
authenticator_data_computed,
|
|
|
|
authentication_ok,
|
|
|
|
authentication_checking_ok );
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-21 17:38:25 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
next_tvb = tvb_new_subset_length(tvb_decrypted, 0,
|
|
|
|
decrypted_len - esp_iv_len - esp_auth_len);
|
|
|
|
export_ipsec_pdu(data_handle, pinfo, next_tvb);
|
|
|
|
call_dissector(data_handle, next_tvb, pinfo, esp_tree);
|
|
|
|
|
|
|
|
if(esp_tree)
|
|
|
|
dissect_esp_authentication(esp_tree,
|
|
|
|
tvb_decrypted,
|
|
|
|
decrypted_len - esp_iv_len, esp_auth_len,
|
|
|
|
authenticator_data_computed, authentication_ok,
|
|
|
|
authentication_checking_ok );
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/*
|
2006-05-02 19:58:19 +00:00
|
|
|
If the packet is present in the security association database and the field g_esp_enable_authentication_check set.
|
2014-04-30 17:25:12 +00:00
|
|
|
*/
|
|
|
|
if(!g_esp_enable_encryption_decode && g_esp_enable_authentication_check && sad_is_present)
|
|
|
|
{
|
|
|
|
next_tvb = tvb_new_subset(tvb, (int)sizeof(struct newesp), len - (int)sizeof(struct newesp) - esp_auth_len, -1);
|
|
|
|
export_ipsec_pdu(data_handle, pinfo, next_tvb);
|
|
|
|
call_dissector(data_handle, next_tvb, pinfo, esp_tree);
|
|
|
|
|
|
|
|
if(esp_tree)
|
|
|
|
dissect_esp_authentication(esp_tree, tvb, len ,
|
|
|
|
esp_auth_len, authenticator_data_computed,
|
|
|
|
authentication_ok, authentication_checking_ok );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The packet does not belong to a security association and the field g_esp_enable_null_encryption_decode_heuristic is set */
|
|
|
|
else if(null_encryption_decode_heuristic)
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
if(g_esp_enable_null_encryption_decode_heuristic)
|
2011-10-27 15:38:32 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Get length of whole ESP packet. */
|
|
|
|
len = tvb_reported_length(tvb);
|
|
|
|
|
|
|
|
/* Make sure the packet is not truncated before the fields
|
|
|
|
* we need to read to determine the encapsulated protocol */
|
|
|
|
if(tvb_bytes_exist(tvb, len - 14, 2))
|
|
|
|
{
|
|
|
|
esp_pad_len = tvb_get_guint8(tvb, len - 14);
|
|
|
|
encapsulated_protocol = tvb_get_guint8(tvb, len - 13);
|
|
|
|
dissector_handle = dissector_get_uint_handle(ip_dissector_table, encapsulated_protocol);
|
|
|
|
if (dissector_handle) {
|
|
|
|
saved_match_uint = pinfo->match_uint;
|
|
|
|
pinfo->match_uint = encapsulated_protocol;
|
|
|
|
next_tvb = tvb_new_subset(tvb, (int)sizeof(struct newesp), -1,
|
|
|
|
len - (int)sizeof(struct newesp) - 14 - esp_pad_len);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2011-10-27 15:38:32 +00:00
|
|
|
}
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
if(decrypt_dissect_ok)
|
2011-10-27 15:38:32 +00:00
|
|
|
{
|
2014-04-30 17:25:12 +00:00
|
|
|
if(esp_tree)
|
|
|
|
{
|
|
|
|
proto_tree_add_uint(esp_tree, hf_esp_pad_len, tvb,
|
|
|
|
len - 14, 1,
|
|
|
|
esp_pad_len);
|
2011-10-27 15:38:32 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
proto_tree_add_uint_format(esp_tree, hf_esp_protocol, tvb,
|
|
|
|
len - 13, 1,
|
|
|
|
encapsulated_protocol,
|
|
|
|
"Next header: %s (0x%02x)",
|
|
|
|
ipprotostr(encapsulated_protocol), encapsulated_protocol);
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Make sure we have the auth trailer data */
|
|
|
|
if(tvb_bytes_exist(tvb, len - 12, 12))
|
2011-10-27 15:38:32 +00:00
|
|
|
{
|
2014-11-01 20:55:25 +00:00
|
|
|
proto_tree_add_item(esp_tree, hf_esp_authentication_data, tvb, len - 12, 12, ENC_NA);
|
2011-10-27 15:38:32 +00:00
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Truncated so just display what we have */
|
2014-11-01 20:55:25 +00:00
|
|
|
proto_tree_add_bytes_format(esp_tree, hf_esp_authentication_data, tvb, len - 12, 12 - (len - tvb_length(tvb)),
|
|
|
|
NULL, "Authentication Data (truncated)");
|
2014-04-30 17:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
2011-10-27 15:38:32 +00:00
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
#endif
|
2006-08-09 02:00:05 +00:00
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
|
1999-10-15 05:30:43 +00:00
|
|
|
|
2000-04-20 07:05:58 +00:00
|
|
|
static void
|
2001-02-28 06:37:29 +00:00
|
|
|
dissect_ipcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
1999-10-15 05:30:43 +00:00
|
|
|
{
|
2006-03-27 16:25:35 +00:00
|
|
|
proto_tree *ipcomp_tree;
|
|
|
|
proto_item *ti;
|
|
|
|
struct ipcomp ipcomp;
|
|
|
|
const char *p;
|
2013-06-18 23:01:46 +00:00
|
|
|
dissector_handle_t dissector_handle;
|
|
|
|
guint32 saved_match_uint;
|
1999-10-15 05:30:43 +00:00
|
|
|
|
2006-03-27 16:25:35 +00:00
|
|
|
/*
|
|
|
|
* load the top pane info. This should be overwritten by
|
|
|
|
* the next protocol in the stack
|
|
|
|
*/
|
2009-08-09 06:26:46 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPComp");
|
2009-08-09 07:36:13 +00:00
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2006-03-27 16:25:35 +00:00
|
|
|
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&ipcomp, 0, sizeof(ipcomp));
|
|
|
|
|
2013-06-14 01:02:11 +00:00
|
|
|
p = try_val_to_str(g_ntohs(ipcomp.comp_cpi), cpi2val);
|
|
|
|
if (p == NULL) {
|
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "IPComp (CPI=0x%04x)", g_ntohs(ipcomp.comp_cpi));
|
|
|
|
} else {
|
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "IPComp (CPI=%s)", p);
|
2006-03-27 16:25:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* populate a tree in the second pane with the status of the link layer
|
|
|
|
* (ie none)
|
|
|
|
*/
|
|
|
|
if (tree) {
|
2010-12-01 15:45:24 +00:00
|
|
|
tvbuff_t *data, *decomp;
|
|
|
|
|
2011-10-21 02:10:19 +00:00
|
|
|
ti = proto_tree_add_item(tree, proto_ipcomp, tvb, 0, -1, ENC_NA);
|
2006-03-27 16:25:35 +00:00
|
|
|
ipcomp_tree = proto_item_add_subtree(ti, ett_ipcomp);
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2014-11-01 20:55:25 +00:00
|
|
|
proto_tree_add_uint_format_value(ipcomp_tree, hf_ipcomp_next_header, tvb,
|
2014-04-30 17:25:12 +00:00
|
|
|
offsetof(struct ipcomp, comp_nxt), 1,
|
2014-11-01 20:55:25 +00:00
|
|
|
ipcomp.comp_nxt, "%s (0x%02x)",
|
2014-04-30 17:25:12 +00:00
|
|
|
ipprotostr(ipcomp.comp_nxt), ipcomp.comp_nxt);
|
2006-03-27 16:25:35 +00:00
|
|
|
proto_tree_add_uint(ipcomp_tree, hf_ipcomp_flags, tvb,
|
2014-04-30 17:25:12 +00:00
|
|
|
offsetof(struct ipcomp, comp_flags), 1,
|
|
|
|
ipcomp.comp_flags);
|
2006-03-27 16:25:35 +00:00
|
|
|
proto_tree_add_uint(ipcomp_tree, hf_ipcomp_cpi, tvb,
|
2014-04-30 17:25:12 +00:00
|
|
|
offsetof(struct ipcomp, comp_cpi), 2,
|
|
|
|
g_ntohs(ipcomp.comp_cpi));
|
2010-12-01 15:45:24 +00:00
|
|
|
|
2013-02-19 23:17:07 +00:00
|
|
|
data = tvb_new_subset_remaining(tvb, sizeof(struct ipcomp));
|
2013-06-18 23:01:46 +00:00
|
|
|
export_ipsec_pdu(data_handle, pinfo, data);
|
2010-12-01 15:45:24 +00:00
|
|
|
call_dissector(data_handle, data, pinfo, ipcomp_tree);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* try to uncompress as if it were DEFLATEd. With negotiated
|
|
|
|
* CPIs, we don't know the algorithm beforehand; if we get it
|
|
|
|
* wrong, tvb_uncompress() returns NULL and nothing is displayed.
|
|
|
|
*/
|
2014-06-19 17:18:16 +00:00
|
|
|
decomp = tvb_child_uncompress(data, data, 0, tvb_length(data));
|
2010-12-01 15:45:24 +00:00
|
|
|
if (decomp) {
|
|
|
|
add_new_data_source(pinfo, decomp, "IPcomp inflated data");
|
2013-06-18 23:01:46 +00:00
|
|
|
saved_match_uint = pinfo->match_uint;
|
|
|
|
dissector_handle = dissector_get_uint_handle(ip_dissector_table, ipcomp.comp_nxt);
|
|
|
|
if (dissector_handle) {
|
|
|
|
pinfo->match_uint = ipcomp.comp_nxt;
|
|
|
|
} else {
|
|
|
|
dissector_handle = data_handle;
|
|
|
|
}
|
|
|
|
export_ipsec_pdu(dissector_handle, pinfo, decomp);
|
|
|
|
call_dissector(dissector_handle, decomp, pinfo, tree);
|
|
|
|
pinfo->match_uint = saved_match_uint;
|
2010-12-01 15:45:24 +00:00
|
|
|
}
|
2006-03-27 16:25:35 +00:00
|
|
|
}
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
1999-07-29 05:47:07 +00:00
|
|
|
|
2014-04-28 21:29:53 +00:00
|
|
|
static void ipsec_init_protocol(void)
|
|
|
|
{
|
2014-09-12 13:56:29 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2014-04-30 17:25:12 +00:00
|
|
|
/* Free any SA records added by other dissectors */
|
|
|
|
guint n;
|
|
|
|
for (n=0; n < extra_esp_sa_records.num_records; n++) {
|
|
|
|
uat_esp_sa_record_free_cb(&(extra_esp_sa_records.records[n]));
|
|
|
|
}
|
2014-05-12 21:30:14 +00:00
|
|
|
|
|
|
|
/* Free overall block of records */
|
|
|
|
if (extra_esp_sa_records.num_records > 0) {
|
|
|
|
g_free(extra_esp_sa_records.records);
|
|
|
|
extra_esp_sa_records.records = NULL;
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
extra_esp_sa_records.num_records = 0;
|
2014-09-09 22:26:31 +00:00
|
|
|
|
|
|
|
/* Destroy any existing hashes. */
|
|
|
|
if (esp_sequence_analysis_hash) {
|
|
|
|
g_hash_table_destroy(esp_sequence_analysis_hash);
|
|
|
|
}
|
|
|
|
if (esp_sequence_analysis_report_hash) {
|
|
|
|
g_hash_table_destroy(esp_sequence_analysis_report_hash);
|
|
|
|
}
|
2014-09-12 13:56:29 +00:00
|
|
|
#endif
|
2014-09-09 22:26:31 +00:00
|
|
|
|
|
|
|
/* Now create them over */
|
|
|
|
esp_sequence_analysis_hash = g_hash_table_new(word_hash_func, word_equal);
|
|
|
|
esp_sequence_analysis_report_hash = g_hash_table_new(word_hash_func, word_equal);
|
|
|
|
|
2014-04-28 21:29:53 +00:00
|
|
|
}
|
|
|
|
|
1999-07-29 05:47:07 +00:00
|
|
|
void
|
|
|
|
proto_register_ipsec(void)
|
|
|
|
{
|
1999-10-11 12:37:50 +00:00
|
|
|
static hf_register_info hf_ah[] = {
|
2014-11-01 20:55:25 +00:00
|
|
|
{ &hf_ah_next_header,
|
|
|
|
{ "Next header", "ah.next_header", FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_ah_length,
|
|
|
|
{ "Length", "ah.length", FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
1999-10-11 12:37:50 +00:00
|
|
|
{ &hf_ah_spi,
|
2007-04-13 05:44:57 +00:00
|
|
|
{ "AH SPI", "ah.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
|
|
|
|
"IP Authentication Header Security Parameters Index", HFILL }},
|
2006-09-12 09:53:10 +00:00
|
|
|
{ &hf_ah_iv,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
{ "AH ICV", "ah.icv", FT_BYTES, BASE_NONE, NULL, 0x0,
|
2007-04-13 05:44:57 +00:00
|
|
|
"IP Authentication Header Integrity Check Value", HFILL }},
|
1999-10-11 12:37:50 +00:00
|
|
|
{ &hf_ah_sequence,
|
2007-04-13 05:44:57 +00:00
|
|
|
{ "AH Sequence", "ah.sequence", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
|
|
"IP Authentication Header Sequence Number", HFILL }}
|
1999-10-11 12:37:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static hf_register_info hf_esp[] = {
|
|
|
|
{ &hf_esp_spi,
|
2011-12-08 19:34:04 +00:00
|
|
|
{ "ESP SPI", "esp.spi", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
|
2007-04-13 05:44:57 +00:00
|
|
|
"IP Encapsulating Security Payload Security Parameters Index", HFILL }},
|
1999-10-11 12:37:50 +00:00
|
|
|
{ &hf_esp_sequence,
|
2007-04-13 05:44:57 +00:00
|
|
|
{ "ESP Sequence", "esp.sequence", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
|
|
"IP Encapsulating Security Payload Sequence Number", HFILL }},
|
2014-11-01 20:55:25 +00:00
|
|
|
{ &hf_esp_pad,
|
|
|
|
{ "Pad", "esp.pad", FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
2006-04-13 22:26:13 +00:00
|
|
|
{ &hf_esp_pad_len,
|
2007-04-13 05:44:57 +00:00
|
|
|
{ "ESP Pad Length", "esp.pad_len", FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"IP Encapsulating Security Payload Pad Length", HFILL }},
|
2004-11-12 10:03:53 +00:00
|
|
|
{ &hf_esp_protocol,
|
2007-04-13 05:44:57 +00:00
|
|
|
{ "ESP Next Header", "esp.protocol", FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
|
|
"IP Encapsulating Security Payload Next Header", HFILL }},
|
2014-11-01 20:55:25 +00:00
|
|
|
{ &hf_esp_authentication_data,
|
|
|
|
{ "Authentication Data", "esp.authentication_data", FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
2006-09-12 09:53:10 +00:00
|
|
|
{ &hf_esp_iv,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
{ "ESP IV", "esp.iv", FT_BYTES, BASE_NONE, NULL, 0x0,
|
2012-10-11 20:38:39 +00:00
|
|
|
"IP Encapsulating Security Payload", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_esp_icv_good,
|
|
|
|
{ "Good", "esp.icv_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
|
|
|
"True: ICV matches packet content; False: doesn't match content or not checked", HFILL }},
|
|
|
|
{ &hf_esp_icv_bad,
|
|
|
|
{ "Bad", "esp.icv_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
|
|
|
"True: ICV doesn't match packet content; False: matches content or not checked", HFILL }},
|
2014-09-09 22:26:31 +00:00
|
|
|
{ &hf_esp_sequence_analysis_expected_sn,
|
|
|
|
{ "Expected SN", "esp.sequence-analysis.expected-sn", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_esp_sequence_analysis_previous_frame,
|
|
|
|
{ "Previous Frame", "esp.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
1999-10-11 12:37:50 +00:00
|
|
|
};
|
|
|
|
|
1999-10-15 05:30:43 +00:00
|
|
|
static hf_register_info hf_ipcomp[] = {
|
2014-11-01 20:55:25 +00:00
|
|
|
{ &hf_ipcomp_next_header,
|
|
|
|
{ "Next Header", "ipcomp.next_header", FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
1999-10-15 05:46:18 +00:00
|
|
|
{ &hf_ipcomp_flags,
|
2007-04-13 05:44:57 +00:00
|
|
|
{ "IPComp Flags", "ipcomp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
|
|
"IP Payload Compression Protocol Flags", HFILL }},
|
1999-10-15 05:30:43 +00:00
|
|
|
{ &hf_ipcomp_cpi,
|
2007-04-13 05:44:57 +00:00
|
|
|
{ "IPComp CPI", "ipcomp.cpi", FT_UINT16, BASE_HEX, VALS(cpi2val), 0x0,
|
|
|
|
"IP Payload Compression Protocol Compression Parameter Index", HFILL }},
|
1999-10-15 05:30:43 +00:00
|
|
|
};
|
2011-06-02 07:11:26 +00:00
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_ah,
|
|
|
|
&ett_esp,
|
2012-10-11 20:38:39 +00:00
|
|
|
&ett_esp_icv,
|
1999-11-16 11:44:20 +00:00
|
|
|
&ett_ipcomp,
|
|
|
|
};
|
1999-10-15 05:30:43 +00:00
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
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 }}
|
|
|
|
};
|
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2011-06-02 07:11:26 +00:00
|
|
|
|
|
|
|
static const value_string esp_proto_type_vals[] = {
|
|
|
|
{ IPSEC_SA_IPV4, "IPv4" },
|
|
|
|
{ IPSEC_SA_IPV6, "IPv6" },
|
|
|
|
{ 0x00, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string esp_encryption_type_vals[] = {
|
|
|
|
{ IPSEC_ENCRYPT_NULL, "NULL" },
|
|
|
|
{ IPSEC_ENCRYPT_3DES_CBC, "TripleDES-CBC [RFC2451]" },
|
|
|
|
{ IPSEC_ENCRYPT_AES_CBC, "AES-CBC [RFC3602]" },
|
|
|
|
{ IPSEC_ENCRYPT_AES_CTR, "AES-CTR [RFC3686]" },
|
|
|
|
{ IPSEC_ENCRYPT_DES_CBC, "DES-CBC [RFC2405]" },
|
|
|
|
{ IPSEC_ENCRYPT_CAST5_CBC, "CAST5-CBC [RFC2144]" },
|
|
|
|
{ IPSEC_ENCRYPT_BLOWFISH_CBC, "BLOWFISH-CBC [RFC2451]" },
|
|
|
|
{ IPSEC_ENCRYPT_TWOFISH_CBC, "TWOFISH-CBC" },
|
2013-02-25 22:19:15 +00:00
|
|
|
{ IPSEC_ENCRYPT_AES_GCM, "AES-GCM [RFC4106]" },
|
2011-06-02 07:11:26 +00:00
|
|
|
{ 0x00, NULL }
|
2006-03-27 16:25:35 +00:00
|
|
|
};
|
|
|
|
|
2011-06-02 07:11:26 +00:00
|
|
|
static const value_string esp_authentication_type_vals[] = {
|
|
|
|
{ IPSEC_AUTH_NULL, "NULL" },
|
|
|
|
{ IPSEC_AUTH_HMAC_SHA1_96, "HMAC-SHA-1-96 [RFC2404]" },
|
|
|
|
{ IPSEC_AUTH_HMAC_SHA256_96, "HMAC-SHA-256-96 [draft-ietf-ipsec-ciph-sha-256-00]" },
|
|
|
|
{ IPSEC_AUTH_HMAC_SHA256_128, "HMAC-SHA-256-128 [RFC4868]" },
|
2012-10-22 12:34:01 +00:00
|
|
|
{ IPSEC_AUTH_HMAC_SHA384_192, "HMAC-SHA-384-192 [RFC4868]" },
|
|
|
|
{ IPSEC_AUTH_HMAC_SHA512_256, "HMAC-SHA-512-256 [RFC4868]" },
|
2011-06-02 07:11:26 +00:00
|
|
|
{ IPSEC_AUTH_HMAC_MD5_96, "HMAC-MD5-96 [RFC2403]" },
|
|
|
|
{ IPSEC_AUTH_HMAC_RIPEMD160_96, "MAC-RIPEMD-160-96 [RFC2857]" },
|
|
|
|
/* { IPSEC_AUTH_AES_XCBC_MAC_96, "AES-XCBC-MAC-96 [RFC3566]" }, */
|
2013-12-08 02:27:52 +00:00
|
|
|
{ IPSEC_AUTH_ANY_64BIT, "ANY 64 bit authentication [no checking]" },
|
2011-06-02 07:11:26 +00:00
|
|
|
{ IPSEC_AUTH_ANY_96BIT, "ANY 96 bit authentication [no checking]" },
|
|
|
|
{ IPSEC_AUTH_ANY_128BIT, "ANY 128 bit authentication [no checking]" },
|
|
|
|
{ IPSEC_AUTH_ANY_192BIT, "ANY 192 bit authentication [no checking]" },
|
|
|
|
{ IPSEC_AUTH_ANY_256BIT, "ANY 256 bit authentication [no checking]" },
|
|
|
|
{ 0x00, NULL }
|
2006-03-27 16:25:35 +00:00
|
|
|
};
|
2011-06-02 07:11:26 +00:00
|
|
|
|
|
|
|
static uat_field_t esp_uat_flds[] = {
|
2011-10-21 02:10:19 +00:00
|
|
|
UAT_FLD_VS(uat_esp_sa_records, protocol, "Protocol", esp_proto_type_vals, "Protocol used"),
|
2011-06-02 07:11:26 +00:00
|
|
|
UAT_FLD_CSTRING(uat_esp_sa_records, srcIP, "Src IP", "Source Address"),
|
|
|
|
UAT_FLD_CSTRING(uat_esp_sa_records, dstIP, "Dest IP", "Destination Address"),
|
|
|
|
UAT_FLD_CSTRING(uat_esp_sa_records, spi, "SPI", "SPI"),
|
2011-10-21 02:10:19 +00:00
|
|
|
UAT_FLD_VS(uat_esp_sa_records, encryption_algo, "Encryption", esp_encryption_type_vals, "Encryption algorithm"),
|
2014-04-28 21:29:53 +00:00
|
|
|
UAT_FLD_CSTRING(uat_esp_sa_records, encryption_key_string, "Encryption Key", "Encryption Key"),
|
2011-10-21 02:10:19 +00:00
|
|
|
UAT_FLD_VS(uat_esp_sa_records, authentication_algo, "Authentication", esp_authentication_type_vals, "Authentication algorithm"),
|
2014-04-28 21:29:53 +00:00
|
|
|
UAT_FLD_CSTRING(uat_esp_sa_records, authentication_key_string, "Authentication Key", "Authentication Key"),
|
2011-06-02 07:11:26 +00:00
|
|
|
UAT_END_FIELDS
|
|
|
|
};
|
2006-03-27 16:25:35 +00:00
|
|
|
#endif
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
module_t *ah_module;
|
|
|
|
module_t *esp_module;
|
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
expert_module_t* expert_esp;
|
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
proto_ah = proto_register_protocol("Authentication Header", "AH", "ah");
|
|
|
|
proto_register_field_array(proto_ah, hf_ah, array_length(hf_ah));
|
|
|
|
|
|
|
|
proto_esp = proto_register_protocol("Encapsulating Security Payload",
|
2014-04-30 17:25:12 +00:00
|
|
|
"ESP", "esp");
|
2006-06-14 08:04:43 +00:00
|
|
|
proto_register_field_array(proto_esp, hf_esp, array_length(hf_esp));
|
|
|
|
|
|
|
|
proto_ipcomp = proto_register_protocol("IP Payload Compression",
|
2014-04-30 17:25:12 +00:00
|
|
|
"IPComp", "ipcomp");
|
2006-06-14 08:04:43 +00:00
|
|
|
proto_register_field_array(proto_ipcomp, hf_ipcomp, array_length(hf_ipcomp));
|
|
|
|
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
expert_esp = expert_register_protocol(proto_esp);
|
|
|
|
expert_register_field_array(expert_esp, ei, array_length(ei));
|
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
/* Register a configuration option for placement of AH payload dissection */
|
|
|
|
ah_module = prefs_register_protocol(proto_ah, NULL);
|
|
|
|
prefs_register_bool_preference(ah_module, "place_ah_payload_in_subtree",
|
2014-04-30 17:25:12 +00:00
|
|
|
"Place AH payload in subtree",
|
|
|
|
"Whether the AH payload decode should be placed in a subtree",
|
|
|
|
&g_ah_payload_in_subtree);
|
2004-11-12 10:03:53 +00:00
|
|
|
esp_module = prefs_register_protocol(proto_esp, NULL);
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2004-11-12 10:03:53 +00:00
|
|
|
prefs_register_bool_preference(esp_module, "enable_null_encryption_decode_heuristic",
|
2014-04-30 17:25:12 +00:00
|
|
|
"Attempt to detect/decode NULL encrypted ESP payloads",
|
|
|
|
"This is done only if the Decoding is not SET or the packet does not belong to a SA. "
|
2009-08-26 19:30:44 +00:00
|
|
|
"Assumes a 12 byte auth (HMAC-SHA1-96/HMAC-MD5-96/AES-XCBC-MAC-96) "
|
|
|
|
"and attempts decode based on the ethertype 13 bytes from packet end",
|
2014-04-30 17:25:12 +00:00
|
|
|
&g_esp_enable_null_encryption_decode_heuristic);
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-09-09 22:26:31 +00:00
|
|
|
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",
|
|
|
|
&g_esp_do_sequence_analysis);
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2006-06-14 08:04:43 +00:00
|
|
|
#ifdef HAVE_LIBGCRYPT
|
2006-03-27 16:25:35 +00:00
|
|
|
prefs_register_bool_preference(esp_module, "enable_encryption_decode",
|
2014-04-30 17:25:12 +00:00
|
|
|
"Attempt to detect/decode encrypted ESP payloads",
|
|
|
|
"Attempt to decode based on the SAD described hereafter.",
|
|
|
|
&g_esp_enable_encryption_decode);
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2006-04-13 22:26:13 +00:00
|
|
|
prefs_register_bool_preference(esp_module, "enable_authentication_check",
|
2014-04-30 17:25:12 +00:00
|
|
|
"Attempt to Check ESP Authentication",
|
|
|
|
"Attempt to Check ESP Authentication based on the SAD described hereafter.",
|
|
|
|
&g_esp_enable_authentication_check);
|
2006-04-13 22:26:13 +00:00
|
|
|
|
UATs could be put into "categories". The categories were defined only
implicitly by the #define name and string they were defined to; not all
UATs neatly fit into any of the categories, so some of them were put
into categories that weren't obviously correct for them, and one - the
display filter macro UAT - wasn't put into any category at all (which
caused crashes when editing them, as the GUI code that handled UAT
changes from a dialog assumed the category field was non-null).
The category was, in practice, used only to decide, in the
aforementioned GUI code, whether the packet summary pane needed to be
updated or not. It also offered no option of "don't update the packet
summary pane *and* don't redissect anything", which is what would be
appropriate for the display filter macro UAT.
Replace the category with a set of fields indicating what the UAT
affects; we currently offer "dissection", which applies to most UATs
(any UAT in libwireshark presumably affects dissection at a minimum) and
"the set of named fields that exist". Changing any UAT that affects
dissection requires a redissection; changing any UAT that affects the
set of named fields that exist requires a redissection *and* rebuilding
the packet summary pane.
Perhaps we also need "filtering", so that if you change a display filter
macro, we re-filter, in case the display is currently filtered with a
display filter that uses a macro that changed.
svn path=/trunk/; revision=43603
2012-07-08 01:00:46 +00:00
|
|
|
esp_uat = uat_new("ESP SAs",
|
|
|
|
sizeof(uat_esp_sa_record_t), /* record size */
|
|
|
|
"esp_sa", /* filename */
|
|
|
|
TRUE, /* from_profile */
|
2014-01-30 17:43:52 +00:00
|
|
|
&uat_esp_sa_records, /* data_ptr */
|
UATs could be put into "categories". The categories were defined only
implicitly by the #define name and string they were defined to; not all
UATs neatly fit into any of the categories, so some of them were put
into categories that weren't obviously correct for them, and one - the
display filter macro UAT - wasn't put into any category at all (which
caused crashes when editing them, as the GUI code that handled UAT
changes from a dialog assumed the category field was non-null).
The category was, in practice, used only to decide, in the
aforementioned GUI code, whether the packet summary pane needed to be
updated or not. It also offered no option of "don't update the packet
summary pane *and* don't redissect anything", which is what would be
appropriate for the display filter macro UAT.
Replace the category with a set of fields indicating what the UAT
affects; we currently offer "dissection", which applies to most UATs
(any UAT in libwireshark presumably affects dissection at a minimum) and
"the set of named fields that exist". Changing any UAT that affects
dissection requires a redissection; changing any UAT that affects the
set of named fields that exist requires a redissection *and* rebuilding
the packet summary pane.
Perhaps we also need "filtering", so that if you change a display filter
macro, we re-filter, in case the display is currently filtered with a
display filter that uses a macro that changed.
svn path=/trunk/; revision=43603
2012-07-08 01:00:46 +00:00
|
|
|
&num_sa_uat, /* numitems_ptr */
|
|
|
|
UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
|
|
|
|
NULL, /* help */
|
2011-10-27 19:20:39 +00:00
|
|
|
uat_esp_sa_record_copy_cb, /* copy callback */
|
2014-04-28 21:29:53 +00:00
|
|
|
uat_esp_sa_record_update_cb, /* update callback */
|
2011-10-27 19:20:39 +00:00
|
|
|
uat_esp_sa_record_free_cb, /* free callback */
|
UATs could be put into "categories". The categories were defined only
implicitly by the #define name and string they were defined to; not all
UATs neatly fit into any of the categories, so some of them were put
into categories that weren't obviously correct for them, and one - the
display filter macro UAT - wasn't put into any category at all (which
caused crashes when editing them, as the GUI code that handled UAT
changes from a dialog assumed the category field was non-null).
The category was, in practice, used only to decide, in the
aforementioned GUI code, whether the packet summary pane needed to be
updated or not. It also offered no option of "don't update the packet
summary pane *and* don't redissect anything", which is what would be
appropriate for the display filter macro UAT.
Replace the category with a set of fields indicating what the UAT
affects; we currently offer "dissection", which applies to most UATs
(any UAT in libwireshark presumably affects dissection at a minimum) and
"the set of named fields that exist". Changing any UAT that affects
dissection requires a redissection; changing any UAT that affects the
set of named fields that exist requires a redissection *and* rebuilding
the packet summary pane.
Perhaps we also need "filtering", so that if you change a display filter
macro, we re-filter, in case the display is currently filtered with a
display filter that uses a macro that changed.
svn path=/trunk/; revision=43603
2012-07-08 01:00:46 +00:00
|
|
|
NULL, /* post update callback */
|
|
|
|
esp_uat_flds); /* UAT field definitions */
|
|
|
|
|
|
|
|
prefs_register_uat_preference(esp_module,
|
|
|
|
"sa_table",
|
|
|
|
"ESP SAs",
|
|
|
|
"Preconfigured ESP Security Associations",
|
|
|
|
esp_uat);
|
2014-09-12 13:56:29 +00:00
|
|
|
#endif
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2014-04-30 14:45:47 +00:00
|
|
|
register_init_routine(&ipsec_init_protocol);
|
2004-11-12 10:03:53 +00:00
|
|
|
|
2001-08-29 08:12:32 +00:00
|
|
|
register_dissector("esp", dissect_esp, proto_esp);
|
2001-08-30 02:23:17 +00:00
|
|
|
register_dissector("ah", dissect_ah, proto_ah);
|
1999-07-29 05:47:07 +00:00
|
|
|
}
|
2000-04-16 22:46:25 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_ipsec(void)
|
|
|
|
{
|
2014-04-28 23:42:42 +00:00
|
|
|
dissector_handle_t esp_handle, ah_handle, ipv6_ah_handle, ipcomp_handle;
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2001-11-26 04:52:51 +00:00
|
|
|
data_handle = find_dissector("data");
|
2001-12-03 04:00:26 +00:00
|
|
|
ah_handle = find_dissector("ah");
|
2010-12-20 05:35:29 +00:00
|
|
|
dissector_add_uint("ip.proto", IP_PROTO_AH, ah_handle);
|
2001-12-03 04:00:26 +00:00
|
|
|
esp_handle = find_dissector("esp");
|
2010-12-20 05:35:29 +00:00
|
|
|
dissector_add_uint("ip.proto", IP_PROTO_ESP, esp_handle);
|
2001-12-03 04:00:26 +00:00
|
|
|
ipcomp_handle = create_dissector_handle(dissect_ipcomp, proto_ipcomp);
|
2010-12-20 05:35:29 +00:00
|
|
|
dissector_add_uint("ip.proto", IP_PROTO_IPCOMP, ipcomp_handle);
|
2014-04-28 23:42:42 +00:00
|
|
|
ipv6_ah_handle = new_create_dissector_handle(dissect_ah_header, proto_ah );
|
|
|
|
dissector_add_uint("ipv6.nxt", IP_PROTO_AH, ipv6_ah_handle);
|
2006-08-09 02:00:05 +00:00
|
|
|
|
2003-04-29 17:24:35 +00:00
|
|
|
ip_dissector_table = find_dissector_table("ip.proto");
|
2006-03-27 16:25:35 +00:00
|
|
|
|
2013-06-18 23:01:46 +00:00
|
|
|
exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_3);
|
|
|
|
}
|
2014-04-30 17:25:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Editor modelines
|
|
|
|
*
|
|
|
|
* Local Variables:
|
|
|
|
* c-basic-offset: 2
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* ex: set shiftwidth=2 tabstop=8 expandtab:
|
|
|
|
* :indentSize=2:tabSize=8:noTabs=true:
|
|
|
|
*/
|