/* packet-wai.c * Routines for WAI packet dissection * Based on: WAPI ISO submission - ISO/IEC JTC 1 N 9880 [ref: 1] * chapter "8.1.4 WAI protocol" * * Written by Lukasz Kotasa * Lukasz Suchy * Copyright 2010, Tieto. * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ /* Protocol reference: * http://isotc.iso.org/livelink/livelink?func=ll&objId=8500308&objAction=Open&ei=nt-RTKe1IJKTjAeepLS8BQ&usg=AFQjCNEn8hlU_SfoAGkM-X48JL_BL8bptA&sig2=JOHNPrqgCMO4q0cWhAfkow * (chapter: 8.1.4. WAI protocol) */ #include "config.h" #include #include #include #define WAI_SUB_PRE_AUTHENTICATION 0x01 /* pre-authentication start */ #define WAI_SUB_STAKEY_REQ 0x02 /* STAKey request */ #define WAI_SUB_AUTH_ACTIVATION 0x03 /* authentication activation */ #define WAI_SUB_ACCESS_AUTH_REQ 0x04 /* access authentication request */ #define WAI_SUB_ACCESS_AUTH_RESP 0x05 /* access authentication response */ #define WAI_SUB_CERT_AUTH_REQ 0x06 /* certificate authentication request */ #define WAI_SUB_CERT_AUTH_RESP 0x07 /* certificate authentication response */ #define WAI_SUB_UNICAST_KEY_REQ 0x08 /* unicast key negotiation request */ #define WAI_SUB_UNICAST_KEY_RESP 0x09 /* unicast key negotiation response */ #define WAI_SUB_UNICAST_KEY_CONFIRM 0x0A /* unicast key negotiation confirmation */ #define WAI_SUB_MULTICAST_ANNOUNCE 0x0B /* multicast key/STAKey announcement */ #define WAI_SUB_MULTICAST_ANNOUNCE_RESP 0x0C /* multicast key/STAKey announcement response */ #define FLAG_BIT0 0x01 #define FLAG_BIT1 0x02 #define FLAG_BIT2 0x04 #define FLAG_BIT3 0x08 #define FLAG_BIT4 0x10 #define FLAG_BIT5 0x20 #define FLAG_BIT6 0x40 #define FLAG_BIT7 0x80 void proto_register_wai(void); void proto_reg_handoff_wai(void); static reassembly_table wai_reassembly_table; static dissector_handle_t wai_handle; static int proto_wai = -1; static gint hf_wai_version = -1; static gint hf_wai_type = -1; static gint hf_wai_subtype = -1; static gint hf_wai_reserved = -1; static gint hf_wai_length = -1; static gint hf_wai_seq = -1; static gint hf_wai_fragm_seq = -1; static gint hf_wai_flag = -1; static gint hf_wai_data = -1; static gint hf_wai_bk_rekeying_flag = -1; static gint hf_wai_preauthentication_flag = -1; static gint hf_wai_certificate_flag = -1; static gint hf_wai_optional_flag = -1; static gint hf_wai_usk_rekeying_flag = -1; static gint hf_wai_negotiation_flag = -1; static gint hf_wai_revoking_flag = -1; static gint hf_wai_reserved_flag = -1; static gint hf_wai_attr_type = -1; static gint hf_wai_cert = -1; static gint hf_wai_cert_id = -1; static gint hf_wai_cert_data = -1; static gint hf_wai_cert_len = -1; static gint hf_wai_addid = -1; static gint hf_wai_ae_mac = -1; static gint hf_wai_asue_mac = -1; static gint hf_wai_bkid = -1; static gint hf_wai_uskid = -1; static gint hf_wai_wie = -1; static gint hf_wai_message_auth_code = -1; static gint hf_wai_mskid = -1; static gint hf_wai_data_pack_num = -1; static gint hf_wai_key_data = -1; static gint hf_wai_key_data_len = -1; static gint hf_wai_key_data_content = -1; static gint hf_wai_key_ann_id = -1; static gint hf_wai_auth_id = -1; static gint hf_wai_identity = -1; static gint hf_wai_identity_id = -1; static gint hf_wai_identity_len = -1; static gint hf_wai_identity_data = -1; static gint hf_wai_ecdh = -1; static gint hf_wai_ecdh_id = -1; static gint hf_wai_ecdh_len = -1; static gint hf_wai_ecdh_content = -1; static gint hf_wai_counter = -1; static gint hf_wai_sta_key_id = -1; static gint hf_wai_challenge = -1; static gint hf_wai_cert_ver = -1; static gint hf_wai_nonce = -1; static gint hf_wai_ver_res = -1; static gint hf_wai_sign_alg = -1; static gint hf_wai_hash_alg_id = -1; static gint hf_wai_sign_alg_id = -1; static gint hf_wai_param = -1; static gint hf_wai_param_id = -1; static gint hf_wai_param_content = -1; static gint hf_wai_sign_val = -1; static gint hf_wai_sign_content = -1; static gint hf_wai_sign = -1; static gint hf_wai_identity_list = -1; static gint hf_wai_reserved_byte = -1; static gint hf_wai_no_of_ids = -1; static gint hf_wai_access_res = -1; static gint hf_wai_fragments = -1; static gint hf_wai_fragment = -1; static gint hf_wai_fragment_overlap = -1; static gint hf_wai_fragment_overlap_conflicts = -1; static gint hf_wai_fragment_multiple_tails = -1; static gint hf_wai_fragment_too_long_fragment = -1; static gint hf_wai_fragment_error = -1; static gint hf_wai_fragment_count = -1; static gint hf_wai_reassembled_in = -1; static gint hf_wai_reassembled_length = -1; static gint ett_wai = -1; static gint ett_wai_data = -1; static gint ett_wai_flags = -1; static gint ett_wai_certificate = -1; static gint ett_wai_mac = -1; static gint ett_wai_identity = -1; static gint ett_wai_key_data = -1; static gint ett_wai_ecdh_param = -1; static gint ett_wai_certificate_verification = -1; static gint ett_wai_identity_list = -1; static gint ett_wai_sign = -1; static gint ett_wai_sign_alg = -1; static gint ett_wai_sign_val = -1; static gint ett_wai_parameter = -1; static gint ett_wai_fragment = -1; static gint ett_wai_fragments = -1; static const value_string wai_type_names [] = { { 1, "WAI protocol package"}, { 0, NULL } }; static const value_string wai_attr_type_names [] = { { 1, "Signature"}, { 2, "Certificate Authentication Result"}, { 3, "Identity List"}, { 0, NULL } }; static const value_string wai_ver_res_names [] = { { 0, "Certificate is valid" }, { 1, "Certificate issuer is unknown"}, { 2, "Root certificate is untrusted"}, { 3, "Certificate time is invalid"}, { 4, "Certificate signature is invalid"}, { 5, "Certificate is revoked"}, { 6, "Certificate is not valid in its proposed usage"}, { 7, "Certificate revocation state is unknown"}, { 8, "Certificate has an unknown error"}, { 0, NULL } }; static const value_string wai_access_res_names [] = { { 0, "Success" }, { 1, "Unidentified certificate"}, { 2, "Certificate Error"}, { 3, "Prohibited by AE"}, { 0, NULL } }; static const fragment_items wai_frag_items = { /* Fragment subtrees */ &ett_wai_fragment, &ett_wai_fragments, /* Fragment fields */ &hf_wai_fragments, &hf_wai_fragment, &hf_wai_fragment_overlap, &hf_wai_fragment_overlap_conflicts, &hf_wai_fragment_multiple_tails, &hf_wai_fragment_too_long_fragment, &hf_wai_fragment_error, &hf_wai_fragment_count, /* Reassembled in field */ &hf_wai_reassembled_in, /* Reassembled length field */ &hf_wai_reassembled_length, /* Reassembled data field */ NULL, /* Tag */ "Message fragments" }; static const value_string wai_subtype_names[] = { { WAI_SUB_PRE_AUTHENTICATION, "Pre-Authentication start" }, { WAI_SUB_STAKEY_REQ, "STAKey request" }, { WAI_SUB_AUTH_ACTIVATION, "Authentication activation" }, { WAI_SUB_ACCESS_AUTH_REQ, "Access authentication request" }, { WAI_SUB_ACCESS_AUTH_RESP, "Access authentication response" }, { WAI_SUB_CERT_AUTH_REQ, "Certificate authentication request" }, { WAI_SUB_CERT_AUTH_RESP, "Certificate authentication response" }, { WAI_SUB_UNICAST_KEY_REQ, "Unicast key negotiation request" }, { WAI_SUB_UNICAST_KEY_RESP, "Unicast key negotiation response" }, { WAI_SUB_UNICAST_KEY_CONFIRM, "Unicast key negotiation confirmation" }, { WAI_SUB_MULTICAST_ANNOUNCE, "Multicast key/STAKey announcement" }, { WAI_SUB_MULTICAST_ANNOUNCE_RESP, "Multicast key/STAKey announcement response" }, { 0, NULL } }; static value_string_ext wai_subtype_names_ext = VALUE_STRING_EXT_INIT(wai_subtype_names); static const true_false_string wai_bk_rekeying_flag = { "Packet is a BK rekeying packet", "Packet is not a BK rekeying packet" }; static const true_false_string wai_preauthentication_flag = { "Packet is a pre-authentication packet", "Packet is not a pre-authentication packet" }; static const true_false_string wai_certificate_flag = { "STA requires to verify the peers certificate", "STA doesn't require to verify the peers certificate" }; static const true_false_string wai_optional_flag = { "There are some optional fields in packet", "No optional fields in packet" }; static const true_false_string wai_usk_rekeying_flag = { "Packet is a USK rekeying packet", "Packet is not a USK rekeying packet" }; static const true_false_string wai_negotiation_flag = { "Packet is a STAKey negotiation packet", "Packet is not a STAKey negotiation packet" }; static const true_false_string wai_revoking_flag = { "STA delete a STAKey", "STA doesn't delete a STAKey" }; static const true_false_string wai_reserved_flag = { "reserved 1", "reserved 0" }; static void dissect_flag(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_item *flag_item; proto_tree *flag_tree; flag_item = proto_tree_add_item(tree, hf_wai_flag, tvb, offset, 1, ENC_BIG_ENDIAN); flag_tree = proto_item_add_subtree (flag_item, ett_wai_flags); proto_tree_add_item (flag_tree, hf_wai_bk_rekeying_flag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (flag_tree, hf_wai_preauthentication_flag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (flag_tree, hf_wai_certificate_flag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (flag_tree, hf_wai_optional_flag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (flag_tree, hf_wai_usk_rekeying_flag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (flag_tree, hf_wai_negotiation_flag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (flag_tree, hf_wai_revoking_flag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item (flag_tree, hf_wai_reserved_flag, tvb, offset, 1, ENC_BIG_ENDIAN); } inline static void dissect_bkid(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_tree_add_item(tree, hf_wai_bkid, tvb, offset, 16, ENC_NA); } inline static void dissect_uskid(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_tree_add_item(tree, hf_wai_uskid, tvb, offset, 1, ENC_NA); } inline static void dissect_wie(tvbuff_t *tvb, guint offset, guint length, proto_tree *tree) { proto_tree_add_item(tree, hf_wai_wie, tvb, offset, length, ENC_NA); } inline static void dissect_message_auth_code(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_tree_add_item(tree, hf_wai_message_auth_code, tvb, offset, 20, ENC_NA); } inline static void dissect_mskid(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_tree_add_item(tree, hf_wai_mskid, tvb, offset, 1, ENC_NA); } inline static void dissect_key_announcement_identifier(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_tree_add_item(tree, hf_wai_key_ann_id, tvb, offset, 16, ENC_NA); } inline static void dissect_counter(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_tree_add_item(tree, hf_wai_counter, tvb, offset, 16, ENC_NA); } inline static void dissect_authentication_id(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_tree_add_item(tree, hf_wai_auth_id, tvb, offset, 32, ENC_NA); } static void dissect_addid(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_item *mac_item; proto_tree *mac_tree; mac_item = proto_tree_add_string(tree, hf_wai_addid, tvb, offset, 12, "AE MAC and ASUE MAC addresses"); mac_tree = proto_item_add_subtree(mac_item, ett_wai_mac); proto_tree_add_item(mac_tree, hf_wai_ae_mac, tvb, offset, 6, ENC_NA); proto_tree_add_item(mac_tree, hf_wai_asue_mac, tvb, offset+6, 6, ENC_NA); } static guint16 dissect_identity(tvbuff_t * tvb, const guint16 offset, proto_tree * tree, const char * const label) { proto_tree *id_tree; proto_item *id_item; guint16 length; length = tvb_get_ntohs(tvb, offset+2); id_item = proto_tree_add_item(tree, hf_wai_identity, tvb, offset, length+4, ENC_NA); id_tree = proto_item_add_subtree(id_item, ett_wai_identity); proto_item_set_text(id_item, "%sIdentity", ((label==NULL)?"":label)); proto_tree_add_item(id_tree, hf_wai_identity_id, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(id_tree, hf_wai_identity_len, tvb, offset+2, 2, ENC_BIG_ENDIAN); proto_tree_add_item(id_tree, hf_wai_identity_data, tvb, offset+4, length, ENC_NA); return length + 4; } static gint16 dissect_certificate(tvbuff_t * tvb, const gint offset, proto_tree * tree, const gchar * const label) { proto_item *certificate_item; proto_tree *certificate_tree; proto_item *id_item; guint16 length; guint16 id; const gchar *id_name = "unknown"; id = tvb_get_ntohs(tvb, offset); if (id == 1) { id_name = "X.509 v3"; } else if (id == 2){ id_name = "GBW"; } length = tvb_get_ntohs(tvb, offset+2); certificate_item = proto_tree_add_item(tree, hf_wai_cert, tvb, offset, length+4, ENC_NA); proto_item_set_text(certificate_item, "%sCertificate", ((label==NULL)?"":label)); certificate_tree = proto_item_add_subtree(certificate_item, ett_wai_certificate); id_item = proto_tree_add_item(certificate_tree, hf_wai_cert_id, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_set_text(id_item, "Certificate Identifier: %s (%#x)", id_name, id); proto_tree_add_item(certificate_tree, hf_wai_cert_len, tvb, offset+2, 2, ENC_BIG_ENDIAN); proto_tree_add_item(certificate_tree, hf_wai_cert_data, tvb, offset+4, length, ENC_NA); return length + 4; } static guint16 dissect_ecdh_parameter(tvbuff_t * tvb, const gint offset, proto_tree * tree) { proto_item *ecdh_item; proto_tree *ecdh_tree; proto_item *ecdh_id_item; guint8 ecdh_id; guint16 ecdh_len; const gchar *id_name = "unknown"; ecdh_id = tvb_get_guint8(tvb, offset); if (ecdh_id == 1) { id_name = "OID"; } else if (ecdh_id == 2) { id_name = "Detailed parameter"; } ecdh_len = tvb_get_ntohs(tvb, offset+1); ecdh_item = proto_tree_add_item(tree, hf_wai_ecdh, tvb, offset, ecdh_len+3, ENC_NA); ecdh_tree = proto_item_add_subtree(ecdh_item, ett_wai_ecdh_param); ecdh_id_item = proto_tree_add_item(ecdh_tree, hf_wai_ecdh_id, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_set_text(ecdh_id_item, "ID: %s (%#x)", id_name, ecdh_id); proto_tree_add_item(ecdh_tree, hf_wai_ecdh_len, tvb, offset+1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ecdh_tree, hf_wai_ecdh_content, tvb, offset+3, ecdh_len, ENC_NA); return ecdh_len + 3; } static guint16 dissect_challenge(tvbuff_t *tvb, guint offset, proto_tree *tree, const gchar * const label) { proto_item *challenge_item; const guint16 challenge_length = 32; challenge_item = proto_tree_add_item(tree, hf_wai_challenge, tvb, offset, 32, ENC_NA); proto_item_append_text(challenge_item, "(%schallenge)", ((label==NULL)?"":label)); return challenge_length; } static guint16 dissect_key_data(tvbuff_t *tvb, guint offset, proto_tree *tree, const gchar *const label) { proto_item *key_data_item; proto_tree *key_data_tree; guint8 length; length = tvb_get_guint8(tvb, offset); key_data_item = proto_tree_add_item(tree, hf_wai_key_data, tvb, offset, length+1, ENC_NA); proto_item_set_text(key_data_item, "%sKey Data", ((label==NULL)?"":label)); key_data_tree = proto_item_add_subtree(key_data_item, ett_wai_key_data); proto_tree_add_item(key_data_tree, hf_wai_key_data_len, tvb, offset, 1, ENC_BIG_ENDIAN); if (length > 0) { proto_tree_add_item(key_data_tree, hf_wai_key_data_content, tvb, offset+1, length, ENC_NA); } return length + 1; } static guint dissect_multiple_certificate(tvbuff_t * tvb, guint offset, proto_tree *tree) { proto_item *multicert_item; proto_tree *multicert_tree; proto_item *nonce_1_item; proto_item *nonce_2_item; guint length; length = tvb_get_ntohs(tvb, offset+1); multicert_item = proto_tree_add_item(tree, hf_wai_cert_ver, tvb, offset, length+3, ENC_NA); multicert_tree = proto_item_add_subtree(multicert_item, ett_wai_certificate_verification); proto_tree_add_item(multicert_tree, hf_wai_attr_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(multicert_tree, hf_wai_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; nonce_1_item = proto_tree_add_item(multicert_tree, hf_wai_nonce, tvb, offset, 32, ENC_NA); offset += 32; proto_item_append_text(nonce_1_item, " 1"); nonce_2_item = proto_tree_add_item(multicert_tree, hf_wai_nonce, tvb, offset, 32, ENC_NA); offset += 32; proto_item_append_text(nonce_2_item, " 2"); proto_tree_add_item(multicert_tree, hf_wai_ver_res, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; offset += dissect_certificate(tvb, offset, multicert_tree, "1 "); proto_tree_add_item(multicert_tree, hf_wai_ver_res, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; dissect_certificate(tvb, offset, multicert_tree, "2 "); return length + 3; } static guint dissect_identity_list(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_item *id_list_item; proto_tree *id_list_tree; guint16 length; guint16 no_of_ids; guint16 i; length = tvb_get_ntohs(tvb, offset+1); id_list_item = proto_tree_add_item(tree, hf_wai_identity_list, tvb, offset, length+3, ENC_NA); id_list_tree = proto_item_add_subtree(id_list_item, ett_wai_identity_list); proto_tree_add_item(id_list_tree, hf_wai_attr_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(id_list_tree, hf_wai_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(id_list_tree, hf_wai_reserved_byte, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(id_list_tree, hf_wai_no_of_ids, tvb, offset, 2, ENC_BIG_ENDIAN); no_of_ids = tvb_get_ntohs(tvb, offset); offset += 2; for(i=0; i < no_of_ids; i++) { gchar number[4] = {0}; snprintf(number, 4, "%d", i); offset += dissect_identity(tvb, offset, id_list_tree, number); } return length + 3; } static guint16 dissect_signature_algorithm(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_item *sa_item; proto_tree *sa_tree; proto_item *param_item; proto_tree *param_tree; proto_item *alg_name_item; proto_item *sig_name_item; guint16 length; guint8 alg_id; guint8 sig_id; guint16 param_len; length = tvb_get_ntohs(tvb, offset); sa_item = proto_tree_add_item(tree, hf_wai_sign_alg, tvb, offset, length+2, ENC_NA); sa_tree = proto_item_add_subtree(sa_item, ett_wai_sign_alg); proto_tree_add_item(sa_tree, hf_wai_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; alg_name_item = proto_tree_add_item(sa_tree, hf_wai_hash_alg_id, tvb, offset, 1, ENC_BIG_ENDIAN); alg_id = tvb_get_guint8(tvb, offset); if (1 == alg_id) { proto_item_set_text(alg_name_item, "Algorithm Identifier: SHA-256 (0x01)"); } offset += 1; sig_name_item = proto_tree_add_item(sa_tree, hf_wai_sign_alg_id, tvb, offset, 1, ENC_BIG_ENDIAN); sig_id = tvb_get_guint8(tvb, offset); if (1 == sig_id) { proto_item_set_text(sig_name_item, "Signature Algorithm Identifier: ECDSA-192 (0x01)"); } offset += 1; param_len = tvb_get_ntohs(tvb, offset+1); param_item = proto_tree_add_item(sa_tree, hf_wai_param, tvb, offset, param_len+3, ENC_NA); param_tree = proto_item_add_subtree(param_item, ett_wai_parameter); proto_tree_add_item(param_tree, hf_wai_param_id, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(param_tree, hf_wai_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(param_tree, hf_wai_param_content, tvb, offset, param_len, ENC_NA); return length + 2; } static guint16 dissect_signature_value(tvbuff_t *tvb, guint offset, proto_tree *tree) { proto_item *sv_item; proto_tree *sv_tree; guint16 length = 0; length = tvb_get_ntohs(tvb, offset); sv_item = proto_tree_add_item(tree, hf_wai_sign_val, tvb, offset, length+2, ENC_NA); sv_tree = proto_item_add_subtree(sv_item, ett_wai_sign_val); proto_tree_add_item(sv_tree, hf_wai_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(sv_tree, hf_wai_sign_content, tvb, offset, length, ENC_NA); return length + 2; } static guint16 dissect_signature(tvbuff_t *tvb, guint offset, proto_tree *tree, const gchar *const label) { proto_item *ss_item; proto_tree *ss_tree; guint length = 0; length = tvb_get_ntohs(tvb, offset+1); ss_item = proto_tree_add_item(tree, hf_wai_sign, tvb, offset, length+3, ENC_NA); proto_item_set_text(ss_item, "%s", (label==NULL)?"Signature":label); ss_tree = proto_item_add_subtree(ss_item, ett_wai_sign); proto_tree_add_item(ss_tree, hf_wai_attr_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(ss_tree, hf_wai_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; offset += dissect_identity(tvb, offset, ss_tree, NULL); offset += dissect_signature_algorithm(tvb, offset, ss_tree); dissect_signature_value(tvb, offset, ss_tree); return length + 3; } static void dissect_wai_data(tvbuff_t *tvb, proto_tree *tree, guint8 subtype, guint16 lenx) { proto_item *data_item; proto_tree *data_tree; const gchar *type_name; data_item = proto_tree_add_item(tree, hf_wai_data, tvb, 0, lenx, ENC_NA); data_tree = proto_item_add_subtree (data_item, ett_wai_data); type_name = val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type"); proto_item_set_text(data_item, "%s data (%d bytes)", type_name, lenx); switch (subtype) { case WAI_SUB_PRE_AUTHENTICATION: { /* Chapter 8.1.4.6 Preauthentication [ref: 1] */ dissect_flag(tvb, 0, data_tree); dissect_uskid(tvb, 1, data_tree); dissect_addid(tvb, 2, data_tree); dissect_counter(tvb, 14, data_tree); dissect_message_auth_code(tvb, 30, data_tree); break; } case WAI_SUB_STAKEY_REQ: { /* Chapter 8.1.4.5 STAKey Establishment procedure [ref: 1] */ dissect_flag(tvb, 0, data_tree); proto_tree_add_item(data_tree, hf_wai_sta_key_id, tvb, 1, 1, ENC_BIG_ENDIAN); dissect_uskid(tvb, 2, data_tree); dissect_addid(tvb, 3, data_tree); dissect_counter(tvb, 15, data_tree); dissect_message_auth_code(tvb, 31, data_tree); break; } case WAI_SUB_AUTH_ACTIVATION: { /* Chapter 8.1.4.2.1 WAI Authentication Activation [ref: 1] */ guint16 offset = 0; dissect_flag(tvb, offset, data_tree); offset += 1; dissect_authentication_id(tvb, offset, data_tree); offset += 32; offset += dissect_identity(tvb, offset, data_tree, "Local ASU "); offset += dissect_certificate(tvb, offset, data_tree, "STE AE "); dissect_ecdh_parameter(tvb, offset, data_tree); break; } case WAI_SUB_ACCESS_AUTH_REQ: { /* Chapter 8.1.4.2.2 Access WAI Authentication Request [ref: 1] */ guint16 offset = 0; guint8 optional_field; optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3; dissect_flag(tvb, offset, data_tree); offset += 1; dissect_authentication_id(tvb, offset, data_tree); offset += 32; offset += dissect_challenge(tvb, offset, data_tree, "ASUE "); offset += dissect_key_data(tvb, offset, data_tree, "ASUE "); offset += dissect_identity(tvb, offset, data_tree, "STA AE "); offset += dissect_certificate(tvb, offset, data_tree, "STA ASUE "); offset += dissect_ecdh_parameter(tvb, offset, data_tree); if (optional_field) { offset += dissect_identity_list(tvb, offset, data_tree); } dissect_signature(tvb, offset, data_tree, "ASUE Signature"); break; } case WAI_SUB_ACCESS_AUTH_RESP: { /* Chapter 8.1.4.2.5 Access WAI Authentication Response [ref: 1] */ guint16 offset = 0; guint8 optional_field; optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3; dissect_flag(tvb, offset, data_tree); offset += 1; offset += dissect_challenge(tvb, offset, data_tree, "ASUE "); offset += dissect_challenge(tvb, offset, data_tree, "AE "); proto_tree_add_item(data_tree, hf_wai_access_res, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; offset += dissect_key_data(tvb, offset, data_tree, "ASUE "); offset += dissect_key_data(tvb, offset, data_tree, "AE "); offset += dissect_identity(tvb, offset, data_tree, "STA AE "); offset += dissect_identity(tvb, offset, data_tree, "STA ASUE "); if (optional_field) { guint length = 0; offset += dissect_multiple_certificate(tvb, offset, data_tree); offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by ASUE"); length = tvb_get_ntohs(tvb, offset+1); if (length + 3 + offset + 1 < lenx) offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by AE"); } dissect_signature(tvb, offset, data_tree, "AE Signature"); break; } case WAI_SUB_CERT_AUTH_REQ: { /* Chapter 8.1.4.2.3 Certificate Authentication Request [ref: 1] */ guint16 offset = 0; guint8 optional_field; optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3; dissect_addid(tvb, offset, data_tree); offset += 12; offset += dissect_challenge(tvb, offset, data_tree, "AE "); offset += dissect_challenge(tvb, offset, data_tree, "ASUE "); offset += dissect_certificate(tvb, offset, data_tree, "STE ASUE "); offset += dissect_certificate(tvb, offset, data_tree, "STE AE "); if (optional_field) { dissect_identity_list(tvb, offset, data_tree); } break; } case WAI_SUB_CERT_AUTH_RESP: { /* Chapter 8.1.4.2.4 Certificate Authentication Response [ref: 1] */ guint16 offset = 0; dissect_addid(tvb, offset, data_tree); offset += 12; offset += dissect_multiple_certificate(tvb, offset, data_tree); offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by ASUE"); if (offset < lenx) dissect_signature(tvb, offset, data_tree, "Server Signature trusted by AE"); break; } case WAI_SUB_UNICAST_KEY_REQ: { /* Chapter 8.1.4.3.1 Unicast Key Negotiation Request [ref: 1] */ dissect_flag(tvb, 0, data_tree); dissect_bkid(tvb, 1, data_tree); dissect_uskid(tvb, 17, data_tree); dissect_addid(tvb, 18, data_tree); dissect_challenge(tvb, 30, data_tree , "AE "); break; } case WAI_SUB_UNICAST_KEY_RESP: { /* Chapter 8.1.4.3.2 Unicast Key Negotiation Response [ref: 1] */ tvbuff_t *next_tvb; guint length = 0; dissect_flag(tvb, 0, data_tree); dissect_bkid(tvb, 1, data_tree); dissect_uskid(tvb, 17, data_tree); dissect_addid(tvb, 18, data_tree); dissect_challenge(tvb, 30, data_tree, "ASUE "); dissect_challenge(tvb, 62, data_tree, "AE "); next_tvb = tvb_new_subset_remaining(tvb, 96); length = tvb_reported_length(next_tvb); dissect_wie(next_tvb, 0, length-20, data_tree); dissect_message_auth_code(next_tvb, length-20, data_tree); break; } case WAI_SUB_UNICAST_KEY_CONFIRM: { /* Chapter 8.1.4.3.3 Unicast Key Negotiation Confirmation [ref: 1] */ tvbuff_t *next_tvb; guint length = 0; dissect_flag(tvb, 0, data_tree); dissect_bkid(tvb, 1, data_tree); dissect_uskid(tvb, 17, data_tree); dissect_addid(tvb, 18, data_tree); dissect_challenge(tvb, 30, data_tree, "ASUE "); next_tvb = tvb_new_subset_remaining(tvb, 62); length = tvb_reported_length(next_tvb); dissect_wie(next_tvb, 0, length-20, data_tree); dissect_message_auth_code(next_tvb, length-20, data_tree); break; } case WAI_SUB_MULTICAST_ANNOUNCE: { /* Chapter 8.1.4.4.1 Multicast Key/STAKey Announcement [ref: 1] */ guint16 offset = 0; dissect_flag(tvb, offset, data_tree); offset += 1; dissect_mskid(tvb, offset, data_tree); offset += 1; dissect_uskid(tvb, offset, data_tree); offset += 1; dissect_addid(tvb, offset, data_tree); offset += 12; proto_tree_add_item(data_tree, hf_wai_data_pack_num, tvb, offset, 16, ENC_NA); offset += 16; dissect_key_announcement_identifier(tvb, offset, data_tree); offset += 16; offset += dissect_key_data(tvb, offset, data_tree, NULL); dissect_message_auth_code(tvb, offset, data_tree); break; } case WAI_SUB_MULTICAST_ANNOUNCE_RESP: { /* Chapter 8.1.4.4.2 Multicast Key/STAKey Announcement Response [ref: 1] */ dissect_flag(tvb, 0, data_tree); dissect_mskid(tvb, 1, data_tree); dissect_uskid(tvb, 2, data_tree); dissect_addid(tvb, 3, data_tree); dissect_key_announcement_identifier(tvb, 15, data_tree); dissect_message_auth_code(tvb, 31, data_tree); break; } default: break; } } static int dissect_wai(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { /* Format of WAPI protocol packet in WAI authentication system 0 2 3 4 6 8 10 11 12 ------------------------------------------------------------------------------- | Ver. | Type | Subtype | Reserved | Length | packet | fragm. | flag | data | | | seq. no | seq. no | | |-----------------------------------------------------------------------------| Figure 18 from [ref:1] */ #define WAI_MESSAGE_LENGTH 12 /*Length of all fields without 'Data' field*/ #define WAI_DATA_OFFSET WAI_MESSAGE_LENGTH guint16 version; guint8 subtype; guint16 length; guint16 packet_num; guint8 fragment_num; guint8 flags; fragment_head *frag_msg; proto_tree *wai_tree = NULL; tvbuff_t *next_tvb; tvbuff_t *new_tvb; const gchar *subtype_name = "Unknown type"; length = tvb_get_ntohs(tvb, 6)-WAI_MESSAGE_LENGTH; subtype = tvb_get_guint8(tvb, 3); /* quick sanity check */ if ((length != tvb_reported_length (tvb)-WAI_MESSAGE_LENGTH) || (subtype > WAI_SUB_MULTICAST_ANNOUNCE_RESP)) { return 0; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "WAI"); col_clear(pinfo->cinfo, COL_INFO); version = tvb_get_ntohs(tvb, 0); if (version == 1) { subtype_name = val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type"); } col_append_str(pinfo->cinfo, COL_INFO, subtype_name); /* Field lengths and offsets in WAI protocol described above */ packet_num = tvb_get_ntohs(tvb, 8); fragment_num = tvb_get_guint8(tvb, 10); flags = tvb_get_guint8(tvb, 11); if (tree) { proto_item *wai_item; wai_item = proto_tree_add_item(tree, proto_wai, tvb, 0, -1, ENC_NA); proto_item_set_text (wai_item, "WAI Protocol (%s)", val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type")); wai_tree = proto_item_add_subtree(wai_item, ett_wai); /* Field lengths and offsets in WAI protocol described above */ proto_tree_add_item(wai_tree, hf_wai_version, tvb, 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_type, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_subtype, tvb, 3, 1, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_reserved, tvb, 4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_length, tvb, 6, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_seq, tvb, 8, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_fragm_seq, tvb, 10, 1, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_flag, tvb, 11, 1, ENC_BIG_ENDIAN); } frag_msg = fragment_add_seq_check (&wai_reassembly_table, tvb, WAI_DATA_OFFSET, pinfo, packet_num, NULL, fragment_num, length, flags); next_tvb = tvb_new_subset_remaining(tvb, WAI_DATA_OFFSET); /* Replace INFO column if message is fragmented and call data dissector */ if (flags) { col_add_fstr(pinfo->cinfo, COL_INFO, "Fragment (%d) of message, data not dissected", fragment_num); process_reassembled_data(tvb, WAI_DATA_OFFSET, pinfo, "Reassembled WAI", frag_msg, &wai_frag_items, NULL, wai_tree); call_data_dissector(next_tvb, pinfo, tree); } else { /* If this is the last fragment of fragmented message, then reassamble and dissect otherwise only dissect */ if (fragment_num > 0) { new_tvb = process_reassembled_data(tvb, WAI_DATA_OFFSET, pinfo, "Reassembled WAI", frag_msg, &wai_frag_items, NULL, wai_tree); if (new_tvb) { col_set_str(pinfo->cinfo, COL_INFO, "Last fragment of message, data dissected"); col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", subtype_name); next_tvb=new_tvb; length = tvb_reported_length (next_tvb); } } /* dissect Data field of WAI packet */ if (tree) { dissect_wai_data(next_tvb, wai_tree, subtype, length); } } return tvb_captured_length(tvb); } void proto_register_wai(void) { static hf_register_info hf[] = { { &hf_wai_version, { "Version", "wai.version", FT_UINT16, BASE_DEC, NULL, 0x0, "Version of authentication infrastructure", HFILL }}, { &hf_wai_type, { "Type", "wai.type", FT_UINT8, BASE_HEX, VALS(wai_type_names), 0x0, "Protocol type", HFILL }}, { &hf_wai_subtype, { "Subtype", "wai.subtype", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &wai_subtype_names_ext, 0x0, NULL, HFILL }}, { &hf_wai_reserved, { "Reserved", "wai.reserved", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_wai_length, { "Length", "wai.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_wai_seq, { "Sequence number", "wai.seq", FT_UINT16, BASE_DEC, NULL, 0x0, "Packet sequence number", HFILL }}, { &hf_wai_fragm_seq, { "Fragment sequence number", "wai.fragm.seq", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_wai_flag, { "Flag", "wai.flag", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_wai_data, { "Data", "wai.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_bk_rekeying_flag, {"BK rekeying", "wai.bk.rekeying.flag", FT_BOOLEAN, 8, TFS (&wai_bk_rekeying_flag), FLAG_BIT0, "BK rekeying flag", HFILL }}, { &hf_wai_preauthentication_flag, {"Pre-Authentication", "wai.preauthentication.flag", FT_BOOLEAN, 8, TFS (&wai_preauthentication_flag), FLAG_BIT1, "Pre-Authentication flag", HFILL }}, { &hf_wai_certificate_flag, {"Certificate", "wai.certificate.flag", FT_BOOLEAN, 8, TFS (&wai_certificate_flag), FLAG_BIT2, "Certificate flag", HFILL }}, { &hf_wai_optional_flag, {"Optional", "wai.optional.flag", FT_BOOLEAN, 8, TFS (&wai_optional_flag), FLAG_BIT3, "Optional flag", HFILL }}, { &hf_wai_usk_rekeying_flag, {"USK rekeying", "wai.usk.rekeying.flag", FT_BOOLEAN, 8, TFS (&wai_usk_rekeying_flag), FLAG_BIT4, "USK rekeying flag", HFILL }}, { &hf_wai_negotiation_flag, {"STA negotiation", "wai.negotiation.flag", FT_BOOLEAN, 8, TFS (&wai_negotiation_flag), FLAG_BIT5, "STA negotiation flag", HFILL }}, { &hf_wai_revoking_flag, {"STA revoking", "wai.revoking.flag", FT_BOOLEAN, 8, TFS (&wai_revoking_flag), FLAG_BIT6, "STA revoking flag", HFILL }}, { &hf_wai_reserved_flag, {"Reserved", "wai.reserved.flag", FT_BOOLEAN, 8, TFS (&wai_reserved_flag), FLAG_BIT7, "Reserved flag", HFILL }}, { &hf_wai_attr_type, { "Type", "wai.attrtype", FT_UINT8, BASE_HEX, VALS(wai_attr_type_names), 0x0, "Attribute type", HFILL }}, { &hf_wai_cert, {"Certificate", "wai.cert", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_cert_id, {"Id", "wai.cert.id", FT_UINT16, BASE_HEX, NULL, 0x0, "Certificate Id", HFILL }}, { &hf_wai_cert_data, {"Data", "wai.cert.data", FT_BYTES, BASE_NONE, NULL, 0x0, "Certificate data", HFILL }}, { &hf_wai_cert_len, {"Length", "wai.cert.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Certificate length", HFILL }}, { &hf_wai_addid, {"ADDID", "wai.addid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_ae_mac, {"AE MAC", "wai.ae.mac", FT_ETHER, BASE_NONE, NULL, 0x0, "AE MAC address", HFILL }}, { &hf_wai_asue_mac, {"ASUE MAC", "wai.asue.mac", FT_ETHER, BASE_NONE, NULL, 0x0, "ASUE MAC address", HFILL }}, { &hf_wai_bkid, {"BKID", "wai.bkid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_uskid, {"USKID", "wai.uskid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_wie, {"WIE from ASUE", "wai.wie", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_message_auth_code, {"Message Authentication Code", "wai.message.auth.code", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_mskid, {"MSKID/STAKeyID", "wai.mskid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_data_pack_num, {"Data packet number", "wai.data.packet.num", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_key_data, {"Key Data", "wai.key.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_key_data_len, {"Length", "wai.key.data.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Key data length", HFILL }}, { &hf_wai_key_data_content, {"Content", "wai.key.data.content", FT_BYTES, BASE_NONE, NULL, 0x0, "Key data content", HFILL }}, { &hf_wai_key_ann_id, {"Key Announcement Identifier", "wai.key.ann.id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_auth_id, {"Authentication Identifier", "wai.auth.id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_identity, {"Identifier", "wai.identity", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_identity_id, {"Id", "wai.identity.id", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_wai_identity_len, {"Length", "wai.identity.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Identity length", HFILL }}, { &hf_wai_identity_data, {"Data", "wai.identity.data", FT_BYTES, BASE_NONE, NULL, 0x0, "Identity data", HFILL }}, { &hf_wai_ecdh, {"ECDH Parameter", "wai.ecdhp", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_ecdh_id, {"ID", "wai.edch.id", FT_UINT8, BASE_HEX, NULL, 0x0, "ECDH Parameter Identifier", HFILL }}, { &hf_wai_ecdh_len, {"Length", "wai.ecdh.len", FT_UINT16, BASE_DEC, NULL, 0x0, "ECDH Parameter Length", HFILL }}, { &hf_wai_ecdh_content, {"Content", "wai.ecdh.content", FT_BYTES, BASE_NONE, NULL, 0x0, "ECDH Parameter Content", HFILL }}, { &hf_wai_counter, {"Replay counter", "wai.counter", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_sta_key_id, {"STAKeyID", "wai.sta.key.id", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_wai_challenge, {"Challenge", "wai.challenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_cert_ver, {"Multiple Certificate Verification Result", "wai.cert.ver", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_nonce, {"Nonce", "wai.nonce", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_ver_res, {"Verification result", "wai.ver.res", FT_UINT8, BASE_HEX, VALS(wai_ver_res_names), 0x0, NULL, HFILL }}, { &hf_wai_sign_alg, {"Signature Algorithm", "wai.sign.alg", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_hash_alg_id, {"Hash Algorithm Identifier", "wai.hash.alg.id", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_wai_sign_alg_id, {"Signature Algorithm Identifier", "wai.sign.alg.id", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_wai_param, {"Parameter", "wai.param", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_param_id, {"Parameter Identifier", "wai.param.id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_param_content, {"Parameter Content", "wai.param.content", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_sign_val, {"Signature Value", "wai.sign.val", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_sign_content, {"Signature Content", "wai.sign.content", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_sign, {"Signature", "wai.sign", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_wai_identity_list, {"ASU List trusted by ASUE", "wai.identity_list", FT_BYTES, BASE_NONE, NULL, 0x0, "Identity list", HFILL }}, { &hf_wai_reserved_byte, {"Reserved", "wai.reserved.byte", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_wai_no_of_ids, {"Number of Identities", "wai.no.of.ids", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_wai_access_res, {"Access result", "wai.access_result", FT_UINT8, BASE_HEX, VALS(wai_access_res_names), 0x0, NULL, HFILL }}, { &hf_wai_fragments, {"Message fragments", "wai.fragments", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }}, { &hf_wai_fragment, {"Message fragment", "wai.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }}, { &hf_wai_fragment_overlap, {"Message fragment overlap", "wai.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }}, { &hf_wai_fragment_overlap_conflicts, {"Message fragment overlapping with conflicting data", "wai.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }}, { &hf_wai_fragment_multiple_tails, {"Message has multiple tail fragments", "wai.fragment.multiple_tails", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }}, { &hf_wai_fragment_too_long_fragment, {"Message fragment too long", "wai.fragment.too_long_fragment", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }}, { &hf_wai_fragment_error, {"Message defragmentation error", "wai.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }}, { &hf_wai_fragment_count, {"Message fragment count", "wai.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}, { &hf_wai_reassembled_in, {"Reassembled in", "wai.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }}, { &hf_wai_reassembled_length, {"Reassembled length", "wai.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }} }; static gint *ett[] = { &ett_wai, &ett_wai_data, &ett_wai_flags, &ett_wai_certificate, &ett_wai_mac, &ett_wai_identity, &ett_wai_key_data, &ett_wai_ecdh_param, &ett_wai_certificate_verification, &ett_wai_identity_list, &ett_wai_sign, &ett_wai_sign_alg, &ett_wai_sign_val, &ett_wai_parameter, &ett_wai_fragment, &ett_wai_fragments }; proto_wai = proto_register_protocol("WAI Protocol", "WAI", "wai"); proto_register_field_array(proto_wai, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); reassembly_table_register(&wai_reassembly_table, &addresses_reassembly_table_functions); wai_handle = register_dissector("wai", dissect_wai, proto_wai); } void proto_reg_handoff_wai(void) { dissector_add_uint("ethertype", ETHERTYPE_WAI, wai_handle); } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */