summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docbook/release-notes.asciidoc2
-rw-r--r--epan/dissectors/packet-ieee802154.c559
-rw-r--r--epan/dissectors/packet-ieee802154.h57
3 files changed, 448 insertions, 170 deletions
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc
index eac41b9872..472a414cf1 100644
--- a/docbook/release-notes.asciidoc
+++ b/docbook/release-notes.asciidoc
@@ -46,6 +46,8 @@ since version 2.2.0:
additional printf-style APIs.
* The Default profile can now be reset to default values.
* You can move back and forth in the selection history in the Qt UI.
+* IEEE 802.15.4 dissector now uses an UAT for decryption keys. The original
+ decryption key preference has been obsoleted.
//=== Removed Dissectors
diff --git a/epan/dissectors/packet-ieee802154.c b/epan/dissectors/packet-ieee802154.c
index ea12d2c312..ee7d326dcb 100644
--- a/epan/dissectors/packet-ieee802154.c
+++ b/epan/dissectors/packet-ieee802154.c
@@ -58,8 +58,6 @@
/* Include files */
#include "config.h"
-
-
#include <epan/packet.h>
#include <epan/decode_as.h>
#include <epan/exceptions.h>
@@ -73,7 +71,6 @@
#include <epan/to_str.h>
#include <epan/show_exception.h>
#include <epan/proto_data.h>
-
#include <wsutil/pint.h>
/* Use libgcrypt for cipher libraries. */
@@ -99,17 +96,15 @@ static gboolean ieee802154_cc24xx = FALSE;
/* boolean value set if the FCS must be ok before payload is dissected */
static gboolean ieee802154_fcs_ok = TRUE;
-/* User string with the decryption key. */
-static const gchar *ieee802154_key_str = NULL;
-static gboolean ieee802154_key_valid;
-static guint8 ieee802154_key[IEEE802154_CIPHER_SIZE];
static const char *ieee802154_user = "User";
+static wmem_tree_t* mac_key_hash_handlers;
+
/*
* Address Hash Tables
*
*/
-static ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
+ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
/*
* Static Address Mapping UAT
@@ -156,6 +151,111 @@ UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
+/*
+ * Key Decryption UAT
+ *
+ */
+
+/* UAT variables */
+static uat_t *ieee802154_key_uat = NULL;
+static ieee802154_key_t *ieee802154_keys = NULL;
+static guint num_ieee802154_keys = 0;
+
+static void ieee802154_key_post_update_cb(void)
+{
+ guint i;
+ GByteArray *bytes;
+
+ for (i = 0; i < num_ieee802154_keys; i++)
+ {
+ switch (ieee802154_keys[i].hash_type) {
+ case KEY_HASH_NONE:
+ case KEY_HASH_ZIP:
+ /* Get the IEEE 802.15.4 decryption key. */
+ bytes = g_byte_array_new();
+ if (hex_str_to_bytes(ieee802154_keys[i].pref_key, bytes, FALSE))
+ {
+ if (ieee802154_keys[i].hash_type == KEY_HASH_ZIP) {
+ char digest[32];
+
+ if (!ws_hmac_buffer(GCRY_MD_SHA256, digest, "ZigBeeIP", 8, bytes->data, IEEE802154_CIPHER_SIZE)) {
+ /* Copy upper hashed bytes to the key */
+ memcpy(ieee802154_keys[i].key, &digest[IEEE802154_CIPHER_SIZE], IEEE802154_CIPHER_SIZE);
+ /* Copy lower hashed bytes to the MLE key */
+ memcpy(ieee802154_keys[i].mle_key, digest, IEEE802154_CIPHER_SIZE);
+ } else {
+ /* Just copy the keys verbatim */
+ memcpy(ieee802154_keys[i].key, bytes->data, IEEE802154_CIPHER_SIZE);
+ memcpy(ieee802154_keys[i].mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
+ }
+ } else {
+ /* Just copy the keys verbatim */
+ memcpy(ieee802154_keys[i].key, bytes->data, IEEE802154_CIPHER_SIZE);
+ memcpy(ieee802154_keys[i].mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
+ }
+ }
+ g_byte_array_free(bytes, TRUE);
+ break;
+ case KEY_HASH_THREAD:
+ /* XXX - TODO? */
+ break;
+ }
+ }
+}
+
+static gboolean ieee802154_key_update_cb(void *r, char **err)
+{
+ ieee802154_key_t* rec = (ieee802154_key_t*)r;
+ GByteArray *bytes;
+
+ switch (rec->hash_type) {
+ case KEY_HASH_NONE:
+ case KEY_HASH_ZIP:
+ bytes = g_byte_array_new();
+ if (hex_str_to_bytes(rec->pref_key, bytes, FALSE) == FALSE)
+ {
+ *err = g_strdup("Invalid key");
+ g_byte_array_free(bytes, TRUE);
+ return FALSE;
+ }
+
+ if (bytes->len < IEEE802154_CIPHER_SIZE)
+ {
+ *err = g_strdup_printf("Key must be at least %d bytes", IEEE802154_CIPHER_SIZE);
+ g_byte_array_free(bytes, TRUE);
+ return FALSE;
+ }
+ g_byte_array_free(bytes, TRUE);
+ break;
+ case KEY_HASH_THREAD:
+ /* XXX - TODO? */
+ break;
+ }
+
+ return TRUE;
+}
+
+static void* ieee802154_key_copy_cb(void* n, const void* o, size_t siz _U_) {
+ ieee802154_key_t* new_record = (ieee802154_key_t*)n;
+ const ieee802154_key_t* old_record = (const ieee802154_key_t*)o;
+
+ new_record->pref_key = g_strdup(old_record->pref_key);
+
+ return new_record;
+}
+
+static void ieee802154_key_free_cb(void*r) {
+ ieee802154_key_t* rec = (ieee802154_key_t *)r;
+
+ g_free(rec->pref_key);
+}
+
+/* Field callbacks. */
+UAT_CSTRING_CB_DEF(key_uat, pref_key, ieee802154_key_t)
+UAT_DEC_CB_DEF(key_uat, key_index, ieee802154_key_t)
+UAT_VS_DEF(key_uat, hash_type, ieee802154_key_t, ieee802154_key_hash, KEY_HASH_NONE, "No hash")
+
+
/*-------------------------------------
* Dissector Function Prototypes
*-------------------------------------
@@ -190,22 +290,9 @@ static void dissect_ieee802154_realign (tvbuff_t *, packet_info *, proto
static void dissect_ieee802154_gtsreq (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
/* Decryption helpers. */
-typedef enum {
- DECRYPT_PACKET_SUCCEEDED,
- DECRYPT_NOT_ENCRYPTED,
- DECRYPT_VERSION_UNSUPPORTED,
- DECRYPT_PACKET_TOO_SMALL,
- DECRYPT_PACKET_NO_EXT_SRC_ADDR,
- DECRYPT_PACKET_NO_KEY,
- DECRYPT_PACKET_DECRYPT_FAILED,
- DECRYPT_PACKET_MIC_CHECK_FAILED
-} ws_decrypt_status;
-
-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, 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 *);
+static tvbuff_t *dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *, ieee802154_payload_info_t*);
+
+static gboolean ieee802154_set_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t* uat_key);
/* Initialize Protocol and Registered fields */
static int proto_ieee802154_nonask_phy = -1;
@@ -343,13 +430,17 @@ static int hf_ieee802154_pending16 = -1;
static int hf_ieee802154_pending64 = -1;
/* Registered fields for Auxiliary Security Header */
+static int hf_ieee802154_aux_security_header = -1;
static int hf_ieee802154_security_control_field = -1;
static int hf_ieee802154_security_level = -1;
static int hf_ieee802154_key_id_mode = -1;
static int hf_ieee802154_aux_sec_reserved = -1;
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_source_bytes = -1;
static int hf_ieee802154_aux_sec_key_index = -1;
+static int hf_ieee802154_mic = -1;
+static int hf_ieee802154_key_number = -1;
/* 802.15.4-2003 security */
static int hf_ieee802154_sec_frame_counter = -1;
@@ -517,6 +608,14 @@ static const enum_val_t ieee802154_2003_sec_suite_enums[] = {
{ NULL, NULL, 0 }
};
+/* Enumeration for key generation */
+static const value_string ieee802154_key_hash_vals[] = {
+ { KEY_HASH_NONE, "No hash"},
+ { KEY_HASH_ZIP, "ZigBee IP hash" },
+ { KEY_HASH_THREAD, "Thread hash" },
+ { 0, NULL }
+};
+
static const value_string ieee802154_ie_types[] = {
{ 0, "Header" },
{ 1, "Payload" },
@@ -760,6 +859,114 @@ dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee
*offset += 2;
} /* dissect_ieee802154_fcf */
+void register_ieee802154_mac_key_hash_handler(guint hash_identifier, ieee802154_set_mac_key_func key_func)
+{
+ /* Ensure no duplication */
+ DISSECTOR_ASSERT(wmem_tree_lookup32(mac_key_hash_handlers, hash_identifier) == NULL);
+
+ wmem_tree_insert32(mac_key_hash_handlers, hash_identifier, (void*)key_func);
+}
+
+void dissect_ieee802154_aux_sec_header_and_key(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, ieee802154_packet *packet, guint *offset)
+{
+ proto_tree *field_tree, *header_tree;
+ proto_item *ti, *hidden_item;
+ guint8 security_control;
+ guint aux_length = 5; /* Minimum length of the auxiliary header. */
+ static const int * security_fields[] = {
+ &hf_ieee802154_security_level,
+ &hf_ieee802154_key_id_mode,
+ &hf_ieee802154_aux_sec_reserved,
+ NULL
+ };
+
+ /* Parse the security control field. */
+ security_control = tvb_get_guint8(tvb, *offset);
+ packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
+ packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
+
+ /* Compute the length of the auxiliary header and create a subtree. */
+ if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
+ if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
+ if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
+
+ ti = proto_tree_add_item(tree, hf_ieee802154_aux_security_header, tvb, *offset, aux_length, ENC_NA);
+ header_tree = proto_item_add_subtree(ti, ett_ieee802154_auxiliary_security);
+
+ /* Security Control Field */
+ proto_tree_add_bitmask(header_tree, tvb, *offset, hf_ieee802154_security_control_field, ett_ieee802154_aux_sec_control, security_fields, ENC_NA);
+ (*offset)++;
+
+ /* Frame Counter Field */
+ proto_tree_add_item_ret_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, *offset, 4, ENC_LITTLE_ENDIAN, &packet->frame_counter);
+ (*offset) +=4;
+
+ /* Key identifier field(s). */
+ if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
+ /* Create a subtree. */
+ field_tree = proto_tree_add_subtree(header_tree, tvb, *offset, 1,
+ ett_ieee802154_aux_sec_key_id, &ti, "Key Identifier Field"); /* Will fix length later. */
+ /* Add key source, if it exists. */
+ if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
+ packet->key_source.addr32 = tvb_get_ntohl(tvb, *offset);
+ proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, *offset, 4, packet->key_source.addr32);
+ hidden_item = proto_tree_add_item(field_tree, hf_ieee802154_aux_sec_key_source_bytes, tvb, *offset, 4, ENC_NA);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ proto_item_set_len(ti, 1 + 4);
+ (*offset) += 4;
+ }
+ if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
+ packet->key_source.addr64 = tvb_get_ntoh64(tvb, *offset);
+ proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, *offset, 8, packet->key_source.addr64);
+ hidden_item = proto_tree_add_item(field_tree, hf_ieee802154_aux_sec_key_source_bytes, tvb, *offset, 8, ENC_NA);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ proto_item_set_len(ti, 1 + 8);
+ (*offset) += 8;
+ }
+ /* Add key identifier. */
+ packet->key_index = tvb_get_guint8(tvb, *offset);
+ proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, *offset,1, packet->key_index);
+ (*offset)++;
+ }
+}
+
+tvbuff_t *dissect_ieee802154_payload(tvbuff_t * tvb, guint offset, packet_info * pinfo, proto_tree* key_tree,
+ ieee802154_packet * packet, ieee802154_payload_info_t* payload_info,
+ ieee802154_set_key_func set_key_func, ieee802154_payload_func payload_func)
+{
+ proto_item* ti;
+ unsigned char key[IEEE802154_CIPHER_SIZE];
+ unsigned char alt_key[IEEE802154_CIPHER_SIZE];
+ tvbuff_t * payload_tvb = NULL;
+
+ /* Lookup the key. */
+ for (payload_info->key_number = 0; payload_info->key_number < num_ieee802154_keys; payload_info->key_number++) {
+ if (set_key_func(packet, key, alt_key, &ieee802154_keys[payload_info->key_number])) {
+ /* Try with the initial key */
+ payload_info->key = key;
+ payload_tvb = payload_func(tvb, offset, pinfo, packet, payload_info);
+ if (!((*payload_info->status == DECRYPT_PACKET_MIC_CHECK_FAILED) || (*payload_info->status == DECRYPT_PACKET_DECRYPT_FAILED))) {
+ break;
+ }
+ /* Try with the alternate key */
+ payload_info->key = alt_key;
+ payload_tvb = payload_func(tvb, offset, pinfo, packet, payload_info);
+ if (!((*payload_info->status == DECRYPT_PACKET_MIC_CHECK_FAILED) || (*payload_info->status == DECRYPT_PACKET_DECRYPT_FAILED))) {
+ break;
+ }
+ }
+ }
+ if (payload_info->key_number == num_ieee802154_keys) {
+ /* None of the stored keys seemed to work */
+ *payload_info->status = DECRYPT_PACKET_NO_KEY;
+ }
+
+ /* Store the key number used for retrieval */
+ ti = proto_tree_add_uint(key_tree, hf_ieee802154_key_number, tvb, 0, 0, payload_info->key_number);
+ PROTO_ITEM_SET_HIDDEN(ti);
+ return payload_tvb;
+}
+
/*
*Dissector for IEEE 802.15.4 non-ASK PHY packet with an FCS containing a 16-bit CRC value.
*
@@ -948,18 +1155,21 @@ dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v
static void
dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint options)
{
- tvbuff_t *volatile payload_tvb;
+ tvbuff_t *volatile payload_tvb = NULL;
proto_tree *volatile ieee802154_tree = NULL;
proto_item *volatile proto_root = NULL;
proto_item *hidden_item;
proto_item *ti;
+ proto_item *mic_item = NULL;
+ proto_tree *header_tree = NULL;
guint offset = 0;
volatile gboolean fcs_ok = TRUE;
const char *saved_proto;
ws_decrypt_status status;
gboolean dstPanPresent = FALSE;
gboolean srcPanPresent = FALSE;
-
+ unsigned char rx_mic[IEEE802154_CIPHER_SIZE];
+ guint rx_mic_len = 0;
ieee802154_packet *packet = wmem_new0(wmem_packet_scope(), ieee802154_packet);
ieee802154_short_addr addr16;
ieee802154_hints_t *ieee_hints;
@@ -976,6 +1186,9 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
}
+ /* Save a pointer to the whole packet */
+ ieee_hints->packet = packet;
+
/* Create the protocol tree. */
if (tree) {
proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_captured_length(tvb), "IEEE 802.15.4");
@@ -1397,60 +1610,7 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
/* Existance of the Auxiliary Security Header is controlled by the Security Enabled Field */
if ((packet->security_enable) && (packet->version != IEEE802154_VERSION_2003)) {
- proto_tree *header_tree, *field_tree;
- guint8 security_control;
- guint aux_length = 5; /* Minimum length of the auxiliary header. */
- static const int * security_fields[] = {
- &hf_ieee802154_security_level,
- &hf_ieee802154_key_id_mode,
- &hf_ieee802154_aux_sec_reserved,
- NULL
- };
-
- /* Parse the security control field. */
- security_control = tvb_get_guint8(tvb, offset);
- packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
- packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
-
- /* Compute the length of the auxiliary header and create a subtree. */
- if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
- if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
- if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
- header_tree = proto_tree_add_subtree(ieee802154_tree, tvb, offset, aux_length,
- ett_ieee802154_auxiliary_security, NULL, "Auxiliary Security Header");
-
- /* Security Control Field */
- proto_tree_add_bitmask(header_tree, tvb, offset, hf_ieee802154_security_control_field, ett_ieee802154_aux_sec_control, security_fields, ENC_NA);
- offset++;
-
- /* Frame Counter Field */
- packet->frame_counter = tvb_get_letohl (tvb, offset);
- proto_tree_add_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, offset,4, packet->frame_counter);
- offset +=4;
-
- /* Key identifier field(s). */
- if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
- /* Create a subtree. */
- field_tree = proto_tree_add_subtree(header_tree, tvb, offset, 1,
- ett_ieee802154_aux_sec_key_id, &ti, "Key Identifier Field"); /* Will fix length later. */
- /* Add key source, if it exists. */
- if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
- packet->key_source.addr32 = tvb_get_ntohl(tvb, offset);
- proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 4, packet->key_source.addr32);
- proto_item_set_len(ti, 1 + 4);
- offset += (int)sizeof (guint32);
- }
- if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
- packet->key_source.addr64 = tvb_get_ntoh64(tvb, offset);
- proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 8, packet->key_source.addr64);
- proto_item_set_len(ti, 1 + 8);
- offset += 8;
- }
- /* Add key identifier. */
- packet->key_index = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, offset,1, packet->key_index);
- offset++;
- }
+ dissect_ieee802154_aux_sec_header_and_key(tvb, pinfo, ieee802154_tree, packet, &offset);
}
/*
@@ -1506,7 +1666,15 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
/* Encrypted Payload. */
if (packet->security_enable) {
- payload_tvb = dissect_ieee802154_decrypt(tvb, offset, pinfo, packet, &status);
+ ieee802154_payload_info_t payload_info;
+
+ payload_info.rx_mic = rx_mic;
+ payload_info.rx_mic_length = &rx_mic_len;
+ payload_info.status = &status;
+ payload_info.key = NULL; /* payload function will fill that in */
+
+ payload_tvb = dissect_ieee802154_payload(tvb, offset, pinfo, header_tree, packet, &payload_info,
+ ieee802154_set_mac_key, dissect_ieee802154_decrypt);
/* Get the unencrypted data if decryption failed. */
if (!payload_tvb) {
@@ -1517,11 +1685,18 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
payload_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
}
+ /* Display the MIC. */
+ if (rx_mic_len) {
+ mic_item = proto_tree_add_bytes(header_tree, hf_ieee802154_mic, tvb, 0, rx_mic_len, rx_mic);
+ PROTO_ITEM_SET_GENERATED(mic_item);
+ }
+
/* Display the reason for failure, and abort if the error was fatal. */
switch (status) {
case DECRYPT_PACKET_SUCCEEDED:
case DECRYPT_NOT_ENCRYPTED:
- /* No problem. */
+ /* No problem */
+ proto_item_append_text(mic_item, " [correct (key no. %d)]", payload_info.key_number);
break;
case DECRYPT_VERSION_UNSUPPORTED:
@@ -1552,6 +1727,7 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
case DECRYPT_PACKET_MIC_CHECK_FAILED:
expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "MIC check failed");
+ proto_item_append_text(mic_item, " [incorrect]");
/*
* Abort only if the payload was encrypted, in which case we
* probably didn't decrypt the packet right (eg: wrong key).
@@ -2958,18 +3134,19 @@ dissect_ieee802154_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
*@param pinfo Packet info structure.
*@param offset Offset where the ciphertext 'c' starts.
*@param packet IEEE 802.15.4 packet information.
- *@param status status of decryption returned through here on failure.
*@return decrypted payload.
*/
static tvbuff_t *
-dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee802154_packet *packet, ws_decrypt_status *status)
+dissect_ieee802154_decrypt(tvbuff_t *tvb,
+ guint offset,
+ packet_info *pinfo,
+ ieee802154_packet *packet,
+ ieee802154_payload_info_t* payload_info)
{
tvbuff_t *ptext_tvb;
gboolean have_mic = FALSE;
guint64 srcAddr;
- unsigned char key[16];
- unsigned char tmp[16];
- unsigned char rx_mic[16];
+ unsigned char tmp[IEEE802154_CIPHER_SIZE];
guint M;
gint captured_len;
gint reported_len;
@@ -2983,7 +3160,7 @@ dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee
* we do afterwards, which uses that information, is doable.
*/
if ((packet->version != IEEE802154_VERSION_2006) && (packet->version != IEEE802154_VERSION_2003)) {
- *status = DECRYPT_VERSION_UNSUPPORTED;
+ *payload_info->status = DECRYPT_VERSION_UNSUPPORTED;
return NULL;
}
@@ -2991,9 +3168,11 @@ dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee
/* Get the captured and on-the-wire length of the payload. */
M = IEEE802154_MIC_LENGTH(packet->security_level);
+ *payload_info->rx_mic_length = M;
+
reported_len = tvb_reported_length_remaining(tvb, offset) - IEEE802154_FCS_LEN - M;
if (reported_len < 0) {
- *status = DECRYPT_PACKET_TOO_SMALL;
+ *payload_info->status = DECRYPT_PACKET_TOO_SMALL;
return NULL;
}
/* Check of the payload is truncated. */
@@ -3007,55 +3186,43 @@ dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee
/* Check if the MIC is present in the captured data. */
have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
if (have_mic) {
- tvb_memcpy(tvb, rx_mic, offset + reported_len, M);
+ tvb_memcpy(tvb, payload_info->rx_mic, offset + reported_len, M);
}
/*
* Key Lookup - Need to find the appropriate key.
*
*/
- /*
- * Oh God! The specification is so bad. This is the worst
- * case of design-by-committee I've ever seen in my life.
- * The IEEE has created an unintelligible mess in order
- * to decipher which key is used for which message.
- *
- * Let's hope it's simpler to implement for dissecting only.
- *
- * Also need to find the extended address of the sender.
- */
- if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
- /* The source EUI-64 is included in the headers. */
- srcAddr = packet->src64;
- }
- else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
- /* Use the hint */
- srcAddr = ieee_hints->map_rec->addr64;
- }
- else {
- /* Lookup failed. */
- *status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
- return NULL;
- }
-
- /* Lookup the key. */
- /*
- * TODO: What this dissector really needs is a UAT to store multiple keys
- * and a variety of key configuration data. However, a single shared key
- * should be sufficient to get packet encryption off to a start.
- */
- if (!ieee802154_key_valid) {
- *status = DECRYPT_PACKET_NO_KEY;
- return NULL;
+ if ((packet->key_index == IEEE802154_THR_WELL_KNOWN_KEY_INDEX) &&
+ (packet->key_source.addr32 == IEEE802154_THR_WELL_KNOWN_KEY_SRC))
+ {
+ /* Use the well-known extended address */
+ srcAddr = IEEE802154_THR_WELL_KNOWN_EXT_ADDR;
+ } else {
+ if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
+ /* The source EUI-64 is included in the headers. */
+ srcAddr = packet->src64;
+ }
+ else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
+ /* Use the hint */
+ srcAddr = ieee_hints->map_rec->addr64;
+ }
+ else {
+ /* Lookup failed. */
+ *payload_info->status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
+ return NULL;
+ }
}
- memcpy(key, ieee802154_key, IEEE802154_CIPHER_SIZE);
/*
* CCM* - CTR mode payload encryption
*
*/
/* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
- ccm_init_block(tmp, FALSE, 0, srcAddr, packet, 0);
+ if (packet->version == IEEE802154_VERSION_2003)
+ ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->key_sequence_counter, 0);
+ else
+ ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->security_level, 0);
/* Decrypt the ciphertext, and place the plaintext in a new tvb. */
if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
@@ -3069,28 +3236,28 @@ dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee
text = (guint8 *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
/* Perform CTR-mode transformation. */
- if (!ccm_ctr_encrypt(key, tmp, rx_mic, text, captured_len)) {
+ if (!ccm_ctr_encrypt(payload_info->key, tmp, payload_info->rx_mic, text, captured_len)) {
g_free(text);
- *status = DECRYPT_PACKET_DECRYPT_FAILED;
+ *payload_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
return NULL;
}
/* Create a tvbuff for the plaintext. */
ptext_tvb = tvb_new_child_real_data(tvb, text, captured_len, reported_len);
add_new_data_source(pinfo, ptext_tvb, "Decrypted IEEE 802.15.4 payload");
- *status = DECRYPT_PACKET_SUCCEEDED;
+ *payload_info->status = DECRYPT_PACKET_SUCCEEDED;
}
/* There is no ciphertext. Wrap the plaintext in a new tvb. */
else {
/* Decrypt the MIC (if present). */
- if ((have_mic) && (!ccm_ctr_encrypt(key, tmp, rx_mic, NULL, 0))) {
- *status = DECRYPT_PACKET_DECRYPT_FAILED;
+ if ((have_mic) && (!ccm_ctr_encrypt(payload_info->key, tmp, payload_info->rx_mic, NULL, 0))) {
+ *payload_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
return NULL;
}
/* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
ptext_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
- *status = DECRYPT_PACKET_SUCCEEDED;
+ *payload_info->status = DECRYPT_PACKET_SUCCEEDED;
}
/*
@@ -3113,7 +3280,10 @@ dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee
/* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
- ccm_init_block(tmp, TRUE, M, srcAddr, packet, l_m);
+ if (packet->version == IEEE802154_VERSION_2003)
+ ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->key_sequence_counter, l_m);
+ else
+ ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->security_level, l_m);
/* Compute CBC-MAC authentication tag. */
/*
@@ -3123,12 +3293,12 @@ dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee
* already points to contiguous memory, since we just allocated it in
* decryption phase.
*/
- if (!ccm_cbc_mac(key, tmp, (const gchar *)tvb_memdup(wmem_packet_scope(), tvb, 0, l_a), l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
- *status = DECRYPT_PACKET_MIC_CHECK_FAILED;
+ if (!ccm_cbc_mac(payload_info->key, tmp, (const gchar *)tvb_memdup(wmem_packet_scope(), tvb, 0, l_a), l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
+ *payload_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
}
/* Compare the received MIC with the one we generated. */
- else if (memcmp(rx_mic, dec_mic, M) != 0) {
- *status = DECRYPT_PACKET_MIC_CHECK_FAILED;
+ else if (memcmp(payload_info->rx_mic, dec_mic, M) != 0) {
+ *payload_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
}
}
@@ -3143,11 +3313,12 @@ dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee
*@param adata TRUE if additional auth data is present
*@param M CCM* parameter M.
*@param addr Source extended address.
- *@param packet IEEE 802.15.4 packet information.
+ *@param frame_counter Packet frame counter
+ *@param level Security level or key_sequence_counter for 802.15.4-2003
*@param ctr_val Value in the last L bytes of the block.
*/
-static void
-ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, ieee802154_packet *packet, gint ctr_val)
+void
+ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, guint32 frame_counter, guint8 level, gint ctr_val)
{
gint i = 0;
@@ -3166,14 +3337,11 @@ ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, ieee802154_pa
block[i++] = (guint8)((addr >> 16) & 0xff);
block[i++] = (guint8)((addr >> 8) & 0xff);
block[i++] = (guint8)((addr >> 0) & 0xff);
- 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;
+ block[i++] = (guint8)((frame_counter >> 24) & 0xff);
+ block[i++] = (guint8)((frame_counter >> 16) & 0xff);
+ block[i++] = (guint8)((frame_counter >> 8) & 0xff);
+ block[i++] = (guint8)((frame_counter >> 0) & 0xff);
+ block[i++] = level;
/* Plaintext length. */
block[i++] = (guint8)((ctr_val >> 8) & 0xff);
block[i] = (guint8)((ctr_val >> 0) & 0xff);
@@ -3189,7 +3357,7 @@ ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, ieee802154_pa
*@param length Length of the buffer.
*@return TRUE on SUCCESS, FALSE on error.
*/
-static gboolean
+gboolean
ccm_ctr_encrypt(const gchar *key, const gchar *iv, gchar *mic, gchar *data, gint length)
{
gcry_cipher_hd_t cipher_hd;
@@ -3236,18 +3404,18 @@ ccm_ctr_encrypt(const gchar *key, const gchar *iv, gchar *mic, gchar *data, gint
*@param mic Output for CBC-MAC.
*@return TRUE on SUCCESS, FALSE on error.
*/
-static gboolean
+gboolean
ccm_cbc_mac(const gchar *key, const gchar *iv, const gchar *a, gint a_len, const gchar *m, gint m_len, gchar *mic)
{
gcry_cipher_hd_t cipher_hd;
guint i = 0;
- unsigned char block[16];
+ unsigned char block[IEEE802154_CIPHER_SIZE];
/* Open the cipher. */
if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC)) return FALSE;
/* Set the key. */
- if (gcry_cipher_setkey(cipher_hd, key, 16)) {
+ if (gcry_cipher_setkey(cipher_hd, key, IEEE802154_CIPHER_SIZE)) {
gcry_cipher_close(cipher_hd);
return FALSE;
}
@@ -3359,6 +3527,25 @@ gboolean ieee802154_long_addr_equal(gconstpointer a, gconstpointer b)
return (((const ieee802154_long_addr *)a)->addr == ((const ieee802154_long_addr *)b)->addr);
}
+/* Set MAC key function. */
+static gboolean ieee802154_set_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t* uat_key)
+{
+ ieee802154_set_mac_key_func func = (ieee802154_set_mac_key_func)wmem_tree_lookup32(mac_key_hash_handlers, uat_key->hash_type);
+
+ if (func != NULL)
+ return func(packet, key, alt_key, uat_key);
+
+ /* Right now, KEY_HASH_NONE and KEY_HASH_ZIP are not registered because they
+ work with this "default" behavior */
+ if (packet->key_index == uat_key->key_index)
+ {
+ memcpy(key, uat_key->key, IEEE802154_CIPHER_SIZE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/**
*Creates a record that maps the given short address and pan to a long (extended) address.
*@param short_addr 16-bit short address
@@ -3505,8 +3692,7 @@ proto_cleanup_ieee802154(void)
static void ieee802154_da_prompt(packet_info *pinfo _U_, gchar* result)
{
ieee802154_hints_t *hints;
- hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
- proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
+ hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
if (hints)
g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN 0x%04x as", hints->src_pan);
else
@@ -3517,8 +3703,7 @@ static void ieee802154_da_prompt(packet_info *pinfo _U_, gchar* result)
static gpointer ieee802154_da_value(packet_info *pinfo _U_)
{
ieee802154_hints_t *hints;
- hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
- proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
+ hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
if (hints)
return GUINT_TO_POINTER((guint)(hints->src_pan));
else
@@ -4033,6 +4218,9 @@ void proto_register_ieee802154(void)
/*
* Auxiliary Security Header Fields
*/
+ { &hf_ieee802154_aux_security_header,
+ { "Auxiliary Security Header", "wpan.aux_sec.hdr", FT_NONE, BASE_NONE, NULL,
+ 0x0, "The Auxiliary Security Header of the frame", HFILL }},
{ &hf_ieee802154_security_level,
{ "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names),
@@ -4059,11 +4247,23 @@ void proto_register_ieee802154(void)
{ "Key Source", "wpan.aux_sec.key_source", FT_UINT64, BASE_HEX, NULL, 0x0,
"Key Source for processing of the protected frame", HFILL }},
+ { &hf_ieee802154_aux_sec_key_source_bytes,
+ { "Key Source", "wpan.aux_sec.key_source.bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Key Source for processing of the protected frame", HFILL }},
+
{ &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 }},
- /* IEEE 802.15.4-2003 Security Header Fields */
+ { &hf_ieee802154_mic,
+ { "Decrypted MIC", "wpan.mic", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "The Decrypted MIC", HFILL }},
+
+ { &hf_ieee802154_key_number,
+ { "Key Number", "wpan.key_number", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Key number used to decode", 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 }},
@@ -4174,6 +4374,15 @@ void proto_register_ieee802154(void)
UAT_END_FIELDS
};
+ static uat_field_t key_uat_flds[] = {
+ UAT_FLD_CSTRING(key_uat,pref_key,"Decryption key",
+ "128-bit decryption key in hexadecimal format"),
+ UAT_FLD_DEC(key_uat,key_index,"Decryption key index",
+ "Key index in decimal format"),
+ UAT_FLD_VS(key_uat, hash_type, "Key hash", ieee802154_key_hash_vals, "Specifies which hash scheme is used to derived the key"),
+ UAT_END_FIELDS
+ };
+
static build_valid_func ieee802154_da_build_value[1] = {ieee802154_da_value};
static decode_as_value_t ieee802154_da_values = {ieee802154_da_prompt, 1, ieee802154_da_build_value};
static decode_as_t ieee802154_da = {
@@ -4242,10 +4451,28 @@ void proto_register_ieee802154(void)
"A table of static address mappings between 16-bit short addressing and EUI-64 addresses",
static_addr_uat);
+ /* Create a UAT for key management. */
+ ieee802154_key_uat = uat_new("Keys",
+ sizeof(ieee802154_key_t), /* record size */
+ "ieee802154_keys", /* filename */
+ TRUE, /* from_profile */
+ &ieee802154_keys, /* data_ptr */
+ &num_ieee802154_keys, /* numitems_ptr */
+ UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
+ NULL, /* help */
+ ieee802154_key_copy_cb, /* copy callback */
+ ieee802154_key_update_cb, /* update callback */
+ ieee802154_key_free_cb, /* free callback */
+ ieee802154_key_post_update_cb, /* post update callback */
+ NULL, /* reset callback */
+ key_uat_flds); /* UAT field definitions */
+ prefs_register_uat_preference(ieee802154_module, "ieee802154_keys",
+ "Decryption Keys",
+ "Decryption key configuration data",
+ ieee802154_key_uat);
+
/* Register preferences for a decryption key */
- /* TODO: Implement a UAT for multiple keys, and with more advanced key management. */
- prefs_register_string_preference(ieee802154_module, "802154_key", "Decryption key",
- "128-bit decryption key in hexadecimal format", (const char **)&ieee802154_key_str);
+ prefs_register_obsolete_preference(ieee802154_module, "802154_key");
prefs_register_enum_preference(ieee802154_module, "802154_sec_suite",
"Security Suite (802.15.4-2003)",
@@ -4271,6 +4498,9 @@ void proto_register_ieee802154(void)
register_dissector("wpan_cc24xx", dissect_ieee802154_cc24xx, proto_ieee802154);
ieee802154_nonask_phy_handle = register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
+ /* setup registration for other dissectors to provide mac key hash algorithms */
+ mac_key_hash_handlers = wmem_tree_new(wmem_epan_scope());
+
/* Register a Decode-As handler. */
register_decode_as(&ieee802154_da);
} /* proto_register_ieee802154 */
@@ -4285,8 +4515,6 @@ void proto_reg_handoff_ieee802154(void)
{
static gboolean prefs_initialized = FALSE;
static unsigned int old_ieee802154_ethertype;
- GByteArray *bytes;
- gboolean res;
if (!prefs_initialized){
/* Get the dissector handles. */
@@ -4306,15 +4534,6 @@ void proto_reg_handoff_ieee802154(void)
old_ieee802154_ethertype = ieee802154_ethertype;
- /* Get the IEEE 802.15.4 decryption key. */
- bytes = g_byte_array_new();
- res = hex_str_to_bytes(ieee802154_key_str, bytes, FALSE);
- ieee802154_key_valid = (res && bytes->len >= IEEE802154_CIPHER_SIZE);
- if (ieee802154_key_valid) {
- memcpy(ieee802154_key, bytes->data, IEEE802154_CIPHER_SIZE);
- }
- g_byte_array_free(bytes, TRUE);
-
/* Register dissector handles. */
dissector_add_uint("ethertype", ieee802154_ethertype, ieee802154_handle);
} /* proto_reg_handoff_ieee802154 */
diff --git a/epan/dissectors/packet-ieee802154.h b/epan/dissectors/packet-ieee802154.h
index 442b2f8f8e..c46514b7a1 100644
--- a/epan/dissectors/packet-ieee802154.h
+++ b/epan/dissectors/packet-ieee802154.h
@@ -194,6 +194,11 @@
#define IEEE802154_AUX_KEY_ID_MODE_SHIFT 3
#define IEEE802154_AUX_KEY_RESERVED_MASK 0xE0 /* Reserved */
+/* Thread-specific well-known key support */
+#define IEEE802154_THR_WELL_KNOWN_KEY_INDEX 0xff
+#define IEEE802154_THR_WELL_KNOWN_KEY_SRC 0xffffffff
+#define IEEE802154_THR_WELL_KNOWN_EXT_ADDR 0x3506feb823d48712ULL
+
typedef enum {
SECURITY_LEVEL_NONE = 0x00,
SECURITY_LEVEL_MIC_32 = 0x01,
@@ -212,6 +217,12 @@ typedef enum {
KEY_ID_MODE_KEY_EXPLICIT_8 = 0x03
} ieee802154_key_id_mode;
+typedef enum {
+ KEY_HASH_NONE = 0x00,
+ KEY_HASH_ZIP = 0x01,
+ KEY_HASH_THREAD = 0x02
+} ieee802154_key_hash;
+
/* Header IE Element ID */
#define IEEE802154_HEADER_VENDOR_SPECIFIC 0x00
/* Reserved 0x01-0x19 */
@@ -403,12 +414,56 @@ typedef struct {
guint16 src16;
guint16 dst16;
ieee802154_map_rec *map_rec;
+ void *packet;
} ieee802154_hints_t;
+typedef enum {
+ DECRYPT_PACKET_SUCCEEDED,
+ DECRYPT_NOT_ENCRYPTED,
+ DECRYPT_VERSION_UNSUPPORTED,
+ DECRYPT_PACKET_TOO_SMALL,
+ DECRYPT_PACKET_NO_EXT_SRC_ADDR,
+ DECRYPT_PACKET_NO_KEY,
+ DECRYPT_PACKET_DECRYPT_FAILED,
+ DECRYPT_PACKET_MIC_CHECK_FAILED
+} ws_decrypt_status;
+
+/* UAT key structure. */
+typedef struct {
+ gchar *pref_key;
+ guint key_index;
+ ieee802154_key_hash hash_type;
+ guint8 key[IEEE802154_CIPHER_SIZE];
+ guint8 mle_key[IEEE802154_CIPHER_SIZE];
+} ieee802154_key_t;
+
/* */
void dissect_ieee802154_superframe (tvbuff_t *, packet_info *, proto_tree *, guint *);
void dissect_ieee802154_gtsinfo (tvbuff_t *, packet_info *, proto_tree *, guint *);
void dissect_ieee802154_pendaddr (tvbuff_t *, packet_info *, proto_tree *, guint *);
+void dissect_ieee802154_aux_sec_header_and_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet, guint *offset);
+void ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, guint32 frame_counter, guint8 level, gint ctr_val);
+gboolean ccm_ctr_encrypt(const gchar *key, const gchar *iv, gchar *mic, gchar *data, gint length);
+gboolean ccm_cbc_mac(const gchar *key, const gchar *iv, const gchar *a, gint a_len, const gchar *m, gint m_len, gchar *mic);
+
+typedef struct {
+ unsigned char* rx_mic;
+ guint* rx_mic_length;
+ guint aux_offset;
+ guint aux_length;
+ ws_decrypt_status* status;
+ unsigned char *key;
+ guint key_number;
+} ieee802154_payload_info_t;
+
+typedef gboolean (*ieee802154_set_key_func) (ieee802154_packet * packet, unsigned char* key, unsigned char* alt_key, ieee802154_key_t* key_info);
+typedef tvbuff_t* (*ieee802154_payload_func) (tvbuff_t *, guint, packet_info *, ieee802154_packet *, ieee802154_payload_info_t*);
+tvbuff_t *dissect_ieee802154_payload(tvbuff_t * tvb, guint offset, packet_info * pinfo, proto_tree* key_tree, ieee802154_packet * packet,
+ ieee802154_payload_info_t* payload_info, ieee802154_set_key_func set_key_func, ieee802154_payload_func payload_func);
+
+
+typedef gboolean (*ieee802154_set_mac_key_func) (ieee802154_packet * packet, unsigned char* key, unsigned char* alt_key, ieee802154_key_t* uat_key);
+extern void register_ieee802154_mac_key_hash_handler(guint hash_identifier, ieee802154_set_mac_key_func key_func);
/* Short to Extended Address Prototypes */
extern ieee802154_map_rec *ieee802154_addr_update(ieee802154_map_tab_t *, guint16, guint16, guint64,
@@ -421,4 +476,6 @@ extern gboolean ieee802154_long_addr_equal(gconstpointer a, gconstpointer b);
extern gboolean ieee802154_short_addr_invalidate(guint16, guint16, guint);
extern gboolean ieee802154_long_addr_invalidate(guint64, guint);
+extern ieee802154_map_tab_t ieee802154_map;
+
#endif /* PACKET_IEEE802154_H */