static void dissect_eapol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 eapol_type; guint8 keydesc_type; guint16 eapol_len; guint len; guint16 eapol_key_len, eapol_data_len; guint8 key_index; guint16 keyinfo; proto_tree *ti = NULL; proto_tree *eapol_tree = NULL; proto_tree *keyinfo_item = NULL; proto_tree *keyinfo_tree = NULL; proto_tree *key_index_tree, *keydes_tree; tvbuff_t *next_tvb; col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAPOL"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { ti = proto_tree_add_item(tree, proto_eapol, tvb, 0, -1, FALSE); eapol_tree = proto_item_add_subtree(ti, ett_eapol); proto_tree_add_item(eapol_tree, hf_eapol_version, tvb, offset, 1, FALSE); } offset++; eapol_type = tvb_get_guint8(tvb, offset); if (tree) proto_tree_add_uint(eapol_tree, hf_eapol_type, tvb, offset, 1, eapol_type); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(eapol_type, eapol_type_vals, "Unknown type (0x%02X)")); offset++; eapol_len = tvb_get_ntohs(tvb, offset); len = EAPOL_HDR_LEN + eapol_len; set_actual_length(tvb, len); if (tree) { proto_item_set_len(ti, len); proto_tree_add_uint(eapol_tree, hf_eapol_len, tvb, offset, 2, eapol_len); } offset += 2; switch (eapol_type) { case EAP_PACKET: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(eap_handle, next_tvb, pinfo, eapol_tree); break; case EAPOL_KEY: if (tree) { keydesc_type = tvb_get_guint8(tvb, offset); proto_tree_add_item(eapol_tree, hf_eapol_keydes_type, tvb, offset, 1, FALSE); offset += 1; if (keydesc_type == EAPOL_WPA_KEY || keydesc_type == EAPOL_RSN_KEY) { keyinfo = tvb_get_ntohs(tvb, offset); keyinfo_item = proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_keyinfo, tvb, offset, 2, keyinfo); keyinfo_tree = proto_item_add_subtree(keyinfo_item, ett_keyinfo); proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_keydes_ver, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_type, tvb, offset, 2, keyinfo); proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_index, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_install, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_ack, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_mic, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_secure, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_error, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_request, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_encr_key_data, tvb, offset, 2, keyinfo); offset += 2; proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb, offset, 8, FALSE); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_nonce, tvb, offset, 32, FALSE); offset += 32; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb, offset, 16, FALSE); offset += 16; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_rsc, tvb, offset, 8, FALSE); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_id, tvb, offset, 8, FALSE); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_mic, tvb, offset, 16, FALSE); offset += 16; eapol_data_len = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_datalen, tvb, offset, 2, eapol_data_len); offset += 2; if (eapol_data_len != 0) { ti = proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data, tvb, offset, eapol_data_len, FALSE); if ((keyinfo & KEY_INFO_ENCR_KEY_DATA_MASK) || !(keyinfo & KEY_INFO_KEY_TYPE_MASK)) { /* RSN: EAPOL-Key Key Data is encrypted. * WPA: Group Keys use encrypted Key Data. * Cannot parse this without knowing the key. * IEEE 802.11i-2004 8.5.2. */ } else { keydes_tree = proto_item_add_subtree(ti, ett_eapol_keydes_data); ieee_80211_add_tagged_parameters(tvb, offset, pinfo, keydes_tree, eapol_data_len); } } } else { eapol_key_len = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset, 2, eapol_key_len); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb, offset, 8, FALSE); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb, offset, 16, FALSE); offset += 16; key_index = tvb_get_guint8(tvb, offset); ti = proto_tree_add_text(eapol_tree, tvb, offset, 1, "Key Index: %s, index %u", (key_index & 0x80) ? "unicast" : "broadcast", key_index & 0x7F); key_index_tree = proto_item_add_subtree(ti, ett_eapol_key_index); proto_tree_add_boolean(eapol_tree, hf_eapol_keydes_key_index_keytype, tvb, offset, 1, key_index); proto_tree_add_uint(eapol_tree, hf_eapol_keydes_key_index_indexnum, tvb, offset, 1, key_index); offset += 1; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_signature, tvb, offset, 16, FALSE); offset += 16; if (eapol_key_len != 0) { if (eapol_len > 44) { /* Size of rc4 key with no key content */ proto_tree_add_item(eapol_tree, hf_eapol_keydes_key, tvb, offset, eapol_key_len, FALSE); } else { /* IEEE 802.1X-2004 7.6.3.6: If no bytes remain, then */ proto_tree_add_text(eapol_tree, tvb, offset, 0, "Key: Use key locally generated by peer"); } } } } break; case EAPOL_ENCAP_ASF_ALERT: /* XXX - is this an SNMP trap? */ default: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, eapol_tree); break; } }
static void dissect_eapol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 eapol_type; guint8 keydesc_type; guint16 eapol_len; guint len; guint16 eapol_key_len, eapol_data_len; guint16 keyinfo; gboolean generated_locally; proto_tree *ti = NULL; proto_tree *eapol_tree = NULL; proto_tree *keyinfo_item = NULL; proto_tree *keyinfo_tree = NULL; proto_tree *key_index_tree, *keydes_tree; tvbuff_t *next_tvb; guint8 counter; col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAPOL"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { ti = proto_tree_add_item(tree, proto_eapol, tvb, 0, -1, ENC_NA); eapol_tree = proto_item_add_subtree(ti, ett_eapol); proto_tree_add_item(eapol_tree, hf_eapol_version, tvb, offset, 1, ENC_BIG_ENDIAN); } offset++; eapol_type = tvb_get_guint8(tvb, offset); if (tree) proto_tree_add_item(eapol_tree, hf_eapol_type, tvb, offset, 1, ENC_BIG_ENDIAN); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(eapol_type, eapol_type_vals, "Unknown Type (0x%02X)")); offset++; eapol_len = tvb_get_ntohs(tvb, offset); len = EAPOL_HDR_LEN + eapol_len; set_actual_length(tvb, len); if (tree) { proto_item_set_len(ti, len); proto_tree_add_item(eapol_tree, hf_eapol_len, tvb, offset, 2, ENC_BIG_ENDIAN); } offset += 2; switch (eapol_type) { case EAP_PACKET: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(eap_handle, next_tvb, pinfo, eapol_tree); break; case EAPOL_KEY: if (tree) { keydesc_type = tvb_get_guint8(tvb, offset); proto_tree_add_item(eapol_tree, hf_eapol_keydes_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (keydesc_type == EAPOL_WPA_KEY || keydesc_type == EAPOL_RSN_KEY) { keyinfo = tvb_get_ntohs(tvb, offset); if (keyinfo & KEY_INFO_REQUEST_MASK) { col_set_str(pinfo->cinfo, COL_INFO, "Key (Request)"); if (keyinfo & KEY_INFO_ERROR_MASK) col_set_str(pinfo->cinfo, COL_INFO, "Key (Request, Error)"); } else if (keyinfo & KEY_INFO_KEY_TYPE_MASK) { guint16 masked; masked = keyinfo & (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK | KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK); if (keydesc_type == EAPOL_WPA_KEY) { switch (masked) { case KEY_INFO_KEY_ACK_MASK: col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 1 of 4)"); break; case KEY_INFO_KEY_MIC_MASK: counter = tvb_get_guint8(tvb, offset+11); if (!counter) col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 2 of 4)"); else col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 4 of 4)"); break; case (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK | KEY_INFO_KEY_MIC_MASK): col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 3 of 4)"); break; } } if (keydesc_type == EAPOL_RSN_KEY) { switch (masked) { case KEY_INFO_KEY_ACK_MASK: col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 1 of 4)"); break; case KEY_INFO_KEY_MIC_MASK: col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 2 of 4)"); break; case (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK | KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK): col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 3 of 4)"); break; case (KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK): col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 4 of 4)"); break; } } } else { if (keyinfo & KEY_INFO_KEY_ACK_MASK) col_set_str(pinfo->cinfo, COL_INFO, "Key (Group Message 1 of 2)"); else col_set_str(pinfo->cinfo, COL_INFO, "Key (Group Message 2 of 2)"); } keyinfo_item = proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_keyinfo, tvb, offset, 2, ENC_BIG_ENDIAN); keyinfo_tree = proto_item_add_subtree(keyinfo_item, ett_keyinfo); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_keydes_version, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_type, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_index, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_install, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_ack, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_mic, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_secure, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_error, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_request, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_encrypted_key_data, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_len, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_nonce, tvb, offset, 32, ENC_NA); offset += 32; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb, offset, 16, ENC_NA); offset += 16; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_rsc, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_id, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_mic, tvb, offset, 16, ENC_NA); offset += 16; eapol_data_len = tvb_get_ntohs(tvb, offset); proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data_len, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (eapol_data_len != 0) { ti = proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data, tvb, offset, eapol_data_len, ENC_NA); if ((keyinfo & KEY_INFO_ENCRYPTED_KEY_DATA_MASK) || !(keyinfo & KEY_INFO_KEY_TYPE_MASK)) { /* RSN: EAPOL-Key Key Data is encrypted. * WPA: Group Keys use encrypted Key Data. * Cannot parse this without knowing the key. * IEEE 802.11i-2004 8.5.2. */ } else { keydes_tree = proto_item_add_subtree(ti, ett_eapol_keydes_data); ieee_80211_add_tagged_parameters(tvb, offset, pinfo, keydes_tree, eapol_data_len, -1); } } } else { eapol_key_len = tvb_get_ntohs(tvb, offset); proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_len, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb, offset, 16, ENC_NA); offset += 16; ti = proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_index, tvb, offset, 1, ENC_BIG_ENDIAN); key_index_tree = proto_item_add_subtree(ti, ett_eapol_key_index); proto_tree_add_item(key_index_tree, hf_eapol_keydes_key_index_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(key_index_tree, hf_eapol_keydes_key_index_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_signature, tvb, offset, 16, ENC_NA); offset += 16; if (eapol_key_len != 0) { /* IEEE 802.1X-2004 7.6.3.6: If no bytes remain, then */ generated_locally = eapol_len <= 44; /* Size of rc4 key with no key content */ if (!generated_locally) { proto_tree_add_item(eapol_tree, hf_eapol_keydes_key, tvb, offset, eapol_key_len, ENC_NA); } proto_tree_add_boolean(eapol_tree, hf_eapol_keydes_key_generated_locally, tvb, offset, 0, generated_locally); } } } break; case EAPOL_ENCAP_ASF_ALERT: /* XXX - is this an SNMP trap? */ default: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, eapol_tree); break; } }