aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwmeier <wmeier@f5534014-38df-0310-8fa8-9805f1628bb7>2011-11-25 22:02:25 +0000
committerwmeier <wmeier@f5534014-38df-0310-8fa8-9805f1628bb7>2011-11-25 22:02:25 +0000
commitd98ecffd767a4d9a79ac0c1f9615e8dc36ee9b88 (patch)
tree4fc1f69bd479e9441cfc26ae1225eb6241aceea5
parent052be28fa6c8d6ef66e765983c00b3a1d6d9e096 (diff)
From Ivan Lawrow: Added IEEE 802.15.4-2003 AES-CCM security modes
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4912 git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@40004 f5534014-38df-0310-8fa8-9805f1628bb7
-rw-r--r--AUTHORS4
-rw-r--r--epan/dissectors/packet-ieee802154.c174
-rw-r--r--epan/dissectors/packet-ieee802154.h2
3 files changed, 126 insertions, 54 deletions
diff --git a/AUTHORS b/AUTHORS
index 20cd728aa2..c93be10157 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3350,6 +3350,10 @@ Mariusz Okrój <okrojmariusz [AT]gmail.com> {
XMPP enhancements
}
+Ivan Lawrow <ivan.lawrow [AT] jennic.com> {
+ Added IEEE 802.15.4-2003 AES-CCM security modes
+}
+
and by:
diff --git a/epan/dissectors/packet-ieee802154.c b/epan/dissectors/packet-ieee802154.c
index 6bbc459813..179327f78b 100644
--- a/epan/dissectors/packet-ieee802154.c
+++ b/epan/dissectors/packet-ieee802154.c
@@ -162,10 +162,6 @@ UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
*/
/* Register Functions. Loads the dissector into Wireshark. */
void proto_reg_handoff_ieee802154 (void);
-void proto_register_ieee802154 (void);
-
-static void proto_init_ieee802154 (void);
-/* TODO: cleanup. */
/* Dissection Routines. */
static void dissect_ieee802154_nonask_phy (tvbuff_t *, packet_info *, proto_tree *);
@@ -200,7 +196,7 @@ typedef enum {
static tvbuff_t * dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *,
ws_decrypt_status *);
-static void ccm_init_block (gchar *, gboolean, gint, guint64, guint32, ieee802154_security_level, gint);
+static void ccm_init_block (gchar *, gboolean, gint, guint64, ieee802154_packet *, gint);
static gboolean ccm_ctr_encrypt (const gchar *, const gchar *, gchar *, gchar *, gint);
static gboolean ccm_cbc_mac (const gchar *, const gchar *, const gchar *, gint, const gchar *, gint, gchar *);
@@ -273,6 +269,10 @@ static int hf_ieee802154_aux_sec_frame_counter = -1;
static int hf_ieee802154_aux_sec_key_source = -1;
static int hf_ieee802154_aux_sec_key_index = -1;
+/* 802.15.4-2003 security */
+static int hf_ieee802154_sec_frame_counter = -1;
+static int hf_ieee802154_sec_key_sequence_counter = -1;
+
/* Initialize Subtree Pointers */
static gint ett_ieee802154_nonask_phy = -1;
static gint ett_ieee802154_nonask_phy_phr = -1;
@@ -347,8 +347,25 @@ static const true_false_string ieee802154_gts_direction_tfs = {
"Transmit Only"
};
+/* The 802.15.4-2003 security suites for the security preferences (only AES-CCM suites are supported). */
+/* NOTE: The equivalent 2006 security level identifer enumerations are used to simplify 2003 & 2006 integration! */
+static enum_val_t ieee802154_2003_sec_suite_enums[] = {
+ { "AES-CCM-128", "AES-128 Encryption, 128-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_128 },
+ { "AES-CCM-64", "AES-128 Encryption, 64-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_64 },
+ { "AES-CCM-32", "AES-128 Encryption, 32-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_32 },
+ { NULL, NULL, 0 }
+};
+
+/* Preferences for 2003 security */
+static gint ieee802154_sec_suite = SECURITY_LEVEL_ENC_MIC_64;
+static gboolean ieee802154_extend_auth = TRUE;
+
/* Macro to check addressing, and throw a warning flag if incorrect. */
-#define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_) if (!(_x_)) expert_add_info_format(_pinfo_, _item_, PI_MALFORMED, PI_WARN, "Invalid Addressing for %s", val_to_str(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
+#define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_) \
+ if (!(_x_)) \
+ expert_add_info_format(_pinfo_, _item_, PI_MALFORMED, PI_WARN, \
+ "Invalid Addressing for %s", \
+ val_to_str(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
/* CRC definitions. IEEE 802.15.4 CRCs vary from CCITT by using an initial value of
* 0x0000, and no XOR out. IEEE802154_CRC_XOR is defined as 0xFFFF in order to un-XOR
@@ -968,6 +985,23 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
* PAYLOAD DISSECTION
*=====================================================
*/
+ /* IEEE 802.15.4-2003 may have security information pre-pended to payload */
+ if (packet->security_enable && (packet->version == IEEE802154_VERSION_2003)) {
+ /* Store security suite preference in the 2006 security level identifier to simplify 2003 integration! */
+ packet->security_level = ieee802154_sec_suite;
+
+ /* Frame Counter and Key Sequence Counter prepended to the payload of an encrypted frame */
+ if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
+ packet->frame_counter = tvb_get_letohl (tvb, offset);
+ proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_frame_counter, tvb, offset, sizeof(guint32), packet->frame_counter);
+ offset += sizeof(guint32);
+
+ packet->key_sequence_counter = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_key_sequence_counter, tvb, offset, sizeof(guint8), packet->key_sequence_counter);
+ offset += sizeof(guint8);
+ }
+ }
+
/* Encrypted Payload. */
if (packet->security_enable) {
payload_tvb = dissect_ieee802154_decrypt(tvb, offset, pinfo, packet, &status);
@@ -1766,13 +1800,13 @@ dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ie
ieee802154_hints_t *ieee_hints;
/*
- * Check the version; we only support IEEE 802.15.4-2006.
- * We must do this first, as, if this isn't IEEE 802.15.4-2006,
+ * Check the version; we only support IEEE 802.15.4-2003 and IEEE 802.15.4-2006.
+ * We must do this first, as, if this isn't IEEE 802.15.4-2003 or IEEE 802.15.4-2006,
* we don't have the Auxiliary Security Header, and haven't
* filled in the information for it, and none of the stuff
* we do afterwards, which uses that information, is doable.
*/
- if (packet->version != IEEE802154_VERSION_2006) {
+ if ((packet->version != IEEE802154_VERSION_2006) && (packet->version != IEEE802154_VERSION_2003)) {
*status = DECRYPT_VERSION_UNSUPPORTED;
return NULL;
}
@@ -1845,7 +1879,7 @@ dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ie
*=====================================================
*/
/* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
- ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->security_level, 0);
+ ccm_init_block(tmp, FALSE, 0, srcAddr, packet, 0);
/* Decrypt the ciphertext, and place the plaintext in a new tvb. */
if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
@@ -1899,9 +1933,12 @@ dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ie
l_a += l_m;
l_m = 0;
}
+ else if ((packet->version == IEEE802154_VERSION_2003) && !ieee802154_extend_auth)
+ l_a -= 5; /* Exclude Frame Counter (4 bytes) and Key Sequence Counter (1 byte) from authentication data
+
/* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
- ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->security_level, l_m);
+ ccm_init_block(tmp, TRUE, M, srcAddr, packet, l_m);
/* Compute CBC-MAC authentication tag. */
/*
@@ -1934,15 +1971,14 @@ dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ie
* gboolean adata - TRUE if additional auth data is present
* gint M - CCM* parameter M.
* guint64 addr - Source extended address.
- * guint32 counter - Frame counter.
- * ieee802154_security_level level - Security leve being used.
+ * ieee802154_packet *packet - IEEE 802.15.4 packet information.
* guint16 ctr_val - Value in the last L bytes of the block.
* RETURNS
* void
*---------------------------------------------------------------
*/
static void
-ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, guint32 counter, ieee802154_security_level level, gint ctr_val)
+ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, ieee802154_packet * packet, gint ctr_val)
{
gint i = 0;
@@ -1951,7 +1987,8 @@ ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, guint32 count
if (M > 0) block[i] |= (((M-2)/2) << 3); /* (M-2)/2 */
if (adata) block[i] |= (1 << 6); /* Adata */
i++;
- /* Nonce: Source Address || Frame Counter || Security Level */
+ /* 2003 CCM Nonce: Source Address || Frame Counter || Key Sequence Counter */
+ /* 2006 CCM* Nonce: Source Address || Frame Counter || Security Level */
block[i++] = (guint8)((addr >> 56) & 0xff);
block[i++] = (guint8)((addr >> 48) & 0xff);
block[i++] = (guint8)((addr >> 40) & 0xff);
@@ -1960,11 +1997,14 @@ ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, guint32 count
block[i++] = (guint8)((addr >> 16) & 0xff);
block[i++] = (guint8)((addr >> 8) & 0xff);
block[i++] = (guint8)((addr >> 0) & 0xff);
- block[i++] = (guint8)((counter >> 24) & 0xff);
- block[i++] = (guint8)((counter >> 16) & 0xff);
- block[i++] = (guint8)((counter >> 8) & 0xff);
- block[i++] = (guint8)((counter >> 0) & 0xff);
- block[i++] = level;
+ block[i++] = (guint8)((packet->frame_counter >> 24) & 0xff);
+ block[i++] = (guint8)((packet->frame_counter >> 16) & 0xff);
+ block[i++] = (guint8)((packet->frame_counter >> 8) & 0xff);
+ block[i++] = (guint8)((packet->frame_counter >> 0) & 0xff);
+ if (packet->version == IEEE802154_VERSION_2003)
+ block[i++] = packet->key_sequence_counter;
+ else
+ block[i++] = packet->security_level;
/* Plaintext length. */
block[i++] = (guint8)((ctr_val >> 8) & 0xff);
block[i++] = (guint8)((ctr_val >> 0) & 0xff);
@@ -2303,6 +2343,42 @@ gboolean ieee802154_long_addr_invalidate(guint64 long_addr, guint fnum)
/*FUNCTION:------------------------------------------------------
* NAME
+ * proto_init_ieee802154
+ * DESCRIPTION
+ * Init routine for the IEEE 802.15.4 dissector. Creates hash
+ * tables for mapping between 16-bit to 64-bit addresses and
+ * populates them with static address pairs from a UAT
+ * preference table.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+static void
+proto_init_ieee802154(void)
+{
+ guint i;
+
+ /* Destroy hash tables, if they exist. */
+ if (ieee802154_map.short_table)
+ g_hash_table_destroy(ieee802154_map.short_table);
+ if (ieee802154_map.long_table)
+ g_hash_table_destroy(ieee802154_map.long_table);
+
+ /* Create the hash tables. */
+ ieee802154_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
+ ieee802154_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
+ /* Re-load the hash table from the static address UAT. */
+ for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
+ ieee802154_addr_update(&ieee802154_map,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
+ pntoh64(static_addrs[i].eui64), ieee802154_user, IEEE802154_USER_MAPPING);
+ } /* for */
+} /* proto_init_ieee802154 */
+
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
* proto_register_ieee802154
* DESCRIPTION
* IEEE 802.15.4 protocol registration routine.
@@ -2562,7 +2638,16 @@ void proto_register_ieee802154(void)
{ &hf_ieee802154_aux_sec_key_index,
{ "Key Index", "wpan.aux_sec.key_index", FT_UINT8, BASE_HEX, NULL, 0x0,
- "Key Index for processing of the protected frame", HFILL }}
+ "Key Index for processing of the protected frame", HFILL }},
+
+ /* IEEE 802.15.4-2003 Security Header Fields */
+ { &hf_ieee802154_sec_frame_counter,
+ { "Frame Counter", "wpan.sec_frame_counter", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Frame counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
+
+ { &hf_ieee802154_sec_key_sequence_counter,
+ { "Key Sequence Counter", "wpan.sec_key_sequence_counter", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Key Sequence counter of the originator of the protected frame (802.15.4-2003)", HFILL }}
};
/* Subtrees */
@@ -2651,6 +2736,19 @@ void proto_register_ieee802154(void)
prefs_register_string_preference(ieee802154_module, "802154_key", "Decryption key",
"128-bit decryption key in hexadecimal format", (const char **)&ieee802154_key_str);
+ prefs_register_enum_preference(ieee802154_module, "802154_sec_suite",
+ "Security Suite (802.15.4-2003)",
+ "Specifies the security suite to use for 802.15.4-2003 secured frames"
+ " (only supported suites are listed). Option ignored for 802.15.4-2006"
+ " and unsecured frames.",
+ &ieee802154_sec_suite, ieee802154_2003_sec_suite_enums, FALSE);
+
+ prefs_register_bool_preference(ieee802154_module, "802154_extend_auth",
+ "Extend authentication data (802.15.4-2003)",
+ "Set if the manufacturer extends the authentication data with the"
+ " security header. Option ignored for 802.15.4-2006 and unsecured frames.",
+ &ieee802154_extend_auth);
+
/* Register the subdissector list */
register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN, &ieee802154_heur_subdissector_list);
@@ -2661,6 +2759,7 @@ void proto_register_ieee802154(void)
register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
} /* proto_register_ieee802154 */
+
/*FUNCTION:------------------------------------------------------
* NAME
* proto_reg_handoff_ieee802154
@@ -2714,36 +2813,3 @@ void proto_reg_handoff_ieee802154(void)
/* Register dissector handles. */
dissector_add_uint("ethertype", ieee802154_ethertype, ieee802154_handle);
} /* proto_reg_handoff_ieee802154 */
-
-/*FUNCTION:------------------------------------------------------
- * NAME
- * proto_init_ieee802154
- * DESCRIPTION
- * Init routine for the IEEE 802.15.4 dissector. Creates hash
- * tables for mapping between 16-bit to 64-bit addresses and
- * populates them with static address pairs from a UAT
- * preference table.
- * PARAMETERS
- * none
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
-static void
-proto_init_ieee802154(void)
-{
- guint i;
-
- /* Destroy hash tables, if they exist. */
- if (ieee802154_map.short_table) g_hash_table_destroy(ieee802154_map.short_table);
- if (ieee802154_map.long_table) g_hash_table_destroy(ieee802154_map.long_table);
-
- /* Create the hash tables. */
- ieee802154_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
- ieee802154_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
- /* Re-load the hash table from the static address UAT. */
- for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
- ieee802154_addr_update(&ieee802154_map,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
- pntoh64(static_addrs[i].eui64), ieee802154_user, IEEE802154_USER_MAPPING);
- } /* for */
-} /* proto_init_ieee802154 */
diff --git a/epan/dissectors/packet-ieee802154.h b/epan/dissectors/packet-ieee802154.h
index acbdc5aa84..786268025a 100644
--- a/epan/dissectors/packet-ieee802154.h
+++ b/epan/dissectors/packet-ieee802154.h
@@ -193,6 +193,8 @@ typedef struct {
ieee802154_security_level security_level;
ieee802154_key_id_mode key_id_mode;
guint32 frame_counter;
+ guint8 key_sequence_counter; /* Only for 802.15.4-2003 security suite with encryption */
+
union {
guint32 addr32;
guint64 addr64;