forked from osmocom/wireshark
![Michael Mann](/assets/img/avatar_default.png)
Similar to the "tcp.port" changes in I99604f95d426ad345f4b494598d94178b886eb67, convert dissectors that use "udp.port". More cleanup done on dissectors that use both TCP and UDP dissector tables, so that less preference callbacks exist. Change-Id: If07be9b9e850c244336a7069599cd554ce312dd3 Reviewed-on: https://code.wireshark.org/review/18120 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
1866 lines
49 KiB
C
1866 lines
49 KiB
C
/* packet-mikey.c
|
|
* Routines for Multimedia Internet KEYing dissection
|
|
* Copyright 2007, Mikael Magnusson <mikma@users.sourceforge.net>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Ref:
|
|
* http://tools.ietf.org/html/rfc3830 MIKEY
|
|
* http://tools.ietf.org/html/rfc6043 MIKEY-TICKET (ID role required for SAKKE)
|
|
* http://tools.ietf.org/html/rfc6509 MIKEY-SAKKE
|
|
*/
|
|
|
|
/*
|
|
* TODO
|
|
* tvbuff offset in 32-bit variable.
|
|
* Support CHASH
|
|
* Decode Mikey-PK and Mikey-RSA-R with NULL encryption
|
|
*/
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <epan/packet.h>
|
|
#include <epan/asn1.h>
|
|
#include <epan/proto_data.h>
|
|
#include "packet-x509af.h"
|
|
|
|
void proto_register_mikey(void);
|
|
void proto_reg_handoff_mikey(void);
|
|
|
|
#define PORT_MIKEY 2269
|
|
|
|
static const value_string on_off_vals[] = {
|
|
{ 0, "Off" },
|
|
{ 1, "On" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum data_type_t {
|
|
MIKEY_TYPE_PSK_INIT = 0,
|
|
MIKEY_TYPE_PSK_RESP,
|
|
MIKEY_TYPE_PK_INIT,
|
|
MIKEY_TYPE_PK_RESP,
|
|
MIKEY_TYPE_DH_INIT,
|
|
MIKEY_TYPE_DH_RESP,
|
|
MIKEY_TYPE_ERROR,
|
|
MIKEY_TYPE_DHHMAC_INIT,
|
|
MIKEY_TYPE_DHHMAC_RESP,
|
|
MIKEY_TYPE_RSA_R_INIT,
|
|
MIKEY_TYPE_RSA_R_RESP,
|
|
MIKEY_TYPE_SAKKE_INIT = 26,
|
|
MIKEY_TYPE_SAKKE_RESP
|
|
};
|
|
|
|
static const value_string data_type_vals[] = {
|
|
{ MIKEY_TYPE_PSK_INIT, "Pre-shared" },
|
|
{ MIKEY_TYPE_PSK_RESP, "PSK ver msg" },
|
|
{ MIKEY_TYPE_PK_INIT, "Public key" },
|
|
{ MIKEY_TYPE_PK_RESP, "PK ver msg" },
|
|
{ MIKEY_TYPE_DH_INIT, "D-H init" },
|
|
{ MIKEY_TYPE_DH_RESP, "D-H resp" },
|
|
{ MIKEY_TYPE_ERROR, "Error" },
|
|
{ MIKEY_TYPE_DHHMAC_INIT, "DHHMAC init" },
|
|
{ MIKEY_TYPE_DHHMAC_RESP, "DHHMAC resp" },
|
|
{ MIKEY_TYPE_RSA_R_INIT, "RSA-R I_MSG" },
|
|
{ MIKEY_TYPE_RSA_R_RESP, "RSA-R R_MSG" },
|
|
{ MIKEY_TYPE_SAKKE_INIT, "SAKKE" },
|
|
{ MIKEY_TYPE_SAKKE_RESP, "CS Id map Update" },
|
|
{ 0, NULL }
|
|
};
|
|
static value_string_ext data_type_vals_ext = VALUE_STRING_EXT_INIT(data_type_vals);
|
|
|
|
enum cs_id_map_t {
|
|
CS_ID_SRTP = 0
|
|
};
|
|
|
|
static const value_string cs_id_map_vals[] = {
|
|
{ CS_ID_SRTP, "SRTP-ID" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum payload_t {
|
|
PL_HDR = -1,
|
|
PL_LAST,
|
|
PL_KEMAC,
|
|
PL_PKE,
|
|
PL_DH,
|
|
PL_SIGN,
|
|
PL_T,
|
|
PL_ID,
|
|
PL_CERT,
|
|
PL_CHASH,
|
|
PL_V,
|
|
PL_SP,
|
|
PL_RAND,
|
|
PL_ERR,
|
|
PL_TR = 13, /* MIKEY-TICKET (6043) */
|
|
PL_IDR,
|
|
PL_RANDR,
|
|
PL_TP,
|
|
PL_TICKET,
|
|
PL_KEY_DATA = 20,
|
|
PL_GENERAL_EXT,
|
|
PL_SAKKE = 26,
|
|
PL_MAX
|
|
};
|
|
|
|
#define PL_HDR_TEXT "Common Header (HDR)"
|
|
#define PL_LAST_TEXT "Last payload"
|
|
#define PL_KEMAC_TEXT "Key Data Transport (KEMAC)"
|
|
#define PL_PKE_TEXT "Envelope Data (PKE)"
|
|
#define PL_DH_TEXT "DH Data (DH)"
|
|
#define PL_SIGN_TEXT "Signature (SIGN)"
|
|
#define PL_T_TEXT "Timestamp (T)"
|
|
#define PL_ID_TEXT "ID"
|
|
#define PL_CERT_TEXT "Certificate (CERT)"
|
|
#define PL_CHASH_TEXT "CHASH"
|
|
#define PL_V_TEXT "Ver msg (V)"
|
|
#define PL_SP_TEXT "Security Policy (SP)"
|
|
#define PL_RAND_TEXT "RAND"
|
|
#define PL_ERR_TEXT "Error (ERR)"
|
|
#define PL_KEY_DATA_TEXT "Key data (KEY)"
|
|
#define PL_IDR_TEXT "IDR"
|
|
#define PL_GENERAL_EXT_TEXT "General Extension (EXT)"
|
|
#define PL_SAKKE_TEXT "SAKKE Encapsulated Data (SAKKE)"
|
|
|
|
static const value_string payload_vals[] = {
|
|
{ PL_HDR, PL_HDR_TEXT },
|
|
{ PL_LAST, PL_LAST_TEXT },
|
|
{ PL_KEMAC, PL_KEMAC_TEXT },
|
|
{ PL_PKE, PL_PKE_TEXT },
|
|
{ PL_DH, PL_DH_TEXT },
|
|
{ PL_SIGN, PL_SIGN_TEXT },
|
|
{ PL_T, PL_T_TEXT },
|
|
{ PL_ID, PL_ID_TEXT },
|
|
{ PL_CERT, PL_CERT_TEXT },
|
|
{ PL_CHASH, PL_CHASH_TEXT },
|
|
{ PL_V, PL_V_TEXT },
|
|
{ PL_SP, PL_SP_TEXT },
|
|
{ PL_RAND, PL_RAND_TEXT },
|
|
{ PL_ERR, PL_ERR_TEXT },
|
|
{ PL_IDR, PL_IDR_TEXT },
|
|
{ PL_KEY_DATA, PL_KEY_DATA_TEXT },
|
|
{ PL_GENERAL_EXT, PL_GENERAL_EXT_TEXT },
|
|
{ PL_SAKKE, PL_SAKKE_TEXT },
|
|
{ 0, NULL }
|
|
};
|
|
#if 0 /* First entry (PL_HDR) is -1 and there are gaps so this doesn't work */
|
|
static value_string_ext payload_vals_ext = VALUE_STRING_EXT_INIT(payload_vals);
|
|
#endif
|
|
|
|
enum ts_type_t {
|
|
T_NTP_UTC = 0,
|
|
T_NTP,
|
|
T_COUNTER
|
|
};
|
|
|
|
static const value_string ts_type_vals[] = {
|
|
{ T_NTP_UTC, "NTP-UTC" },
|
|
{ T_NTP, "NTP" },
|
|
{ T_COUNTER, "COUNTER" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum encr_alg_t {
|
|
ENCR_NULL = 0,
|
|
ENCR_AES_CM_128,
|
|
ENCR_AES_KW_128
|
|
};
|
|
|
|
static const value_string encr_alg_vals[] = {
|
|
{ ENCR_NULL, "NULL" },
|
|
{ ENCR_AES_CM_128, "AES-CM-128" },
|
|
{ ENCR_AES_KW_128, "AES-KW-128" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum oakley_t {
|
|
DH_OAKLEY_5 = 0,
|
|
DH_OAKLEY_1,
|
|
DH_OAKLEY_2
|
|
};
|
|
|
|
static const value_string oakley_vals[] = {
|
|
{ DH_OAKLEY_5, "OAKLEY 5" },
|
|
{ DH_OAKLEY_1, "OAKLEY 1" },
|
|
{ DH_OAKLEY_2, "OAKLEY 2" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum mac_alg_t {
|
|
MAC_NULL = 0,
|
|
MAC_HMAC_SHA_1_160
|
|
};
|
|
|
|
static const value_string mac_alg_vals[] = {
|
|
{ MAC_NULL, "NULL" },
|
|
{ MAC_HMAC_SHA_1_160, "HMAC-SHA-1-160" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum pke_c_t {
|
|
PKE_C_NO_CACHE = 0,
|
|
PKE_C_CACHE,
|
|
PKE_C_CACHE_CSB
|
|
};
|
|
|
|
static const value_string pke_c_vals[] = {
|
|
{ PKE_C_NO_CACHE, "No cache" },
|
|
{ PKE_C_CACHE, "Cache" },
|
|
{ PKE_C_CACHE_CSB, "Cache for CSB" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum sign_s_t {
|
|
SIGN_S_PKCS1 = 0,
|
|
SIGN_S_PSS,
|
|
SIGN_S_ECCSI
|
|
};
|
|
|
|
static const value_string sign_s_vals[] = {
|
|
{ SIGN_S_PKCS1, "RSA/PKCS#1/1.5" },
|
|
{ SIGN_S_PSS, "RSA/PSS" },
|
|
{ SIGN_S_ECCSI, "ECCSI" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum id_type_t {
|
|
ID_TYPE_NAI = 0,
|
|
ID_TYPE_URI,
|
|
ID_TYPE_BYTE_STRING
|
|
};
|
|
|
|
static const value_string id_type_vals[] = {
|
|
{ ID_TYPE_NAI, "NAI" },
|
|
{ ID_TYPE_URI, "URI" },
|
|
{ ID_TYPE_BYTE_STRING, "Byte string" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum id_role_t {
|
|
ID_ROLE_RESERVED = 0,
|
|
ID_ROLE_INIT,
|
|
ID_ROLE_RESP,
|
|
ID_ROLE_KMS,
|
|
ID_ROLE_PSK,
|
|
ID_ROLE_APP,
|
|
ID_ROLE_INIT_KMS,
|
|
ID_ROLE_RESP_KMS
|
|
};
|
|
|
|
static const value_string id_role_vals[] = {
|
|
{ ID_ROLE_RESERVED, "Reserved" },
|
|
{ ID_ROLE_INIT, "Initiator (IDRi)" },
|
|
{ ID_ROLE_RESP, "Responder (IDRr)" },
|
|
{ ID_ROLE_KMS, "KMS (IDRkms)" },
|
|
{ ID_ROLE_PSK, "Pre-Shared Key (IDRpsk)" },
|
|
{ ID_ROLE_APP, "Application (IDRapp)" },
|
|
{ ID_ROLE_INIT_KMS, "Initiator's KMS (IDRkmsi)" },
|
|
{ ID_ROLE_RESP_KMS, "Responder's KMS (IDRkmsr)" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum cert_type_t {
|
|
CERT_TYPE_X509V3 = 0,
|
|
CERT_TYPE_X509V3_URL,
|
|
CERT_TYPE_X509V3_SIGN,
|
|
CERT_TYPE_X509V3_ENCR
|
|
};
|
|
|
|
static const value_string cert_type_vals[] = {
|
|
{ CERT_TYPE_X509V3, "X.509v3" },
|
|
{ CERT_TYPE_X509V3_URL, "X.509v3 URL" },
|
|
{ CERT_TYPE_X509V3_SIGN, "X.509v3 Sign" },
|
|
{ CERT_TYPE_X509V3_ENCR, "X.509v3 Encr" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum srtp_policy_type_t {
|
|
SP_ENCR_ALG,
|
|
SP_ENCR_LEN,
|
|
SP_AUTH_ALG,
|
|
SP_AUTH_KEY_LEN,
|
|
SP_SALT_LEN,
|
|
SP_PRF,
|
|
SP_KD_RATE,
|
|
SP_SRTP_ENCR,
|
|
SP_SRTCP_ENCR,
|
|
SP_FEC,
|
|
SP_SRTP_AUTH,
|
|
SP_AUTH_TAG_LEN,
|
|
SP_SRTP_PREFIX,
|
|
SP_MAX
|
|
};
|
|
|
|
#define SP_TEXT_ENCR_ALG "Encryption algorithm"
|
|
#define SP_TEXT_ENCR_LEN "Session Encr. key length"
|
|
#define SP_TEXT_AUTH_ALG "Authentication algorithm"
|
|
#define SP_TEXT_AUTH_KEY_LEN "Session Auth. key length"
|
|
#define SP_TEXT_SALT_LEN "Session Salt key length"
|
|
#define SP_TEXT_PRF "SRTP Pseudo Random Function"
|
|
#define SP_TEXT_KD_RATE "Key derivation rate"
|
|
#define SP_TEXT_SRTP_ENCR "SRTP encryption"
|
|
#define SP_TEXT_SRTCP_ENCR "SRTCP encryption"
|
|
#define SP_TEXT_FEC "Sender's FEC order"
|
|
#define SP_TEXT_SRTP_AUTH "SRTP authentication"
|
|
#define SP_TEXT_AUTH_TAG_LEN "Authentication tag length"
|
|
#define SP_TEXT_SRTP_PREFIX "SRTP prefix length"
|
|
|
|
#if 0
|
|
static const value_string srtp_policy_type_vals[] = {
|
|
{ SP_ENCR_ALG, SP_TEXT_ENCR_ALG },
|
|
{ SP_ENCR_LEN, SP_TEXT_ENCR_LEN },
|
|
{ SP_AUTH_ALG, SP_TEXT_AUTH_ALG },
|
|
{ SP_AUTH_KEY_LEN, SP_TEXT_AUTH_KEY_LEN },
|
|
{ SP_SALT_LEN, SP_TEXT_SALT_LEN },
|
|
{ SP_PRF, SP_TEXT_PRF },
|
|
{ SP_KD_RATE, SP_TEXT_KD_RATE },
|
|
{ SP_SRTP_ENCR, SP_TEXT_SRTP_ENCR },
|
|
{ SP_SRTCP_ENCR, SP_TEXT_SRTCP_ENCR },
|
|
{ SP_FEC, SP_TEXT_FEC },
|
|
{ SP_SRTP_AUTH, SP_TEXT_SRTP_AUTH },
|
|
{ SP_AUTH_TAG_LEN, SP_TEXT_AUTH_TAG_LEN },
|
|
{ SP_SRTP_PREFIX, SP_TEXT_SRTP_PREFIX },
|
|
{ 0, NULL }
|
|
};
|
|
#endif
|
|
|
|
enum sp_encr_alg_t {
|
|
SP_ENCR_NULL = 0,
|
|
SP_ENCR_AES_CM,
|
|
SP_ENCR_AES_F8
|
|
};
|
|
|
|
static const value_string sp_encr_alg_vals[] = {
|
|
{ SP_ENCR_NULL, "NULL" },
|
|
{ SP_ENCR_AES_CM, "AES-CM" },
|
|
{ SP_ENCR_AES_F8, "AES-F8" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum sp_auth_alg_t {
|
|
SP_AUTH_NULL = 0,
|
|
SP_AUTH_HMAC_SHA_1
|
|
};
|
|
|
|
static const value_string sp_auth_alg_vals[] = {
|
|
{ SP_AUTH_NULL, "NULL" },
|
|
{ SP_AUTH_HMAC_SHA_1, "HMAC-SHA-1" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum sp_prf_t {
|
|
SP_PRF_AES_CM = 0
|
|
};
|
|
|
|
static const value_string sp_prf_vals[] = {
|
|
{ SP_PRF_AES_CM, "AES-CM" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum sp_fec_t {
|
|
SP_FEC_SRTP = 0
|
|
};
|
|
|
|
static const value_string sp_fec_vals[] = {
|
|
{ SP_FEC_SRTP, "FEC-SRTP" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum sp_prot_t {
|
|
SP_PROT_TYPE_SRTP = 0
|
|
};
|
|
|
|
static const value_string sp_prot_type_vals[] = {
|
|
{ SP_PROT_TYPE_SRTP, "SRTP" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum prf_func_t {
|
|
PRF_FUNC_MIKEY_1 = 0
|
|
};
|
|
|
|
static const value_string prf_func_vals[] = {
|
|
{ PRF_FUNC_MIKEY_1, "MIKEY-1" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum kv_t {
|
|
KV_NULL = 0,
|
|
KV_SPI,
|
|
KV_INTERVAL
|
|
};
|
|
|
|
static const value_string kv_vals[] = {
|
|
{ KV_NULL, "Null" },
|
|
{ KV_SPI, "SPI/MKI" },
|
|
{ KV_INTERVAL, "Interval" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum kd_t {
|
|
KD_TGK = 0,
|
|
KD_TGK_SALT,
|
|
KD_TEK,
|
|
KD_TEK_SALT
|
|
};
|
|
|
|
static const value_string kd_vals[] = {
|
|
{ KD_TGK, "TGK" },
|
|
{ KD_TGK_SALT, "TGK+SALT" },
|
|
{ KD_TEK, "TEK" },
|
|
{ KD_TEK_SALT, "TEK+SALT" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum err_t {
|
|
ERR_AUTH_FAILURE = 0,
|
|
ERR_INVALID_TS,
|
|
ERR_INVALID_PRF,
|
|
ERR_INVALID_MAC,
|
|
ERR_INVALID_EA,
|
|
ERR_INVALID_HA,
|
|
ERR_INVALID_DH,
|
|
ERR_INVALID_ID,
|
|
ERR_INVALID_CERT,
|
|
ERR_INVALID_SP,
|
|
ERR_INVALID_SPPAR,
|
|
ERR_INVALID_DT,
|
|
ERR_UNKNOWN
|
|
};
|
|
|
|
static const value_string err_vals[] = {
|
|
{ ERR_AUTH_FAILURE, "Authentication failure" },
|
|
{ ERR_INVALID_TS, "Invalid timestamp" },
|
|
{ ERR_INVALID_PRF, "PRF function not supported" },
|
|
{ ERR_INVALID_MAC, "MAC algorithm not supported" },
|
|
{ ERR_INVALID_EA, "Encryption algorithm not supported" },
|
|
{ ERR_INVALID_HA, "Hash function not supported" },
|
|
{ ERR_INVALID_DH, "DH group not supported" },
|
|
{ ERR_INVALID_ID, "ID not supported" },
|
|
{ ERR_INVALID_CERT, "Certificate not supported" },
|
|
{ ERR_INVALID_SP, "SP type not supported" },
|
|
{ ERR_INVALID_SPPAR, "SP parameters not supported" },
|
|
{ ERR_INVALID_DT, "Data type not supported" },
|
|
{ ERR_UNKNOWN, "Unspecified error" },
|
|
{ 0, NULL }
|
|
};
|
|
static value_string_ext err_vals_ext = VALUE_STRING_EXT_INIT(err_vals);
|
|
|
|
enum genext_t {
|
|
GEN_EXT_VENDOR_ID = 0,
|
|
GEN_EXT_SDP_ID
|
|
};
|
|
|
|
static const value_string genext_type_vals[] = {
|
|
{ GEN_EXT_VENDOR_ID, "Vendor-ID" },
|
|
{ GEN_EXT_SDP_ID, "SDP-IDs" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
enum {
|
|
/* HDR */
|
|
POS_HDR_VERSION=0,
|
|
POS_HDR_DATA_TYPE,
|
|
POS_HDR_V,
|
|
POS_HDR_PRF_FUNC,
|
|
POS_HDR_CSB_ID,
|
|
POS_HDR_CS_COUNT,
|
|
POS_HDR_CS_ID_MAP_TYPE,
|
|
POS_ID_SRTP,
|
|
POS_ID_SRTP_NO,
|
|
POS_ID_SRTP_SSRC,
|
|
POS_ID_SRTP_ROC,
|
|
|
|
/* KEMAC */
|
|
POS_KEMAC_ENCR_ALG,
|
|
POS_KEMAC_ENCR_DATA_LEN,
|
|
POS_KEMAC_ENCR_DATA,
|
|
POS_KEMAC_MAC_ALG,
|
|
POS_KEMAC_MAC,
|
|
|
|
/* PKE */
|
|
POS_PKE_C,
|
|
POS_PKE_DATA_LEN,
|
|
POS_PKE_DATA,
|
|
|
|
/* DH */
|
|
POS_DH_GROUP,
|
|
POS_DH_VALUE,
|
|
POS_DH_RESERV,
|
|
POS_DH_KV,
|
|
|
|
/* SIGN */
|
|
POS_SIGNATURE_LEN,
|
|
POS_SIGNATURE,
|
|
POS_SIGN_S_TYPE,
|
|
|
|
/* T */
|
|
POS_TS_TYPE,
|
|
POS_TS_NTP,
|
|
|
|
/* ID/IDR */
|
|
POS_ID_ROLE,
|
|
POS_ID_TYPE,
|
|
POS_ID_LEN,
|
|
POS_ID,
|
|
|
|
/* CERT */
|
|
POS_CERT_TYPE,
|
|
POS_CERT_LEN,
|
|
POS_CERTIFICATE,
|
|
|
|
/* V */
|
|
POS_V_AUTH_ALG,
|
|
POS_V_DATA,
|
|
|
|
/* SP */
|
|
POS_SP_NO,
|
|
POS_SP_TYPE,
|
|
POS_SP_PARAM_LEN,
|
|
/* POS_SP_PARAM, */
|
|
|
|
/* SP param */
|
|
POS_SP_PARAM_F,
|
|
POS_SP_PARAM_F_TYPE,
|
|
POS_SP_PARAM_F_LEN,
|
|
POS_SP_PARAM_F_VALUE,
|
|
|
|
/* RAND */
|
|
POS_RAND_LEN,
|
|
POS_RAND,
|
|
|
|
/* Error */
|
|
POS_ERR_NO,
|
|
POS_ERR_RESERVED,
|
|
|
|
/* Key data */
|
|
POS_KEY_DATA_TYPE,
|
|
POS_KEY_DATA_KV,
|
|
POS_KEY_DATA_LEN,
|
|
POS_KEY_DATA,
|
|
POS_KEY_SALT_LEN,
|
|
POS_KEY_SALT,
|
|
POS_KEY_KV_FROM_LEN,
|
|
POS_KEY_KV_FROM,
|
|
POS_KEY_KV_TO_LEN,
|
|
POS_KEY_KV_TO,
|
|
POS_KEY_KV_SPI_LEN,
|
|
POS_KEY_KV_SPI,
|
|
|
|
/* General Ext. */
|
|
POS_GENERAL_EXT_TYPE,
|
|
POS_GENERAL_EXT_LEN,
|
|
POS_GENERAL_EXT_DATA,
|
|
POS_GENERAL_EXT_VALUE,
|
|
|
|
/* SAKKE */
|
|
POS_SAKKE_PARAMS,
|
|
POS_SAKKE_ID_SCHEME,
|
|
POS_SAKKE_LEN,
|
|
POS_SAKKE_DATA,
|
|
|
|
/* MIKEY */
|
|
POS_PAYLOAD_STR,
|
|
POS_NEXT_PAYLOAD,
|
|
|
|
/* Unused */
|
|
/* POS_PAYLOAD, */
|
|
|
|
MAX_POS
|
|
};
|
|
|
|
typedef struct tag_mikey_t {
|
|
guint8 type;
|
|
} mikey_t;
|
|
|
|
typedef int (*mikey_dissector_t)(mikey_t *, tvbuff_t *, packet_info *, proto_tree *);
|
|
struct mikey_dissector_entry {
|
|
int type;
|
|
mikey_dissector_t dissector;
|
|
};
|
|
|
|
/* Forward declaration we need below */
|
|
static int dissect_payload(int payload, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
|
|
|
|
|
|
/* Initialize the protocol and registered fields */
|
|
static int proto_mikey = -1;
|
|
static int hf_mikey[MAX_POS+1];
|
|
static int hf_mikey_sp_param[SP_MAX+1];
|
|
static int hf_mikey_pl[PL_MAX];
|
|
|
|
/* Initialize the subtree pointers */
|
|
static gint ett_mikey = -1;
|
|
static gint ett_mikey_payload = -1;
|
|
static gint ett_mikey_sp_param = -1;
|
|
static gint ett_mikey_hdr_id = -1;
|
|
static gint ett_mikey_enc_data = -1;
|
|
|
|
static dissector_handle_t mikey_handle;
|
|
|
|
static const struct mikey_dissector_entry *
|
|
mikey_dissector_lookup(const struct mikey_dissector_entry *map, int type)
|
|
{
|
|
unsigned int i;
|
|
for (i = 0; map[i].dissector != NULL; i++) {
|
|
if (map[i].type == type) {
|
|
return &map[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
add_next_payload(tvbuff_t *tvb, proto_tree *tree, int offset)
|
|
{
|
|
proto_tree_add_item(tree, hf_mikey[POS_NEXT_PAYLOAD], tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_payload_cs_id_srtp(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
if (tree) {
|
|
proto_item *id_ti;
|
|
proto_tree *id_tree;
|
|
guint8 no;
|
|
guint32 ssrc;
|
|
guint32 roc;
|
|
|
|
no = tvb_get_guint8(tvb, 0);
|
|
ssrc = tvb_get_ntohl(tvb, 1);
|
|
roc = tvb_get_ntohl(tvb, 5);
|
|
|
|
id_ti = proto_tree_add_none_format(tree, hf_mikey[POS_ID_SRTP], tvb, 0, 9,
|
|
"SRTP ID: Policy: %d, SSRC: 0x%x, ROC: 0x%x", no, ssrc, roc);
|
|
id_tree = proto_item_add_subtree(id_ti, ett_mikey_hdr_id);
|
|
|
|
proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_NO], tvb, 0, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_SSRC], tvb, 1, 4, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(id_tree, hf_mikey[POS_ID_SRTP_ROC], tvb, 5, 4, ENC_BIG_ENDIAN);
|
|
}
|
|
return 9;
|
|
}
|
|
|
|
static const struct mikey_dissector_entry cs_id_map[] = {
|
|
{ CS_ID_SRTP, dissect_payload_cs_id_srtp },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static int
|
|
dissect_payload_cs_id(int type, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
const struct mikey_dissector_entry *entry;
|
|
|
|
entry = mikey_dissector_lookup(cs_id_map, type);
|
|
|
|
if (!entry || !entry->dissector) {
|
|
return 0;
|
|
}
|
|
|
|
return entry->dissector(mikey, tvb, pinfo, tree);
|
|
|
|
}
|
|
|
|
static int
|
|
dissect_payload_hdr(mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint8 cs_id_map_type;
|
|
guint8 ncs;
|
|
int i;
|
|
|
|
tvb_ensure_bytes_exist(tvb, offset, 10);
|
|
mikey->type = tvb_get_guint8(tvb, offset+1);
|
|
ncs = tvb_get_guint8(tvb, offset+8);
|
|
cs_id_map_type = tvb_get_guint8(tvb, offset+9);
|
|
|
|
if (tree) {
|
|
proto_item* parent;
|
|
proto_tree_add_item(tree, hf_mikey[POS_HDR_VERSION],
|
|
tvb, offset+0, 1, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_HDR_DATA_TYPE], tvb, offset+1, 1, ENC_BIG_ENDIAN);
|
|
parent = proto_tree_get_parent(tree);
|
|
proto_item_append_text(parent, " Type: %s",
|
|
val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
|
|
|
|
add_next_payload(tvb, tree, offset+2);
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_HDR_V], tvb, offset+3, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_HDR_PRF_FUNC], tvb, offset+3, 1, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_HDR_CSB_ID], tvb, offset+4, 4, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_HDR_CS_COUNT], tvb, offset+8, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_HDR_CS_ID_MAP_TYPE], tvb, offset+9, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
offset += 10;
|
|
for (i=0; i < ncs; i++) {
|
|
tvbuff_t *sub_tvb;
|
|
int len;
|
|
|
|
sub_tvb = tvb_new_subset_remaining(tvb, offset);
|
|
len = dissect_payload_cs_id(cs_id_map_type, mikey, sub_tvb, pinfo, tree);
|
|
|
|
if (len < 0)
|
|
return 0;
|
|
|
|
offset += len;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_kemac(mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint8 encr_alg;
|
|
guint16 encr_length;
|
|
guint16 mac_length;
|
|
guint8 mac_alg;
|
|
|
|
encr_alg = tvb_get_guint8(tvb, offset+1);
|
|
encr_length = tvb_get_ntohs(tvb, offset+2);
|
|
tvb_ensure_bytes_exist(tvb, offset+4, encr_length+1);
|
|
mac_alg = tvb_get_guint8(tvb, offset+4+encr_length);
|
|
|
|
if (tree) {
|
|
tvbuff_t *sub_tvb;
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_ALG], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_DATA_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
|
|
/* TODO: Add key decode for MIKEY_TYPE_PK_INIT and MIKEY_TYPE_RSA_R_RESP with NULL encryption */
|
|
if ((encr_alg == ENCR_NULL) && (mikey->type == MIKEY_TYPE_PSK_INIT) && (encr_length > 0)) {
|
|
proto_item *key_data_item;
|
|
proto_tree *key_data_tree;
|
|
/* We can decode easily the Key Data if NULL encryption is used */
|
|
key_data_item = proto_tree_add_item(tree, hf_mikey_pl[PL_KEY_DATA], tvb, 4, encr_length, ENC_NA);
|
|
key_data_tree = proto_item_add_subtree(key_data_item, ett_mikey_enc_data);
|
|
|
|
sub_tvb = tvb_new_subset_length(tvb, offset+4, encr_length);
|
|
dissect_payload(PL_KEY_DATA, mikey, sub_tvb, pinfo, key_data_tree);
|
|
} else {
|
|
/* If Key Data is encrypted, show only the encr_data */
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEMAC_ENCR_DATA], tvb, 4, encr_length, ENC_NA);
|
|
}
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEMAC_MAC_ALG], tvb, 4+encr_length, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
switch (mac_alg) {
|
|
case MAC_NULL:
|
|
mac_length = 0;
|
|
break;
|
|
case MAC_HMAC_SHA_1_160:
|
|
mac_length = 160/8;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEMAC_MAC], tvb, 4+encr_length+1, mac_length, ENC_NA);
|
|
|
|
return 4+encr_length+1+mac_length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_pke(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint16 length;
|
|
|
|
length = tvb_get_ntohs(tvb, offset+1) &0x3ff;
|
|
|
|
if (tree) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_PKE_C], tvb, 1, 2, ENC_BIG_ENDIAN);
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_PKE_DATA_LEN], tvb, 1, 2, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_PKE_DATA], tvb, 3, length, ENC_NA);
|
|
return 3 + length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_dh(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint8 dh_group;
|
|
int dh_length;
|
|
guint8 kv;
|
|
|
|
dh_group = tvb_get_guint8(tvb, offset+1);
|
|
|
|
switch (dh_group) {
|
|
case DH_OAKLEY_5:
|
|
dh_length = 1536/8;
|
|
break;
|
|
case DH_OAKLEY_1:
|
|
dh_length = 768/8;
|
|
break;
|
|
case DH_OAKLEY_2:
|
|
dh_length = 1024/8;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
kv = tvb_get_guint8(tvb, offset+2+dh_length) & 0x0f;
|
|
|
|
if (tree) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_DH_GROUP], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_DH_VALUE], tvb, 2, dh_length, ENC_NA);
|
|
proto_tree_add_item(tree, hf_mikey[POS_DH_RESERV], tvb, 2+dh_length, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_DH_KV], tvb, 2+dh_length, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
if (kv != 0) {
|
|
return 0;
|
|
}
|
|
|
|
return 2 + dh_length + 1;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_sign(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint16 length;
|
|
|
|
length = ((tvb_get_guint8(tvb, offset+0) & 0x0f) << 8) + tvb_get_guint8(tvb, offset+1);
|
|
|
|
if (tree) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_SIGN_S_TYPE], tvb, 0, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_uint(tree, hf_mikey[POS_SIGNATURE_LEN], tvb, 0, 2, length);
|
|
}
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_SIGNATURE], tvb, 2, length, ENC_NA);
|
|
return 2 + length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_t(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
guint8 ts_type;
|
|
int offset = 0;
|
|
int len = 0;
|
|
|
|
ts_type = tvb_get_guint8(tvb, offset+1);
|
|
|
|
if (tree) {
|
|
proto_tree *parent;
|
|
parent = proto_tree_get_parent(tree);
|
|
proto_item_append_text(parent, " Type: %s", val_to_str_const(ts_type, ts_type_vals, "Unknown"));
|
|
proto_tree_add_item(tree, hf_mikey[POS_TS_TYPE], tvb, offset+1, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
switch (ts_type) {
|
|
case T_NTP:
|
|
case T_NTP_UTC:
|
|
proto_tree_add_item(tree, hf_mikey[POS_TS_NTP], tvb, offset+2, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN);
|
|
len = 10;
|
|
break;
|
|
case T_COUNTER:
|
|
len = 6;
|
|
break;
|
|
default:
|
|
len = 0;
|
|
break;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_id(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint8 type;
|
|
guint16 length;
|
|
|
|
type = tvb_get_guint8(tvb, offset+1);
|
|
length = tvb_get_ntohs(tvb, offset+2);
|
|
if (tree) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_ID_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_ID_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
if (tree) {
|
|
proto_item* parent;
|
|
const guint8* pos_id;
|
|
proto_tree_add_item_ret_string(tree, hf_mikey[POS_ID], tvb, 4, length, ENC_ASCII|ENC_NA, wmem_packet_scope(), &pos_id);
|
|
|
|
parent = proto_tree_get_parent(tree);
|
|
proto_item_append_text(parent, " %s: %s", val_to_str_const(type, id_type_vals, "Unknown"), pos_id);
|
|
}
|
|
|
|
return 4 + length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_idr(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint8 type;
|
|
guint16 length;
|
|
|
|
type = tvb_get_guint8(tvb, offset+2);
|
|
length = tvb_get_ntohs(tvb, offset+3);
|
|
if (tree) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_ID_ROLE], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_ID_TYPE], tvb, 2, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_ID_LEN], tvb, 3, 2, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
if (tree) {
|
|
proto_item *parent;
|
|
const guint8* pos_id;
|
|
proto_tree_add_item_ret_string(tree, hf_mikey[POS_ID], tvb, 5, length, ENC_ASCII|ENC_NA, wmem_packet_scope(), &pos_id);
|
|
|
|
parent = proto_tree_get_parent(tree);
|
|
proto_item_append_text(parent, " %s: %s", val_to_str_const(type, id_type_vals, "Unknown"), pos_id);
|
|
}
|
|
|
|
return 5 + length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_cert(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint8 type;
|
|
guint16 length;
|
|
tvbuff_t *subtvb;
|
|
asn1_ctx_t asn1_ctx;
|
|
|
|
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
|
|
|
|
type = tvb_get_guint8(tvb, offset+1);
|
|
length = tvb_get_ntohs(tvb, offset+2);
|
|
|
|
tvb_ensure_bytes_exist(tvb, offset+4, length);
|
|
|
|
if (tree) {
|
|
proto_item *parent;
|
|
parent = proto_tree_get_parent(tree);
|
|
proto_tree_add_item(tree, hf_mikey[POS_CERT_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_CERT_LEN], tvb, 1, 2, ENC_BIG_ENDIAN);
|
|
|
|
proto_item_append_text(parent, " Type: %s", val_to_str_const(type, cert_type_vals, "Unknown"));
|
|
}
|
|
|
|
subtvb = tvb_new_subset_length(tvb, offset+4, length);
|
|
dissect_x509af_Certificate(FALSE, subtvb, 0, &asn1_ctx, tree, hf_mikey[POS_CERTIFICATE]);
|
|
|
|
return 4 + length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_v(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint16 length;
|
|
guint8 alg;
|
|
|
|
alg = tvb_get_guint8(tvb, offset+1);
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_V_AUTH_ALG], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
|
|
switch (alg) {
|
|
case MAC_NULL:
|
|
length = 0;
|
|
break;
|
|
case MAC_HMAC_SHA_1_160:
|
|
length = 160/8;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_V_DATA], tvb, 2, length, ENC_NA);
|
|
|
|
return 2 + length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_sp_param(enum sp_prot_t proto, tvbuff_t *tvb, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint8 type;
|
|
guint8 length;
|
|
int hfindex;
|
|
|
|
type = tvb_get_guint8(tvb, offset+0);
|
|
length = tvb_get_guint8(tvb, offset+1);
|
|
|
|
/* Default */
|
|
hfindex = hf_mikey[POS_SP_PARAM_F];
|
|
|
|
switch(proto) {
|
|
case SP_PROT_TYPE_SRTP:
|
|
if (type < array_length(hf_mikey_sp_param))
|
|
hfindex = hf_mikey_sp_param[type];
|
|
break;
|
|
}
|
|
|
|
if (tree) {
|
|
proto_item *param_ti;
|
|
proto_tree *param_tree;
|
|
/*
|
|
* All the parameters in question are either FT_BYTES,
|
|
* in which case the byte order is inapplicable, or
|
|
* FT_UINT8, in which case it could be given as
|
|
* FT_BIG_ENDIAN as per bigger FT_UINT values, but
|
|
* ENC_NA also works, as there's only one byte.
|
|
*/
|
|
param_ti = proto_tree_add_item(tree, hfindex, tvb, 2, length, ENC_NA);
|
|
param_tree = proto_item_add_subtree(param_ti, ett_mikey_sp_param);
|
|
|
|
proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_TYPE], tvb, 0, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_LEN], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(param_tree, hf_mikey[POS_SP_PARAM_F_VALUE], tvb, 2, length, ENC_NA);
|
|
}
|
|
|
|
return 2+length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_sp(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint16 length;
|
|
int sub_pos;
|
|
guint8 no;
|
|
enum sp_prot_t type;
|
|
|
|
length = tvb_get_ntohs(tvb, offset+3);
|
|
no = tvb_get_guint8(tvb, offset+1);
|
|
type = (enum sp_prot_t)tvb_get_guint8(tvb, offset+2);
|
|
|
|
if (tree) {
|
|
proto_item *parent;
|
|
parent = proto_tree_get_parent(tree);
|
|
proto_tree_add_item(tree, hf_mikey[POS_SP_NO], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_SP_TYPE], tvb, 2, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_SP_PARAM_LEN], tvb, 3, 2, ENC_BIG_ENDIAN);
|
|
|
|
proto_item_append_text(parent, " No: %d, Type: %s", no,
|
|
val_to_str_const(type, sp_prot_type_vals, "Unknown"));
|
|
}
|
|
|
|
tvb_ensure_bytes_exist(tvb, offset+5, length);
|
|
/* proto_tree_add_item(tree, hf_mikey[POS_SP_PARAM], tvb, 5, length, ENC_NA); */
|
|
|
|
offset += 5;
|
|
sub_pos = 0;
|
|
|
|
while (sub_pos < length) {
|
|
int param_len;
|
|
tvbuff_t *subtvb;
|
|
|
|
subtvb = tvb_new_subset_length(tvb, offset+sub_pos, length-sub_pos);
|
|
param_len = dissect_payload_sp_param(type, subtvb, tree);
|
|
|
|
if (param_len < 0)
|
|
return 0;
|
|
|
|
sub_pos += param_len;
|
|
}
|
|
|
|
return 5 + length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_rand(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint16 length;
|
|
|
|
length = tvb_get_guint8(tvb, offset+1);
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_RAND_LEN], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_RAND], tvb, 2, length, ENC_NA);
|
|
|
|
return 2 + length;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_err(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
if (tree) {
|
|
proto_item *parent;
|
|
guint8 err_no;
|
|
err_no = tvb_get_guint8(tvb, 1);
|
|
proto_tree_add_item(tree, hf_mikey[POS_ERR_NO], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_ERR_RESERVED], tvb, 2, 2, ENC_NA);
|
|
parent = proto_tree_get_parent(tree);
|
|
proto_item_append_text(parent, ": %s", val_to_str_ext_const(err_no, &err_vals_ext, "Unknown"));
|
|
}
|
|
|
|
return 4;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_keydata(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
guint16 offset;
|
|
guint16 data_len;
|
|
guint8 key_type;
|
|
guint8 kv_type;
|
|
|
|
offset = 0;
|
|
key_type = tvb_get_guint8(tvb, 1) >> 4;
|
|
kv_type = tvb_get_guint8(tvb, 1) & 0x0f;
|
|
data_len = tvb_get_ntohs(tvb, 2);
|
|
|
|
offset += 4;
|
|
|
|
if (tree) {
|
|
proto_item *parent;
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_KV], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_DATA], tvb, 4, data_len, ENC_NA);
|
|
|
|
parent = proto_tree_get_parent(tree);
|
|
proto_item_append_text(parent, " Type: %s", val_to_str_const(key_type, kd_vals, "Unknown"));
|
|
}
|
|
|
|
offset += data_len;
|
|
|
|
/* Dissect SALT key */
|
|
if ((key_type == KD_TGK_SALT) || (key_type == KD_TEK_SALT)) {
|
|
guint16 salt_len;
|
|
salt_len = tvb_get_ntohs(tvb, offset);
|
|
if (salt_len > 0) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_SALT_LEN], tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_SALT], tvb, offset+2, salt_len, ENC_NA);
|
|
}
|
|
offset += 2+salt_len;
|
|
}
|
|
|
|
/* Dissect Key Validity */
|
|
if (kv_type == KV_INTERVAL) {
|
|
guint16 kv_from_len;
|
|
guint16 kv_to_len;
|
|
|
|
kv_from_len = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_FROM_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
if (kv_from_len > 0) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_FROM], tvb, offset+1, kv_from_len, ENC_NA);
|
|
}
|
|
offset += 1+kv_from_len;
|
|
|
|
kv_to_len = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_TO_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
if (kv_to_len > 0) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_TO], tvb, offset+1, kv_to_len, ENC_NA);
|
|
}
|
|
offset += 1+kv_to_len;
|
|
} else if (kv_type == KV_SPI) {
|
|
guint16 kv_spi_len;
|
|
|
|
kv_spi_len = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_SPI_LEN], tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
if (kv_spi_len > 0) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_KEY_KV_SPI], tvb, offset+1, kv_spi_len, ENC_NA);
|
|
}
|
|
offset += 1+kv_spi_len;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_general_ext(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint8 type;
|
|
guint16 data_len;
|
|
|
|
type = tvb_get_guint8(tvb, offset+1);
|
|
data_len = tvb_get_ntohs(tvb, offset+2);
|
|
|
|
if (tree) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_TYPE], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_LEN], tvb, 2, 2, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
if (tree) {
|
|
proto_item *parent;
|
|
|
|
parent = proto_tree_get_parent(tree);
|
|
if (type == 1) {
|
|
/* For SDP-IDs, show a string instead of raw bytes */
|
|
proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_VALUE], tvb, 4, data_len, ENC_ASCII|ENC_NA);
|
|
} else {
|
|
proto_tree_add_item(tree, hf_mikey[POS_GENERAL_EXT_DATA], tvb, 4, data_len, ENC_NA);
|
|
}
|
|
proto_item_append_text(parent, " Type: %s", val_to_str_const(type, genext_type_vals, "Unknown"));
|
|
}
|
|
return 4 + data_len;
|
|
}
|
|
|
|
static int
|
|
dissect_payload_sakke(mikey_t *mikey _U_, tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
{
|
|
int offset = 0;
|
|
guint16 data_len;
|
|
|
|
data_len = tvb_get_ntohs(tvb, offset+3);
|
|
|
|
if (tree) {
|
|
proto_tree_add_item(tree, hf_mikey[POS_SAKKE_PARAMS], tvb, 1, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_SAKKE_ID_SCHEME], tvb, 2, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_mikey[POS_SAKKE_LEN], tvb, 3, 2, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
proto_tree_add_item(tree, hf_mikey[POS_SAKKE_DATA], tvb, 5, data_len, ENC_NA);
|
|
return 5 + data_len;
|
|
}
|
|
|
|
static const struct mikey_dissector_entry payload_map[] = {
|
|
{ PL_HDR, dissect_payload_hdr },
|
|
{ PL_KEMAC, dissect_payload_kemac },
|
|
{ PL_PKE, dissect_payload_pke },
|
|
{ PL_DH, dissect_payload_dh },
|
|
{ PL_SIGN, dissect_payload_sign },
|
|
{ PL_T, dissect_payload_t },
|
|
{ PL_ID, dissect_payload_id },
|
|
{ PL_CERT, dissect_payload_cert },
|
|
{ PL_V, dissect_payload_v },
|
|
{ PL_SP, dissect_payload_sp },
|
|
{ PL_RAND, dissect_payload_rand },
|
|
{ PL_ERR, dissect_payload_err },
|
|
{ PL_IDR, dissect_payload_idr },
|
|
{ PL_KEY_DATA, dissect_payload_keydata },
|
|
{ PL_GENERAL_EXT, dissect_payload_general_ext },
|
|
{ PL_SAKKE, dissect_payload_sakke },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static int
|
|
dissect_payload(int payload, mikey_t *mikey, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
const struct mikey_dissector_entry *entry;
|
|
|
|
entry = mikey_dissector_lookup(payload_map, payload);
|
|
|
|
if (!entry || !entry->dissector) {
|
|
return 0;
|
|
}
|
|
|
|
return entry->dissector(mikey, tvb, pinfo, tree);
|
|
}
|
|
|
|
/* MIKEY dissector */
|
|
static int
|
|
dissect_mikey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
|
{
|
|
proto_item *ti = NULL;
|
|
proto_tree *mikey_tree = NULL;
|
|
int offset = 0;
|
|
int next_payload_offset;
|
|
int payload;
|
|
mikey_t *mikey;
|
|
|
|
mikey = (mikey_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mikey, 0);
|
|
|
|
if (!mikey) {
|
|
mikey = wmem_new0(wmem_file_scope(), mikey_t);
|
|
mikey->type = -1;
|
|
p_add_proto_data(wmem_file_scope(), pinfo, proto_mikey, 0, mikey);
|
|
}
|
|
|
|
|
|
tvb_ensure_bytes_exist(tvb, offset, 3);
|
|
next_payload_offset = offset + 2;
|
|
payload = -1;
|
|
|
|
if (tree) {
|
|
ti = proto_tree_add_item(tree, proto_mikey, tvb, 0, -1, ENC_NA);
|
|
mikey_tree = proto_item_add_subtree(ti, ett_mikey);
|
|
}
|
|
|
|
while (payload != 0) {
|
|
int len;
|
|
proto_item *sub_ti = NULL;
|
|
proto_tree *mikey_payload_tree = NULL;
|
|
int next_payload;
|
|
tvbuff_t *subtvb;
|
|
|
|
next_payload = tvb_get_guint8(tvb, next_payload_offset);
|
|
subtvb = tvb_new_subset_remaining(tvb, offset);
|
|
|
|
if (mikey_tree) {
|
|
int hf = payload;
|
|
|
|
if (hf >= PL_MAX)
|
|
return -1;
|
|
|
|
if (hf == -1)
|
|
hf = 0;
|
|
|
|
sub_ti = proto_tree_add_item(mikey_tree, hf_mikey_pl[hf], subtvb, 0, -1, ENC_NA);
|
|
|
|
mikey_payload_tree = proto_item_add_subtree(sub_ti, ett_mikey_payload);
|
|
if ((payload != PL_HDR) && (payload != PL_SIGN))
|
|
add_next_payload(tvb, mikey_payload_tree, next_payload_offset);
|
|
}
|
|
|
|
len = dissect_payload(payload, mikey, subtvb, pinfo, mikey_payload_tree);
|
|
if (len <= 0) {
|
|
/* protocol violation or invalid data, stop dissecting
|
|
* but accept the data retrieved so far */
|
|
return tvb_captured_length(tvb);
|
|
}
|
|
|
|
if (sub_ti)
|
|
proto_item_set_len(sub_ti, len);
|
|
|
|
if (payload == PL_SIGN)
|
|
break;
|
|
|
|
payload = next_payload;
|
|
offset += len;
|
|
next_payload_offset = offset;
|
|
}
|
|
|
|
if (ti) {
|
|
proto_item_append_text(ti, ": %s",
|
|
val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
|
|
}
|
|
|
|
col_append_str(pinfo->cinfo, COL_PROTOCOL, "/MIKEY");
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Mikey: %s",
|
|
val_to_str_ext_const(mikey->type, &data_type_vals_ext, "Unknown"));
|
|
|
|
/* Return the amount of data this dissector was able to dissect */
|
|
return tvb_captured_length(tvb);
|
|
}
|
|
|
|
|
|
/* Register the protocol with Wireshark */
|
|
|
|
void
|
|
proto_register_mikey(void)
|
|
{
|
|
|
|
/* Setup list of header fields */
|
|
static hf_register_info hf[] = {
|
|
/* Payload types */
|
|
{ &hf_mikey_pl[PL_HDR+1],
|
|
{ PL_HDR_TEXT, "mikey.hdr",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_KEMAC],
|
|
{ PL_KEMAC_TEXT, "mikey.kemac",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_PKE],
|
|
{ PL_PKE_TEXT, "mikey.pke",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_DH],
|
|
{ PL_DH_TEXT, "mikey.dh",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_SIGN],
|
|
{ PL_SIGN_TEXT, "mikey.sign",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_T],
|
|
{ PL_T_TEXT, "mikey.t",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_ID],
|
|
{ PL_ID_TEXT, "mikey.id",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_CERT],
|
|
{ PL_CERT_TEXT, "mikey.cert",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_CHASH],
|
|
{ PL_CHASH_TEXT, "mikey.chash",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_V],
|
|
{ PL_V_TEXT, "mikey.v",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_SP],
|
|
{ PL_SP_TEXT, "mikey.sp",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_RAND],
|
|
{ PL_RAND_TEXT, "mikey.rand",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_ERR],
|
|
{ PL_ERR_TEXT, "mikey.err",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_IDR],
|
|
{ PL_IDR_TEXT, "mikey.idr",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_KEY_DATA],
|
|
{ PL_KEY_DATA_TEXT, "mikey.key",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_GENERAL_EXT],
|
|
{ PL_GENERAL_EXT_TEXT, "mikey.ext",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_pl[PL_SAKKE],
|
|
{ PL_SAKKE_TEXT, "mikey.sakke",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Common Header payload (HDR) */
|
|
{ &hf_mikey[POS_HDR_VERSION],
|
|
{ "Version", "mikey.version",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_HDR_DATA_TYPE],
|
|
{ "Data Type", "mikey.type",
|
|
FT_UINT8, BASE_DEC|BASE_EXT_STRING, &data_type_vals_ext, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_NEXT_PAYLOAD],
|
|
{ "Next Payload", "mikey.next_payload",
|
|
FT_UINT8, BASE_DEC, VALS(payload_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_HDR_V],
|
|
{ "V", "mikey.v.set",
|
|
FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_HDR_PRF_FUNC],
|
|
{ "PRF func", "mikey.prf_func",
|
|
FT_UINT8, BASE_DEC, VALS(prf_func_vals), 0x7f,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_HDR_CSB_ID],
|
|
{ "CSB ID", "mikey.csb_id",
|
|
FT_UINT32, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_HDR_CS_COUNT],
|
|
{ "#CS", "mikey.cs_count",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_HDR_CS_ID_MAP_TYPE],
|
|
{ "CS ID map type", "mikey.cs_id_map_type",
|
|
FT_UINT8, BASE_DEC, VALS(cs_id_map_vals), 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* SRTP ID */
|
|
{ &hf_mikey[POS_ID_SRTP],
|
|
{ "SRTP ID", "mikey.srtp_id",
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_ID_SRTP_NO],
|
|
{ "Policy No", "mikey.srtp_id.policy_no",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_ID_SRTP_SSRC],
|
|
{ "SSRC", "mikey.srtp_id.ssrc",
|
|
FT_UINT32, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_ID_SRTP_ROC],
|
|
{ "ROC", "mikey.srtp_id.roc",
|
|
FT_UINT32, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Key Data Transport payload (KEMAC) */
|
|
{ &hf_mikey[POS_KEMAC_ENCR_ALG],
|
|
{ "Encr alg", "mikey.kemac.encr_alg",
|
|
FT_UINT8, BASE_DEC, VALS(encr_alg_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEMAC_ENCR_DATA_LEN],
|
|
{ "Key data len", "mikey.kemac.key_data_len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEMAC_ENCR_DATA],
|
|
{ "Key data", "mikey.kemac.key_data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEMAC_MAC_ALG],
|
|
{ "Mac alg", "mikey.kemac.mac_alg",
|
|
FT_UINT8, BASE_DEC, VALS(mac_alg_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEMAC_MAC],
|
|
{ "MAC", "mikey.kemac.mac",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Envelope Data payload (PKE) */
|
|
{ &hf_mikey[POS_PKE_C],
|
|
{ "C", "mikey.pke.c",
|
|
FT_UINT16, BASE_DEC, VALS(pke_c_vals), 0xc000,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_PKE_DATA_LEN],
|
|
{ "Data len", "mikey.pke.len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x3fff,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_PKE_DATA],
|
|
{ "Data", "mikey.pke.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* DH data payload (DH) */
|
|
{ &hf_mikey[POS_DH_GROUP],
|
|
{ "DH-Group", "mikey.dh.group",
|
|
FT_UINT8, BASE_DEC, VALS(oakley_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_DH_VALUE],
|
|
{ "DH-Value", "mikey.dh.value",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_DH_RESERV],
|
|
{ "Reserv", "mikey.dh.reserv",
|
|
FT_UINT8, BASE_HEX, NULL, 0xf0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_DH_KV],
|
|
{ "KV", "mikey.dh.kv",
|
|
FT_UINT8, BASE_DEC, VALS(kv_vals), 0x0f,
|
|
NULL, HFILL }},
|
|
|
|
/* Signature payload (SIGN) */
|
|
{ &hf_mikey[POS_SIGN_S_TYPE],
|
|
{ "Signature type", "mikey.sign.type",
|
|
FT_UINT16, BASE_DEC, VALS(sign_s_vals), 0xf000,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SIGNATURE_LEN],
|
|
{ "Signature len", "mikey.sign.len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0fff,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SIGNATURE],
|
|
{ "Signature", "mikey.sign.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Timestamp payload (T) */
|
|
{ &hf_mikey[POS_TS_TYPE],
|
|
{ "TS type", "mikey.t.ts_type",
|
|
FT_UINT8, BASE_DEC, VALS(ts_type_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_TS_NTP],
|
|
{ "NTP timestamp", "mikey.t.ntp",
|
|
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_mikey[POS_PAYLOAD_STR],
|
|
{ "Payload", "mikey.payload",
|
|
FT_STRING, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* ID payload (ID) */
|
|
{ &hf_mikey[POS_ID_TYPE],
|
|
{ "ID type", "mikey.id.type",
|
|
FT_UINT8, BASE_DEC, VALS(id_type_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_ID_LEN],
|
|
{ "ID len", "mikey.id.len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_ID],
|
|
{ "ID", "mikey.id.data",
|
|
FT_STRING, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Certificate payload (CERT) */
|
|
{ &hf_mikey[POS_CERT_LEN],
|
|
{ "Certificate len", "mikey.cert.len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_CERT_TYPE],
|
|
{ "Certificate type", "mikey.cert.type",
|
|
FT_UINT8, BASE_DEC, VALS(cert_type_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_CERTIFICATE],
|
|
{ "Certificate", "mikey.cert.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Ver msg payload (V) */
|
|
{ &hf_mikey[POS_V_AUTH_ALG],
|
|
{ "Auth alg", "mikey.v.auth_alg",
|
|
FT_UINT8, BASE_DEC, VALS(mac_alg_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_V_DATA],
|
|
{ "Ver data", "mikey.v.ver_data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Security Policy payload (SP) */
|
|
{ &hf_mikey[POS_SP_NO],
|
|
{ "Policy No", "mikey.sp.no",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SP_TYPE],
|
|
{ "Protocol type", "mikey.sp.proto_type",
|
|
FT_UINT8, BASE_DEC, VALS(sp_prot_type_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SP_PARAM_LEN],
|
|
{ "Policy param length", "mikey.sp.param_len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Security Policy param */
|
|
{ &hf_mikey[POS_SP_PARAM_F],
|
|
{ "Policy param", "mikey.sp.param",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SP_PARAM_F_TYPE],
|
|
{ "Type", "mikey.sp.param.type",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SP_PARAM_F_LEN],
|
|
{ "Length", "mikey.sp.param.len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SP_PARAM_F_VALUE],
|
|
{ "Value", "mikey.sp.patam.value",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* SRTP policy param */
|
|
{ &hf_mikey_sp_param[SP_ENCR_ALG],
|
|
{ SP_TEXT_ENCR_ALG, "mikey.sp.encr_alg",
|
|
FT_UINT8, BASE_DEC, VALS(sp_encr_alg_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_ENCR_LEN],
|
|
{ SP_TEXT_ENCR_LEN, "mikey.sp.encr_len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_AUTH_ALG],
|
|
{ SP_TEXT_AUTH_ALG, "mikey.sp.auth_alg",
|
|
FT_UINT8, BASE_DEC, VALS(sp_auth_alg_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_AUTH_KEY_LEN],
|
|
{ SP_TEXT_AUTH_KEY_LEN, "mikey.sp.auth_key_len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_SALT_LEN],
|
|
{ SP_TEXT_SALT_LEN, "mikey.sp.salt_len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_PRF],
|
|
{ SP_TEXT_PRF, "mikey.sp.prf",
|
|
FT_UINT8, BASE_DEC, VALS(sp_prf_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_KD_RATE],
|
|
{ SP_TEXT_KD_RATE, "mikey.sp.kd_rate",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_SRTP_ENCR],
|
|
{ SP_TEXT_SRTP_ENCR, "mikey.sp.srtp_encr",
|
|
FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_SRTCP_ENCR],
|
|
{ SP_TEXT_SRTCP_ENCR, "mikey.sp.srtcp_encr",
|
|
FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_FEC],
|
|
{ SP_TEXT_FEC, "mikey.sp.fec",
|
|
FT_UINT8, BASE_DEC, VALS(sp_fec_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_SRTP_AUTH],
|
|
{ SP_TEXT_SRTP_AUTH, "mikey.sp.srtp_auth",
|
|
FT_UINT8, BASE_DEC, VALS(on_off_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_AUTH_TAG_LEN],
|
|
{ SP_TEXT_AUTH_TAG_LEN, "mikey.sp.auth_tag_len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey_sp_param[SP_SRTP_PREFIX],
|
|
{ SP_TEXT_SRTP_PREFIX, "mikey.sp.srtp_prefix",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* RAND payload (RAND) */
|
|
{ &hf_mikey[POS_RAND_LEN],
|
|
{ "RAND len", "mikey.rand.len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_RAND],
|
|
{ "RAND", "mikey.rand.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Error payload (ERR) */
|
|
{ &hf_mikey[POS_ERR_NO],
|
|
{ "Error no.", "mikey.err.no",
|
|
FT_UINT8, BASE_DEC|BASE_EXT_STRING, &err_vals_ext, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_ERR_RESERVED],
|
|
{ "Reserved", "mikey.err.reserved",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* IDR */
|
|
{ &hf_mikey[POS_ID_ROLE],
|
|
{ "ID role", "mikey.id.role",
|
|
FT_UINT8, BASE_DEC, VALS(id_role_vals), 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* Key data sub-payload */
|
|
{ &hf_mikey[POS_KEY_DATA_TYPE],
|
|
{ "Type", "mikey.key.type",
|
|
FT_UINT8, BASE_DEC, VALS(kd_vals), 0xf0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_DATA_KV],
|
|
{ "KV", "mikey.key.kv",
|
|
FT_UINT8, BASE_DEC, VALS(kv_vals), 0x0f,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_DATA_LEN],
|
|
{ "Key len", "mikey.key.data.len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_DATA],
|
|
{ "Key", "mikey.key.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_SALT_LEN],
|
|
{ "Salt key len", "mikey.key.salt.len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_SALT],
|
|
{ "Salt key", "mikey.key.salt",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_KV_FROM_LEN],
|
|
{ "Valid from len", "mikey.key.kv.from.len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_KV_FROM],
|
|
{ "Valid from", "mikey.key.kv.from",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_KV_TO_LEN],
|
|
{ "Valid to len", "mikey.key.kv.to.len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_KV_TO],
|
|
{ "Valid to", "mikey.key.kv.to",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_KV_SPI_LEN],
|
|
{ "Valid SPI len", "mikey.key.kv.spi.len",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_KEY_KV_SPI],
|
|
{ "Valid SPI", "mikey.key.kv.spi",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* General Extension payload (GENERAL_EXT) */
|
|
{ &hf_mikey[POS_GENERAL_EXT_TYPE],
|
|
{ "Extension type", "mikey.ext.type",
|
|
FT_UINT8, BASE_DEC, VALS(genext_type_vals), 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_GENERAL_EXT_LEN],
|
|
{ "Length", "mikey.ext.len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_GENERAL_EXT_DATA],
|
|
{ "Data", "mikey.ext.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_GENERAL_EXT_VALUE],
|
|
{ "Value", "mikey.ext.value",
|
|
FT_STRING, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/* SAKKE */
|
|
{ &hf_mikey[POS_SAKKE_PARAMS],
|
|
{ "SAKKE params", "mikey.sakke.params",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SAKKE_ID_SCHEME],
|
|
{ "ID scheme", "mikey.sakke.idscheme",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SAKKE_LEN],
|
|
{ "SAKKE data length", "mikey.sakke.len",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
{ &hf_mikey[POS_SAKKE_DATA],
|
|
{ "SAKKE data", "mikey.sakke.data",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
/*
|
|
{ &hf_mikey[POS_SP_PARAM],
|
|
{ "Policy param", "mikey.policy_param",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_mikey[POS_PAYLOAD],
|
|
{ "Payload", "mikey.payload",
|
|
FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
*/
|
|
};
|
|
|
|
/* Setup protocol subtree array */
|
|
static gint *ett[] = {
|
|
&ett_mikey,
|
|
&ett_mikey_payload,
|
|
&ett_mikey_sp_param,
|
|
&ett_mikey_hdr_id,
|
|
&ett_mikey_enc_data
|
|
};
|
|
|
|
/* Register the protocol name and description */
|
|
proto_mikey = proto_register_protocol("Multimedia Internet KEYing", "MIKEY", "mikey");
|
|
|
|
mikey_handle = register_dissector("mikey", dissect_mikey, proto_mikey);
|
|
|
|
/* Required function calls to register the header fields and subtrees used */
|
|
proto_register_field_array(proto_mikey, hf, array_length(hf));
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
}
|
|
|
|
|
|
void
|
|
proto_reg_handoff_mikey(void)
|
|
{
|
|
dissector_add_string("key_mgmt", "mikey", mikey_handle);
|
|
dissector_add_uint_with_preference("tcp.port", PORT_MIKEY, mikey_handle);
|
|
dissector_add_uint_with_preference("udp.port", PORT_MIKEY, mikey_handle);
|
|
}
|
|
/*
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local variables:
|
|
* c-basic-offset: 8
|
|
* tab-width: 8
|
|
* indent-tabs-mode: t
|
|
* End:
|
|
*
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
*/
|