diff options
author | wmeier <wmeier@f5534014-38df-0310-8fa8-9805f1628bb7> | 2011-11-25 22:02:25 +0000 |
---|---|---|
committer | wmeier <wmeier@f5534014-38df-0310-8fa8-9805f1628bb7> | 2011-11-25 22:02:25 +0000 |
commit | d98ecffd767a4d9a79ac0c1f9615e8dc36ee9b88 (patch) | |
tree | 4fc1f69bd479e9441cfc26ae1225eb6241aceea5 | |
parent | 052be28fa6c8d6ef66e765983c00b3a1d6d9e096 (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-- | AUTHORS | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee802154.c | 174 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee802154.h | 2 |
3 files changed, 126 insertions, 54 deletions
@@ -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; |