Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-mka.c
Warning:line 1095, column 5
Value stored to 'offset' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-mka.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-04-13-100341-3641-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-mka.c
1/* packet-mka.c
2 * Routines for EAPOL-MKA IEEE 802.1X-2010 / IEEE 802.1bx-2014 /
3 * IEEE Std 802.1Xck-2018 / IEEE 802.1X-2020 MKPDU dissection
4 * Copyright 2014, Hitesh K Maisheri <[email protected]>
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <[email protected]>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13#include "config.h"
14#define WS_LOG_DOMAIN"MKA" "MKA"
15
16#include <epan/packet.h>
17#include <epan/expert.h>
18#include <epan/proto_data.h>
19#include <epan/uat.h>
20#include <epan/etypes.h>
21
22#include <wsutil/pint.h>
23#include <wsutil/wsgcrypt.h>
24#include <wsutil/ws_padding_to.h>
25#include <wsutil/to_str.h>
26
27#include "packet-eapol.h"
28#include "packet-mka.h"
29
30/*** UAT: CKN INFO ***/
31#define DATAFILE_CKN_INFO"mka_ckn_info" "mka_ckn_info"
32
33#define LIVE_PEER_LIST_TYPE1 1
34#define POTENTIAL_PEER_LIST_TYPE2 2
35#define MACSEC_SAK_USE_TYPE3 3
36#define DISTRIBUTED_SAK_TYPE4 4
37#define DISTRIBUTED_CAK_TYPE5 5
38#define KMD_TYPE6 6
39#define ANNOUNCEMENT_TYPE7 7
40#define XPN_TYPE8 8
41#define ICV_TYPE255 255
42
43#define CIPHER_SUITE_LEN8 8
44#define AES_CMAC_LEN16 16
45#define WRAPPED_KEY_IV_LEN8 8
46#define WRAPPED_KEY_LEN(kl)((kl) + 8) ((kl) + WRAPPED_KEY_IV_LEN8)
47
48#define MKA_MI_LEN12U 12U
49#define MKA_MAX_CKN_LEN32 32
50
51#define KDF_LABEL_LEN12 12
52#define KDF_CTX_LEN16 16
53
54#define DEFAULT_ICV_LEN16 16
55
56#define BASIC_PARAMSET_BODY_LENGTH28 28
57#define DISTRIBUTED_SAK_AES128_BODY_LEN28 28
58#define DISTRIBUTED_SAK_AES256_BODY_LEN52 52
59#define DISTRIBUTED_SAK_AES128_XPN_BODY_LEN36 36
60
61/* keys for p_[add|get]_proto_data */
62#define CKN_KEY0 0
63#define ICV_KEY1 1
64#define MI_KEY2 2
65#define SAK_KEY3 3
66#define PEER_SCI_KEY4 4
67#define PEER_MI_KEY5 5
68#define LATEST_KEY6 6
69#define OLD_KEY7 7
70
71void proto_register_mka(void);
72void proto_reg_handoff_mka(void);
73
74static int proto_mka;
75static int proto_eapol;
76
77static int hf_mka_version_id;
78static int hf_mka_basic_param_set;
79static int hf_mka_live_peer_list_set;
80static int hf_mka_potential_peer_list_set;
81static int hf_mka_macsec_sak_use_set;
82static int hf_mka_distributed_sak_set;
83static int hf_mka_distributed_cak_set;
84static int hf_mka_kmd_set;
85static int hf_mka_announcement_set;
86static int hf_mka_xpn_set;
87static int hf_mka_unknown_set;
88static int hf_mka_unknown_param_set;
89static int hf_mka_icv_set;
90static int hf_mka_param_set_type;
91
92static int hf_mka_keyserver_priority;
93static int hf_mka_key_server;
94static int hf_mka_macsec_desired;
95static int hf_mka_macsec_capability;
96static int hf_mka_param_body_length;
97static int hf_mka_sci;
98static int hf_mka_sci_system_identifier;
99static int hf_mka_sci_port_identifier;
100static int hf_mka_actor_mi;
101static int hf_mka_actor_mn;
102static int hf_mka_algo_agility;
103static int hf_mka_cak_name;
104static int hf_mka_cak_name_info;
105
106static int hf_mka_padding;
107
108static int hf_mka_key_server_ssci;
109static int hf_mka_peer_mi;
110static int hf_mka_peer_mn;
111
112static int hf_mka_latest_key_an;
113static int hf_mka_latest_key_tx;
114static int hf_mka_latest_key_rx;
115static int hf_mka_old_key_an;
116static int hf_mka_old_key_tx;
117static int hf_mka_old_key_rx;
118static int hf_mka_plain_tx;
119static int hf_mka_plain_rx;
120static int hf_mka_delay_protect;
121static int hf_mka_latest_key_server_mi;
122static int hf_mka_latest_key_number;
123static int hf_mka_latest_lowest_acceptable_pn;
124static int hf_mka_old_key_server_mi;
125static int hf_mka_old_key_number;
126static int hf_mka_old_lowest_acceptable_pn;
127
128static int hf_mka_distributed_an;
129static int hf_mka_confidentiality_offset;
130static int hf_mka_key_number;
131static int hf_mka_aes_key_wrap_sak;
132static int hf_mka_aes_key_wrap_unwrapped_sak;
133static int hf_mka_macsec_cipher_suite;
134static int hf_mka_aes_key_wrap_cak;
135
136static int hf_mka_kmd;
137
138static int hf_mka_suspension_time;
139static int hf_mka_latest_lowest_accept_pn_msb;
140static int hf_mka_old_lowest_accept_pn_msb;
141
142static int hf_mka_icv;
143static int hf_mka_icv_status;
144
145static int hf_mka_tlv_entry;
146static int hf_mka_tlv_type;
147static int hf_mka_tlv_info_string_length;
148static int hf_mka_tlv_data;
149static int hf_mka_tlv_cipher_suite_impl_cap;
150
151static expert_field ei_mka_icv_bad;
152static expert_field ei_mka_undecoded;
153static expert_field ei_unexpected_data;
154static expert_field ei_mka_unimplemented;
155
156static int ett_mka;
157static int ett_mka_sci;
158static int ett_mka_basic_param_set;
159static int ett_mka_live_peer_list_set;
160static int ett_mka_potential_peer_list_set;
161static int ett_mka_sak_use_set;
162static int ett_mka_distributed_sak_set;
163static int ett_mka_distributed_cak_set;
164static int ett_mka_kmd_set;
165static int ett_mka_announcement_set;
166static int ett_mka_xpn_set;
167static int ett_mka_unknown_set;
168static int ett_mka_icv_set;
169static int ett_mka_tlv;
170static int ett_mka_cipher_suite_entry;
171
172static const value_string param_set_type_vals[] = {
173 { LIVE_PEER_LIST_TYPE1, "Live Peer List" },
174 { POTENTIAL_PEER_LIST_TYPE2, "Potential Peer List" },
175 { MACSEC_SAK_USE_TYPE3, "MACsec SAK Use" },
176 { DISTRIBUTED_SAK_TYPE4, "Distributed SAK" },
177 { DISTRIBUTED_CAK_TYPE5, "Distributed CAK" },
178 { KMD_TYPE6, "KMD" },
179 { ANNOUNCEMENT_TYPE7, "Announcement" },
180 { XPN_TYPE8, "XPN" },
181 { ICV_TYPE255, "ICV Indicator" },
182 { 0, NULL((void*)0) }
183};
184
185static const value_string macsec_capability_type_vals[] = {
186 { 0, "MACsec not implemented" },
187 { 1, "MACsec Integrity without confidentiality" },
188 { 2, "MACsec Integrity with/without confidentiality, no confidentiality offset" },
189 { 3, "MACsec Integrity with/without confidentiality, confidentiality offset 0, 30, or 50" },
190 { 0, NULL((void*)0) }
191};
192
193static const value_string algo_agility_vals[] = {
194 { 0x0080C201, "IEEE Std 802.1X-2020" },
195 { 0, NULL((void*)0) }
196};
197
198static const value_string confidentiality_offset_vals[] = {
199 { 0, "No confidentiality" },
200 { 1, "No confidentiality offset" },
201 { 2, "Confidentiality offset 30 octets" },
202 { 3, "Confidentiality offset 50 octets" },
203 { 0, NULL((void*)0) }
204};
205
206/* The incorrect value can appear in the MACsec Cipher Suites TLV in the
207 * Announcement parameter set, but not in the Distributed SAK parameter set,
208 * which is the agreed upon value shared with the MACsec dissector. */
209static const val64_string macsec_cipher_suite_vals[] = {
210 { INT64_C(0x0080020001000001)0x0080020001000001L, "GCM-AES-128" }, // Original, incorrect value in IEEE 802.1AE-2006 and IEEE 802.1X-2010
211 { MACSEC_GCM_AES_1280x0080C20001000001UL, "GCM-AES-128" },
212 { MACSEC_GCM_AES_2560x0080C20001000002UL, "GCM-AES-256" },
213 { MACSEC_GCM_AES_XPN_1280x0080C20001000003UL, "GCM-AES-XPN-128" },
214 { MACSEC_GCM_AES_XPN_2560x0080C20001000004UL, "GCM-AES-XPN-256" },
215 { 0, NULL((void*)0) }
216};
217
218
219static const value_string macsec_tlvs[] = {
220 // 0 - 110 reserved
221 { 111, "Access Information" },
222 { 112, "MACsec Cipher Suites" },
223 { 113, "Key Management Domain" },
224 { 114, "NID (Network Identifier)" },
225 // 115 - 125 reserved
226 { 126, "Organizationally Specific Set TLV" },
227 { 127, "Organizationally Specific TLVs" },
228 { 0, NULL((void*)0) }
229};
230
231static wmem_map_t *mka_mi_sci_map;
232static wmem_multimap_t *mka_ckn_sak_map;
233static wmem_map_t *mka_ki_pn_map;
234
235static const char *mka_ckn_info_uat_defaults_[] = { NULL((void*)0), "", "" };
236
237static mka_ckn_info_t *mka_ckn_uat_data = NULL((void*)0);
238static unsigned num_mka_ckn_uat_data = 0;
239static GHashTable *ht_mka_ckn = NULL((void*)0);
240
241UAT_BUFFER_CB_DEF(mka_ckn_uat_data, cak, mka_ckn_info_t, cak, cak_len)static void mka_ckn_uat_data_cak_set_cb(void* rec, const char
* buf, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { unsigned char* new_buf =
len ? (unsigned char *)g_memdup2(buf,len) : ((void*)0); g_free
((((mka_ckn_info_t*)rec)->cak)); (((mka_ckn_info_t*)rec)->
cak) = new_buf; (((mka_ckn_info_t*)rec)->cak_len) = len; }
static void mka_ckn_uat_data_cak_tostr_cb(void* rec, char** out_ptr
, unsigned* out_len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { *out_ptr = ((mka_ckn_info_t
*)rec)->cak ? (char*)g_memdup2(((mka_ckn_info_t*)rec)->
cak,((mka_ckn_info_t*)rec)->cak_len) : g_strdup_inline (""
); *out_len = ((mka_ckn_info_t*)rec)->cak_len; }
242UAT_BUFFER_CB_DEF(mka_ckn_uat_data, ckn, mka_ckn_info_t, ckn, ckn_len)static void mka_ckn_uat_data_ckn_set_cb(void* rec, const char
* buf, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { unsigned char* new_buf =
len ? (unsigned char *)g_memdup2(buf,len) : ((void*)0); g_free
((((mka_ckn_info_t*)rec)->ckn)); (((mka_ckn_info_t*)rec)->
ckn) = new_buf; (((mka_ckn_info_t*)rec)->ckn_len) = len; }
static void mka_ckn_uat_data_ckn_tostr_cb(void* rec, char** out_ptr
, unsigned* out_len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { *out_ptr = ((mka_ckn_info_t
*)rec)->ckn ? (char*)g_memdup2(((mka_ckn_info_t*)rec)->
ckn,((mka_ckn_info_t*)rec)->ckn_len) : g_strdup_inline (""
); *out_len = ((mka_ckn_info_t*)rec)->ckn_len; }
243UAT_CSTRING_CB_DEF(mka_ckn_uat_data, name, mka_ckn_info_t)static void mka_ckn_uat_data_name_set_cb(void* rec, const char
* buf, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { char* new_buf = g_strndup
(buf,len); g_free((((mka_ckn_info_t*)rec)->name)); (((mka_ckn_info_t
*)rec)->name) = new_buf; } static void mka_ckn_uat_data_name_tostr_cb
(void* rec, char** out_ptr, unsigned* out_len, const void* u1
__attribute__((unused)), const void* u2 __attribute__((unused
))) { if (((mka_ckn_info_t*)rec)->name ) { *out_ptr = g_strdup_inline
((((mka_ckn_info_t*)rec)->name)); *out_len = (unsigned)strlen
((((mka_ckn_info_t*)rec)->name)); } else { *out_ptr = g_strdup_inline
(""); *out_len = 0; } }
244
245/* Derive the ICK or KEK from the CAK and label. */
246static unsigned
247mka_derive_key(const uint8_t *label, uint8_t *out, void *k) {
248 mka_ckn_info_t *rec = (mka_ckn_info_t *)k;
249 uint8_t *cak = (uint8_t *)rec->cak;
250 uint8_t *ckn = (uint8_t *)rec->ckn;
251
252 unsigned ckn_len = rec->ckn_len;
253 unsigned cak_len = rec->cak_len;
254
255 /* Build context. */
256 /* Context is the first 16 bytes of the CAK name. */
257 uint8_t context[16] = {0};
258 memcpy(context, ckn, MIN(ckn_len, 16)(((ckn_len) < (16)) ? (ckn_len) : (16)));
259
260 gcry_mac_hd_t hd;
261
262 if (ws_log_msg_is_active(WS_LOG_DOMAIN"MKA", LOG_LEVEL_DEBUG)) {
263 char *cak_str = bytes_to_str_maxlen(NULL((void*)0), cak, cak_len, 0);
264 ws_debug("cak: %s", cak_str)do { if (1) { ws_log_full("MKA", LOG_LEVEL_DEBUG, "epan/dissectors/packet-mka.c"
, 264, __func__, "cak: %s", cak_str); } } while (0)
;
265 g_free(cak_str);
266
267 char *lbl_str = bytes_to_str_maxlen(NULL((void*)0), label, KDF_LABEL_LEN12, 0);
268 ws_debug("lbl: %s", lbl_str)do { if (1) { ws_log_full("MKA", LOG_LEVEL_DEBUG, "epan/dissectors/packet-mka.c"
, 268, __func__, "lbl: %s", lbl_str); } } while (0)
;
269 g_free(lbl_str);
270
271 char *ctx_str = bytes_to_str_maxlen(NULL((void*)0), context, KDF_CTX_LEN16, 0);
272 ws_debug("ctx: %s", ctx_str)do { if (1) { ws_log_full("MKA", LOG_LEVEL_DEBUG, "epan/dissectors/packet-mka.c"
, 272, __func__, "ctx: %s", ctx_str); } } while (0)
;
273 g_free(ctx_str);
274 }
275
276 /* Format input data for cmac.
277 Input data length is (1 byte counter + 12 bytes label + 1 byte for 0x00 + 16 bytes for context + 2 bytes for length) = 32 */
278 #define INPUT_DATA_LENGTH(1 + 12 + 1 + 16 + 2) (1 + KDF_LABEL_LEN12 + 1 + KDF_CTX_LEN16 + 2)
279 uint8_t inputdata[INPUT_DATA_LENGTH(1 + 12 + 1 + 16 + 2)];
280
281 size_t clen = AES_CMAC_LEN16;
282 unsigned klen = cak_len * 8;
283 unsigned iterations = cak_len / AES_CMAC_LEN16;
284 unsigned outlen = 0;
285
286 /* Open the cmac context. */
287 if (gcry_mac_open(&hd, GCRY_MAC_CMAC_AES, 0, NULL((void*)0))) {
288 ws_warning("failed to open CMAC context")do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 288, __func__, "failed to open CMAC context"); } } while (0
)
;
289 return 0;
290 }
291
292 /* Set key to use. */
293 if (gcry_mac_setkey(hd, cak, cak_len)) {
294 ws_warning("failed to set CMAC key")do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 294, __func__, "failed to set CMAC key"); } } while (0)
;
295 gcry_mac_close(hd);
296 return 0;
297 }
298
299 for (unsigned i = 0; i < iterations; i++)
300 {
301 /* Reset cmac context, if needed */
302 if ((i > 0) && gcry_mac_reset(hd)gcry_mac_ctl ((hd), GCRYCTL_RESET, ((void*)0), 0)) {
303 ws_warning("failed CMAC reset")do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 303, __func__, "failed CMAC reset"); } } while (0)
;
304 gcry_mac_close(hd);
305 return 0;
306 }
307
308 inputdata[0] = (i + 1); // Iteration
309 memcpy(&inputdata[1], label, KDF_LABEL_LEN12); // Key label - must be 12 bytes
310 inputdata[13] = 0x00; // Always 0x00
311 memcpy(&inputdata[14], context, KDF_CTX_LEN16); // Context data - must be 16 bytes
312 inputdata[30] = (klen & 0xFF00) >> 8; // MSB of key length in bits
313 inputdata[31] = (klen & 0xFF); // LSB of key length in bits
314
315 /* Write the formatted input data to the CMAC. */
316 if (gcry_mac_write(hd, inputdata, INPUT_DATA_LENGTH(1 + 12 + 1 + 16 + 2))) {
317 ws_warning("failed CMAC write")do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 317, __func__, "failed CMAC write"); } } while (0)
;
318 gcry_mac_close(hd);
319 return 0;
320 }
321
322 /* Read the CMAC result. */
323 gcry_mac_read(hd, (out + (i * clen)), &clen);
324 outlen += (unsigned)clen;
325 }
326
327 /* Close the context. */
328 gcry_mac_close(hd);
329
330 if (ws_log_msg_is_active(WS_LOG_DOMAIN"MKA", LOG_LEVEL_DEBUG)) {
331 char *key_str = bytes_to_str_maxlen(NULL((void*)0), out, cak_len, 0);
332 ws_debug("key: %s", key_str)do { if (1) { ws_log_full("MKA", LOG_LEVEL_DEBUG, "epan/dissectors/packet-mka.c"
, 332, __func__, "key: %s", key_str); } } while (0)
;
333 g_free(key_str);
334 }
335
336 return outlen;
337}
338
339static void
340mka_derive_kek(void * k) {
341 mka_ckn_info_t *rec = (mka_ckn_info_t *)k;
342
343 const uint8_t label[KDF_LABEL_LEN12 + 1] = "IEEE8021 KEK";
344 rec->key.kek_len = mka_derive_key(label, rec->key.kek, rec);
345}
346
347static void
348mka_derive_ick(void * k) {
349 mka_ckn_info_t *rec = (mka_ckn_info_t *)k;
350
351 const uint8_t label[KDF_LABEL_LEN12 + 1] = "IEEE8021 ICK";
352 rec->key.ick_len = mka_derive_key(label, rec->key.ick, rec);
353}
354
355static unsigned
356ckn_key_hash_func(const void *k) {
357 const mka_ckn_info_t *rec = (const mka_ckn_info_t *)k;
358 size_t i;
359 unsigned hash = 0;
360 uint8_t *tmp = (uint8_t *)rec->ckn;
361
362 /* Reduce to uint32_t by XOR */
363 for (i = 0; i < rec->ckn_len; i++) {
364 hash ^= tmp[i] << 8 * (i % 4);
365 }
366
367 return hash;
368}
369
370static int
371ckn_key_equal_func(const void *c1, const void *c2) {
372 const mka_ckn_info_t *ckn1 = (const mka_ckn_info_t *)c1;
373 const mka_ckn_info_t *ckn2 = (const mka_ckn_info_t *)c2;
374 if (ckn1->ckn_len != ckn2->ckn_len) return 0;
375 if (memcmp(ckn1->ckn, ckn2->ckn, ckn1->ckn_len) != 0) return 0;
376
377 return 1;
378}
379
380static void *
381ckn_info_copy_cb(void *n, const void *o, size_t size _U___attribute__((unused))) {
382 mka_ckn_info_t *new_rec = (mka_ckn_info_t *)n;
383 const mka_ckn_info_t *old_rec = (const mka_ckn_info_t *)o;
384
385 new_rec->cak = (unsigned char *)g_memdup2(old_rec->cak, old_rec->cak_len);
386 new_rec->cak_len = old_rec->cak_len;
387 new_rec->ckn = (unsigned char *)g_memdup2(old_rec->ckn, old_rec->ckn_len);
388 new_rec->ckn_len = old_rec->ckn_len;
389 new_rec->name = g_strdup(old_rec->name)g_strdup_inline (old_rec->name);
390
391 return new_rec;
392}
393
394static bool_Bool
395ckn_info_update_cb(void *r, char **err) {
396 mka_ckn_info_t *rec = (mka_ckn_info_t *)r;
397
398 if ((0 != rec->cak_len) && ((AES128_KEY_LEN16 != rec->cak_len) && (AES256_KEY_LEN32 != rec->cak_len))) {
399 *err = ws_strdup("Invalid CAK length! CAKs need to be 16 or 32 bytes when specified.")wmem_strdup(((void*)0), "Invalid CAK length! CAKs need to be 16 or 32 bytes when specified."
)
;
400 return false0;
401 }
402
403 if ((0 == rec->ckn_len) || (rec->ckn_len > MKA_MAX_CKN_LEN32)) {
404 *err = ws_strdup("Invalid CKN length! CKNs need to be from 1 to 32 bytes.")wmem_strdup(((void*)0), "Invalid CKN length! CKNs need to be from 1 to 32 bytes."
)
;
405 return false0;
406 }
407
408 if (0 == strlen(rec->name)) {
409 *err = ws_strdup("Missing name! A name must be specified for this CAK/CKN entry.")wmem_strdup(((void*)0), "Missing name! A name must be specified for this CAK/CKN entry."
)
;
410 return false0;
411 }
412
413 /* XXX - The CKN must be unique for pre-shared CAKs (IEEE 802.1X-2020 6.3.3,
414 * 9.3.1). Can that be validated here? */
415
416 return true1;
417}
418
419static void
420ckn_info_free_cb(void *r) {
421 mka_ckn_info_t *rec = (mka_ckn_info_t *)r;
422
423 g_free(rec->cak);
424 g_free(rec->ckn);
425 g_free(rec->name);
426}
427
428static void
429ckn_info_reset_cb(void) {
430 if (NULL((void*)0) != ht_mka_ckn) {
431 g_hash_table_destroy(ht_mka_ckn);
432 ht_mka_ckn = NULL((void*)0);
433 }
434}
435
436static void
437ckn_info_post_update_cb(void) {
438 ckn_info_reset_cb();
439
440 ht_mka_ckn = g_hash_table_new(&ckn_key_hash_func, &ckn_key_equal_func);
441
442 for (size_t i = 0; i < num_mka_ckn_uat_data; i++) {
443 /* Derive the KEK and ICK and store with the CAK/CKN for this table entry. */
444 ws_info("deriving ICK for CKN table entry %zu (%s)", i, mka_ckn_uat_data[i].name)do { if (1) { ws_log_full("MKA", LOG_LEVEL_INFO, ((void*)0), -
1, ((void*)0), "deriving ICK for CKN table entry %zu (%s)", i
, mka_ckn_uat_data[i].name); } } while (0)
;
445 mka_derive_ick(&(mka_ckn_uat_data[i]));
446
447 ws_info("deriving KEK for CKN table entry %zu (%s)", i, mka_ckn_uat_data[i].name)do { if (1) { ws_log_full("MKA", LOG_LEVEL_INFO, ((void*)0), -
1, ((void*)0), "deriving KEK for CKN table entry %zu (%s)", i
, mka_ckn_uat_data[i].name); } } while (0)
;
448 mka_derive_kek(&(mka_ckn_uat_data[i]));
449
450 /* The disadvantage of using hash tables like this is that it's not
451 * possible to have multiple entries with the same CKN without more
452 * changes. */
453 g_hash_table_insert(ht_mka_ckn, &(mka_ckn_uat_data[i]), &(mka_ckn_uat_data[i]));
454 }
455}
456
457
458/* Find a table entry for the given CKN string */
459static mka_ckn_info_t *
460ckn_info_lookup(uint8_t ckn[], uint32_t ckn_len) {
461 mka_ckn_info_t tmp_key = { .ckn = ckn, .ckn_len = ckn_len };
462
463 if (ht_mka_ckn == NULL((void*)0)) {
464 ws_debug("No hash table")do { if (1) { ws_log_full("MKA", LOG_LEVEL_DEBUG, "epan/dissectors/packet-mka.c"
, 464, __func__, "No hash table"); } } while (0)
;
465 return NULL((void*)0);
466 }
467
468 return (mka_ckn_info_t *)g_hash_table_lookup(ht_mka_ckn, &tmp_key);
469}
470
471/* Get the entire table's contents. */
472const mka_ckn_info_t *
473get_mka_ckn_table(void) {
474 return (const mka_ckn_info_t *)mka_ckn_uat_data;
475}
476
477/* Get the size of the table. */
478unsigned
479get_mka_ckn_table_count(void) {
480 return num_mka_ckn_uat_data;
481}
482
483static unsigned
484mka_sci_hash(const void *key) {
485 return wmem_strong_hash(key, MACSEC_SCI_LEN8U);
486}
487
488static gboolean
489mka_sci_equal(const void *k1, const void *k2) {
490 return memcmp(k1, k2, MACSEC_SCI_LEN8U) == 0;
491}
492
493static unsigned
494mka_mi_hash(const void *key) {
495 return wmem_strong_hash(key, MKA_MI_LEN12U);
496}
497
498static gboolean
499mka_mi_equal(const void *k1, const void *k2) {
500 return memcmp(k1, k2, MKA_MI_LEN12U) == 0;
501}
502
503typedef struct _mka_ki_pn_t {
504 uint8_t ki[MKA_KI_LEN16U];
505 uint64_t pn;
506} mka_ki_pn_t;
507
508typedef struct _mka_ki_pn_value_t {
509 wmem_tree_t *all_sci_lpn_tree;
510 wmem_multimap_t *sci_lpn_multimap;
511} mka_ki_value_t;
512
513static unsigned
514mka_ki_hash(const void *k) {
515 mka_ki_pn_t *key = (mka_ki_pn_t*)k;
516 return wmem_strong_hash(key->ki, MKA_KI_LEN16U);
517}
518
519static gboolean
520mka_ki_equal(const void *k1, const void *k2) {
521 mka_ki_pn_t *key1 = (mka_ki_pn_t*)k1;
522 mka_ki_pn_t *key2 = (mka_ki_pn_t*)k2;
523
524 return memcmp(key1->ki, key2->ki, MKA_KI_LEN16U) == 0;
525}
526
527/* For use by other dissectors (MACsec), this looks for the most recent
528 * Lowest Acceptable Packet Number for a given Key Identifier (in the
529 * SAK info) and SCI (SecY). sci is allowed to be NULL, in which case
530 * the most recent value for any SCI is given, if known. The result is
531 * only accurate to the top 33 significant digits, as that is all that
532 * is required by the PN recovery algorithm in 802.1AE-2018 10.6.2. */
533uint64_t
534mka_get_lpn(const mka_sak_info_key_t *sak_info, const uint8_t *sci, uint32_t frame_num) {
535 mka_ki_value_t *value = wmem_map_lookup(mka_ki_pn_map, sak_info->ki);
536 uint64_t *lpn_p;
537 if (!value) {
538 return 0;
539 }
540 if (sci) {
541 lpn_p = wmem_multimap_lookup32_le(value->sci_lpn_multimap, sci, frame_num);
542 } else {
543 lpn_p = wmem_tree_lookup32_le(value->all_sci_lpn_tree, frame_num);
544 }
545
546 return lpn_p ? *lpn_p : 0;
547}
548
549static void
550update_lpn(const mka_ki_pn_t *tmp_value, const uint8_t *sci, uint32_t frame_num) {
551 // Shortcut: Don't bother creating the structures for zero values.
552 if ((tmp_value->pn >> 31) == 0) {
553 return;
554 }
555
556 mka_ki_value_t *value = wmem_map_lookup(mka_ki_pn_map, tmp_value->ki);
557 uint64_t lpn, *lpn_p, *perm_lpn_p = NULL((void*)0);
558 if (!value) {
559 value = wmem_new(wmem_file_scope(), mka_ki_value_t)((mka_ki_value_t*)wmem_alloc((wmem_file_scope()), sizeof(mka_ki_value_t
)))
;
560 value->all_sci_lpn_tree = wmem_tree_new(wmem_file_scope());
561 value->sci_lpn_multimap = wmem_multimap_new(wmem_file_scope(), mka_sci_hash, mka_sci_equal);
562 uint8_t *perm_ki = wmem_memdup(wmem_file_scope(), tmp_value->ki, MKA_KI_LEN16U);
563 wmem_map_insert(mka_ki_pn_map, perm_ki, value);
564 }
565 lpn_p = wmem_tree_lookup32_le(value->all_sci_lpn_tree, frame_num);
566 lpn = lpn_p ? *lpn_p : 0;
567 if ((tmp_value->pn >> 31) > (lpn >> 31)) {
568 /* Due to the algorithm for PN recovery (802.1AE-2018 10.6.2), we only
569 * need to update the value when the upper 33 bits change. */
570 perm_lpn_p = wmem_new(wmem_file_scope(), uint64_t)((uint64_t*)wmem_alloc((wmem_file_scope()), sizeof(uint64_t))
)
;
571 *perm_lpn_p = tmp_value->pn;
572 wmem_tree_insert32(value->all_sci_lpn_tree, frame_num, perm_lpn_p);
573 }
574 lpn_p = wmem_multimap_lookup32_le(value->sci_lpn_multimap, sci, frame_num);
575 lpn = lpn_p ? *lpn_p : 0;
576 if ((tmp_value->pn >> 31) > (lpn >> 31)) {
577 if (perm_lpn_p == NULL((void*)0)) {
578 // We can share the values here, as they have the same scope
579 perm_lpn_p = wmem_new(wmem_file_scope(), uint64_t)((uint64_t*)wmem_alloc((wmem_file_scope()), sizeof(uint64_t))
)
;
580 *perm_lpn_p = tmp_value->pn;
581 }
582 wmem_multimap_insert32(value->sci_lpn_multimap, sci, frame_num, perm_lpn_p);
583 }
584}
585
586typedef struct _mka_sak_key_t {
587 const mka_ckn_info_t *ckn_info;
588 uint8_t an;
589} mka_sak_key_t;
590
591static unsigned
592mka_sak_key_hash(const void *k) {
593 const mka_sak_key_t *key = (const mka_sak_key_t*)k;
594
595 return ckn_key_hash_func(key->ckn_info) ^ key->an;
596}
597
598static gboolean
599mka_sak_key_equal(const void *k1, const void *k2) {
600 const mka_sak_key_t *key1 = (const mka_sak_key_t*)k1;
601 const mka_sak_key_t *key2 = (const mka_sak_key_t*)k2;
602
603 return (key1->an == key2->an) &&
604 ckn_key_equal_func(key1->ckn_info, key2->ckn_info);
605}
606
607/* For use by other dissectors (MACsec), this looks for the most recent
608 * SAK with a given CKN and AN. */
609mka_sak_info_key_t *
610mka_get_sak_info(const mka_ckn_info_t *ckn, unsigned an, uint32_t frame_num) {
611 mka_sak_key_t key = {ckn, an};
612 return wmem_multimap_lookup32_le(mka_ckn_sak_map, &key, frame_num);
613}
614
615/* This static function is used internally on the second pass and requires an
616 * exact match on the frame number. */
617static mka_sak_info_key_t *
618get_sak_info(const mka_ckn_info_t *ckn, unsigned an, uint32_t frame_num) {
619 mka_sak_key_t tmp_key = {ckn, an};
620 mka_sak_info_key_t *sak_info = wmem_multimap_lookup32(mka_ckn_sak_map, &tmp_key, frame_num);
621 return sak_info;
622}
623
624static mka_sak_info_key_t *
625get_or_create_sak_info(const mka_ckn_info_t *ckn, unsigned an, uint32_t frame_num) {
626 mka_sak_info_key_t *sak_info = get_sak_info(ckn, an, frame_num);
627 if (sak_info == NULL((void*)0)) {
628 mka_sak_key_t *perm_key = wmem_new(wmem_file_scope(), mka_sak_key_t)((mka_sak_key_t*)wmem_alloc((wmem_file_scope()), sizeof(mka_sak_key_t
)))
;
629 perm_key->ckn_info = ckn;
630 perm_key->an = an;
631 sak_info = wmem_new0(wmem_file_scope(), mka_sak_info_key_t)((mka_sak_info_key_t*)wmem_alloc0((wmem_file_scope()), sizeof
(mka_sak_info_key_t)))
;
632 sak_info->sci_map = wmem_map_new(wmem_file_scope(), mka_sci_hash, mka_sci_equal);
633 sak_info->mi_array = wmem_array_new(wmem_file_scope(), MKA_MI_LEN12U);
634 wmem_multimap_insert32(mka_ckn_sak_map, perm_key, frame_num, sak_info);
635 }
636 return sak_info;
637}
638
639static mka_ckn_info_t *
640mka_add_ckn_info(proto_tree *tree, tvbuff_t *tvb, int offset, uint16_t ckn_len) {
641 proto_item *ti;
642
643 uint8_t ckn[MKA_MAX_CKN_LEN32]; /* Only accept CKN between 1 and 32 bytes! */
644 if (1 <= ckn_len && ckn_len <= MKA_MAX_CKN_LEN32) {
645 tvb_memcpy(tvb, ckn, offset, ckn_len);
646
647 mka_ckn_info_t *rec = ckn_info_lookup(ckn, ckn_len);
648 if (rec != NULL((void*)0)) {
649 ti = proto_tree_add_string(tree, hf_mka_cak_name_info, tvb, offset, ckn_len, rec->name);
650 proto_item_set_generated(ti);
651 }
652 return rec;
653 }
654 return NULL((void*)0);
655}
656
657static proto_tree *
658dissect_basic_paramset(proto_tree *mka_tree, packet_info *pinfo, tvbuff_t *tvb, int offset, uint16_t param_body_len) {
659 unsigned sci_offset;
660 proto_tree *basic_param_set_tree, *sci_tree;
661 proto_item *ti;
662 uint16_t ckn_len;
663 uint8_t *mi, *sci;
664
665 ti = proto_tree_add_item(mka_tree, hf_mka_basic_param_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
666 basic_param_set_tree = proto_item_add_subtree(ti, ett_mka_basic_param_set);
667
668 proto_tree_add_item(basic_param_set_tree, hf_mka_version_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
669 offset += 1;
670
671 proto_tree_add_item(basic_param_set_tree, hf_mka_keyserver_priority, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
672 offset += 1;
673
674 proto_tree_add_item(basic_param_set_tree, hf_mka_key_server, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
675 proto_tree_add_item(basic_param_set_tree, hf_mka_macsec_desired, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
676 proto_tree_add_item(basic_param_set_tree, hf_mka_macsec_capability, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
677
678 if (tvb_get_uint8(tvb, offset) & 0x80)
679 {
680 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0), "Key Server");
681 }
682
683 proto_tree_add_uint(basic_param_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
684 offset += 2;
685
686 ti = proto_tree_add_item(basic_param_set_tree, hf_mka_sci, tvb, offset, 8, ENC_NA0x00000000);
687 sci_offset = offset;
688 sci_tree = proto_item_add_subtree(ti, ett_mka_sci);
689 proto_tree_add_item(sci_tree, hf_mka_sci_system_identifier, tvb, offset, 6, ENC_NA0x00000000);
690 offset += 6;
691 proto_tree_add_item(sci_tree, hf_mka_sci_port_identifier, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
692 offset += 2;
693
694 proto_tree_add_item(basic_param_set_tree, hf_mka_actor_mi, tvb, offset, MKA_MI_LEN12U, ENC_NA0x00000000);
695 mi = tvb_memdup(pinfo->pool, tvb, offset, MKA_MI_LEN12U);
696 p_add_proto_data(pinfo->pool, pinfo, proto_mka, MI_KEY2, mi);
697 if (!wmem_map_contains(mka_mi_sci_map, mi)) {
698 /* We will assume that the 96-bit randomly chosen MIs do not collide.
699 * However note that an SCI can choose multiple MI over a lifetime if
700 * the Message Number would wrap. (IEEE 802.1X-2020 9.4.2) */
701 mi = tvb_memdup(wmem_file_scope(), tvb, offset, MKA_MI_LEN12U);
702 sci = tvb_memdup(wmem_file_scope(), tvb, sci_offset, MACSEC_SCI_LEN8U);
703 wmem_map_insert(mka_mi_sci_map, mi, sci);
704 }
705 offset += MKA_MI_LEN12U;
706
707 proto_tree_add_item(basic_param_set_tree, hf_mka_actor_mn, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
708 offset += 4;
709
710 proto_tree_add_item(basic_param_set_tree, hf_mka_algo_agility, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
711 offset += 4;
712
713 ckn_len = param_body_len - BASIC_PARAMSET_BODY_LENGTH28;
714 proto_tree_add_item(basic_param_set_tree, hf_mka_cak_name, tvb, offset, ckn_len, ENC_NA0x00000000);
715
716 /* look up the CAK/CKN in the CKN table, and add a private hash table entry if it does not yet exist there */
717 mka_ckn_info_t *rec = mka_add_ckn_info(basic_param_set_tree, tvb, offset, ckn_len);
718
719 if (NULL((void*)0) != rec) {
720 /* add the record to the private hash table for this packet to tell ourselves about the CKN and its keys later on */
721 p_add_proto_data(pinfo->pool, pinfo, proto_mka, CKN_KEY0, rec);
722 }
723
724 return basic_param_set_tree;
725}
726
727static int
728sort_mi_by_sci(const void* a, const void* b) {
729 uint8_t *sci_a = wmem_map_lookup(mka_mi_sci_map, a);
730 uint8_t *sci_b = wmem_map_lookup(mka_mi_sci_map, b);
731
732 DISSECTOR_ASSERT(sci_a && sci_b)((void) ((sci_a && sci_b) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-mka.c"
, 732, "sci_a && sci_b"))))
;
733 // Numerically greatest SCI uses the SSCI value 0x01, etc.
734 return -memcmp(sci_a, sci_b, MACSEC_SCI_LEN8U);
735}
736
737static proto_tree *
738dissect_live_peer_list(proto_tree *mka_tree, packet_info *pinfo, tvbuff_t *tvb, int offset, uint16_t param_body_len, bool_Bool key_server_ssci_flag) {
739 proto_tree *live_peer_list_set_tree;
740 proto_item *ti;
741 mka_sak_info_key_t *sak_info = NULL((void*)0);
742 uint32_t ssci;
743 uint8_t server_ssci = 0;
744 uint8_t *mi = NULL((void*)0);
745 uint8_t *sci = NULL((void*)0);
746
747 wmem_map_t *sci_map = NULL((void*)0);
748 wmem_array_t *mi_array = NULL((void*)0);
749
750 sak_info = p_get_proto_data(pinfo->pool, pinfo, proto_mka, SAK_KEY3);
751 mi = p_get_proto_data(pinfo->pool, pinfo, proto_mka, MI_KEY2);
752 sci = wmem_map_lookup(mka_mi_sci_map, mi);
753 DISSECTOR_ASSERT(sci)((void) ((sci) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-mka.c", 753, "sci"))))
;
754 if (sak_info) {
755 // Distributed SAK parameter set already processed.
756 sci_map = sak_info->sci_map;
757 mi_array = sak_info->mi_array;
758 } else {
759 // Distributed SAK parameter set not already processed.
760 // It should not appear later, per 11.11.3, but in practice
761 // in many implementations it does.
762 sci_map = wmem_map_new(pinfo->pool, mka_sci_hash, mka_sci_equal);
763 p_add_proto_data(pinfo->pool, pinfo, proto_mka, PEER_SCI_KEY4, sci_map);
764 mi_array = wmem_array_new(pinfo->pool, MKA_MI_LEN12U);
765 p_add_proto_data(pinfo->pool, pinfo, proto_mka, PEER_MI_KEY5, mi_array);
766 }
767
768 ti = proto_tree_add_item(mka_tree, hf_mka_live_peer_list_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
769 live_peer_list_set_tree = proto_item_add_subtree(ti, ett_mka_live_peer_list_set);
770
771 proto_tree_add_uint(live_peer_list_set_tree, hf_mka_param_set_type, tvb, offset, 1, LIVE_PEER_LIST_TYPE1);
772 offset += 1;
773
774 if (key_server_ssci_flag)
775 {
776 /* XXX - The presence of this field is non-trivial to find out. See IEEE 802.1X-2020, Section 11.11.3
777 * Only present in MKPDU's with:
778 * - MKA version 3 (that's covered), and
779 * - In Live Peer list parameter set (that's covered), and
780 * - A Distributed SAK parameter set present (which could be before or after this parameter set*), but only
781 * - A Distributed SAK parameter set with XPN Cipher suites (requires to look into the contents),
782 * otherwise 0.
783 *
784 * * - 802.1X-2010 and 802.1X-2020 both specify (11.11.3 Encoding MKPDUs)
785 * that implementations with a MKA Version Identifier of 1, 2, or 3 all
786 * shall encode the protocol parameters as follows:
787 * a) The Basic Parameter Set is encoded first.
788 * b) The remaining parameter sets, except for the Live Peer List,
789 * Potential Peer List, and ICV Indicator are then encoded in
790 * parameter set type ascending order.
791 * c) The Live Peer List, if present, is encoded next.
792 * d) The Potential Peer List, if present, is encoded next.
793 * e) The ICV Indicator, if present (i.e. the Algorithm Agility
794 * parameter indicates an ICV of length other than 16 octets)
795 * is encoded last.
796 * That would make our lives easier, but in practice, implementations
797 * do not do this. A common approach is to order *all* the parameter
798 * sets other than the Basic Parameter Set in ascending type order,
799 * which puts the Live Peer List before the Distributed SAK. Some
800 * implementations include the ICV Indicator even when not necessary.
801 *
802 * Since 0 is not used as an SSCI and even though the SSCI is 32-bits
803 * in practice it cannot be larger than 255 (9.10) or even 100 or less
804 * (see the NOTE in IEEE 802.1AE-2018 10.7.13), it suffices in normal
805 * operation to add it here iff the value is nonzero.
806 */
807 server_ssci = tvb_get_uint8(tvb, offset);
808 if (server_ssci) {
809 proto_tree_add_item(live_peer_list_set_tree, hf_mka_key_server_ssci, tvb, offset, 1, ENC_NA0x00000000);
810 }
811 }
812
813 bool_Bool know_all_sci = false0;
814 if (sci_map) {
815 know_all_sci = true1;
816 if (server_ssci) {
817 wmem_map_insert(sci_map, sci, GUINT_TO_POINTER(server_ssci)((gpointer) (gulong) (server_ssci)));
818 } else {
819 wmem_map_insert(sci_map, sci, GUINT_TO_POINTER(UINT32_MAX)((gpointer) (gulong) ((4294967295U))));
820 }
821 if (server_ssci > 1) {
822 uint8_t *zeroes = wmem_alloc0(pinfo->pool, MKA_MI_LEN12U * (server_ssci - 1));
823 wmem_array_append(mi_array, zeroes, server_ssci - 1);
824 }
825 wmem_array_append(mi_array, mi, 1);
826 }
827
828 offset += 1;
829
830 proto_tree_add_uint(live_peer_list_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
831 offset += 2;
832
833 unsigned index = 1; // SSCIs start at 1
834 while (param_body_len >= 16) {
835 /* If this is MKA version 3 and a Live Peer List in a MKPDU that contains
836 * a Distributed SAK, then the MIs are ordered in order of their SCI. This,
837 * combined with the SSCI least significant octet of the Key Server (see
838 * above) can be used to determine the SCI->SSCI mapping for XPN cipher
839 * suites, provided that the MI->SCI mapping was also recorded from the
840 * MKPDUs sent by those actors.
841 *
842 * In practice, since the SSCIs are assigned incrementing from 1, we can
843 * record the number of peers in the Live Peer List (plus the Key Server
844 * itself) and try all of them in the MACsec dissector, if necessary.
845 */
846 proto_tree_add_item(live_peer_list_set_tree, hf_mka_peer_mi, tvb, offset, MKA_MI_LEN12U, ENC_NA0x00000000);
847 if (sci_map) {
848 mi = tvb_memdup(pinfo->pool, tvb, offset, MKA_MI_LEN12U);
849 if (index >= server_ssci) {
850 // This is the correct 1-indexed position if server_ssci is 0
851 // Because the server SCI was put at the first position.
852 ssci = index + 1;
853 } else {
854 ssci = index;
855 }
856 // Do we know the SCI for this MI?
857 sci = wmem_map_lookup(mka_mi_sci_map, mi);
858 if (sci) {
859 if (server_ssci) {
860 wmem_map_insert(sci_map, sci, GUINT_TO_POINTER(ssci)((gpointer) (gulong) (ssci)));
861 } else {
862 /* This value is to get around wmem_map_find() not being able to
863 * distinguish between finding 0 and not finding a result.
864 * (There's no equivalent of wmem_map_lookup_extended.)
865 */
866 wmem_map_insert(sci_map, sci, GUINT_TO_POINTER(UINT32_MAX)((gpointer) (gulong) ((4294967295U))));
867 }
868 } else {
869 know_all_sci = false0;
870 }
871 if (ssci == wmem_array_get_count(mi_array) + 1) {
872 wmem_array_append(mi_array, mi, 1);
873 } else if (ssci < wmem_array_get_count(mi_array)) {
874 memcpy(wmem_array_index(mi_array, ssci - 1), mi, MKA_MI_LEN12U);
875 } else {
876 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/dissectors/packet-mka.c", 876))
;
877 }
878 }
879 offset += MKA_MI_LEN12U;
880
881 proto_tree_add_item(live_peer_list_set_tree, hf_mka_peer_mn, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
882 offset += 4;
883
884 param_body_len -= 16;
885 index++;
886 }
887
888 if (mi_array && know_all_sci && !server_ssci) {
889 // For the case before MKA version 3, we manually sort these.
890 // XXX - Should we try sorting them anyway?
891 wmem_array_sort(mi_array, sort_mi_by_sci);
892 for (ssci = 1; ssci <= wmem_array_get_count(mi_array); ++ssci) {
893 mi = wmem_array_index(mi_array, ssci - 1);
894 sci = wmem_map_lookup(mka_mi_sci_map, mi);
895 if (sci) {
896 wmem_map_insert(sci_map, sci, GUINT_TO_POINTER(ssci)((gpointer) (gulong) (ssci)));
897 }
898 }
899 }
900
901 if (param_body_len != 0) {
902 proto_tree_add_expert(live_peer_list_set_tree, pinfo, &ei_mka_undecoded, tvb, offset, param_body_len);
903 }
904
905 return live_peer_list_set_tree;
906}
907
908static proto_tree *
909dissect_potential_peer_list(proto_tree *mka_tree, packet_info *pinfo, tvbuff_t *tvb, int offset, uint16_t param_body_len) {
910 proto_tree *potential_peer_list_set_tree;
911 proto_item *ti;
912
913 ti = proto_tree_add_item(mka_tree, hf_mka_potential_peer_list_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
914 potential_peer_list_set_tree = proto_item_add_subtree(ti, ett_mka_potential_peer_list_set);
915
916 proto_tree_add_uint(potential_peer_list_set_tree, hf_mka_param_set_type, tvb, offset, 1, POTENTIAL_PEER_LIST_TYPE2);
917 offset += 2;
918
919 proto_tree_add_uint(potential_peer_list_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
920 offset += 2;
921
922 while (param_body_len >= 16) {
923 proto_tree_add_item(potential_peer_list_set_tree, hf_mka_peer_mi, tvb, offset, MKA_MI_LEN12U, ENC_NA0x00000000);
924 offset += MKA_MI_LEN12U;
925
926 proto_tree_add_item(potential_peer_list_set_tree, hf_mka_peer_mn, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
927 offset += 4;
928
929 param_body_len -= 16;
930 }
931
932 if (param_body_len != 0) {
933 proto_tree_add_expert(potential_peer_list_set_tree, pinfo, &ei_mka_undecoded, tvb, offset, param_body_len);
934 }
935
936 return potential_peer_list_set_tree;
937}
938
939static proto_tree *
940dissect_sak_use(proto_tree *mka_tree, packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, uint16_t param_body_len) {
941 proto_tree *sak_use_set_tree;
942 proto_item *ti;
943 bool_Bool latest_rx, old_rx;
944 uint32_t pn;
945 uint8_t ki[MKA_KI_LEN16U];
946 mka_ki_pn_t *pn_key;
947
948 ti = proto_tree_add_item(mka_tree, hf_mka_macsec_sak_use_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
949 sak_use_set_tree = proto_item_add_subtree(ti, ett_mka_sak_use_set);
950
951 proto_tree_add_item(sak_use_set_tree, hf_mka_param_set_type, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
952 offset += 1;
953
954 proto_tree_add_item(sak_use_set_tree, hf_mka_latest_key_an, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
955 proto_tree_add_item(sak_use_set_tree, hf_mka_latest_key_tx, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
956 proto_tree_add_item_ret_boolean(sak_use_set_tree, hf_mka_latest_key_rx, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &latest_rx);
957
958 proto_tree_add_item(sak_use_set_tree, hf_mka_old_key_an, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
959 proto_tree_add_item(sak_use_set_tree, hf_mka_old_key_tx, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
960 proto_tree_add_item_ret_boolean(sak_use_set_tree, hf_mka_old_key_rx, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &old_rx);
961 offset += 1;
962
963 proto_tree_add_item(sak_use_set_tree, hf_mka_plain_tx, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
964 proto_tree_add_item(sak_use_set_tree, hf_mka_plain_rx, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
965 proto_tree_add_item(sak_use_set_tree, hf_mka_delay_protect, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
966
967 proto_tree_add_uint(sak_use_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
968 offset += 2;
969
970 /*
971 * 802.1X-2020 specifies only 0 or 40 are valid! See Figure 11-10 Note d
972 */
973 if (param_body_len == 0) /* MACsec not supported */
974 {
975 /* Nothing */
976 }
977 else if (param_body_len == 40) /* MACsec supported */
978 {
979 proto_tree_add_item(sak_use_set_tree, hf_mka_latest_key_server_mi, tvb, offset, 12, ENC_NA0x00000000);
980 if (latest_rx && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
981 tvb_memcpy(tvb, ki, offset, MKA_KI_LEN16U);
982 }
983 offset += 12;
984
985 proto_tree_add_item(sak_use_set_tree, hf_mka_latest_key_number, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
986 offset += 4;
987 if (latest_rx && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
988 proto_tree_add_item_ret_uint(sak_use_set_tree, hf_mka_latest_lowest_acceptable_pn, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &pn);
989
990 pn_key = wmem_new(pinfo->pool, mka_ki_pn_t)((mka_ki_pn_t*)wmem_alloc((pinfo->pool), sizeof(mka_ki_pn_t
)))
;
991 memcpy(pn_key->ki, ki, MKA_KI_LEN16U);
992 pn_key->pn = pn;
993 p_add_proto_data(pinfo->pool, pinfo, proto_mka, LATEST_KEY6, pn_key);
994 } else {
995 proto_tree_add_item(sak_use_set_tree, hf_mka_latest_lowest_acceptable_pn, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
996 }
997 offset += 4;
998
999 proto_tree_add_item(sak_use_set_tree, hf_mka_old_key_server_mi, tvb, offset, 12, ENC_NA0x00000000);
1000 if (old_rx && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
1001 tvb_memcpy(tvb, ki, offset, MKA_KI_LEN16U);
1002 }
1003 offset += 12;
1004
1005 proto_tree_add_item(sak_use_set_tree, hf_mka_old_key_number, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
1006 offset += 4;
1007
1008 if (old_rx && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
1009 proto_tree_add_item_ret_uint(sak_use_set_tree, hf_mka_old_lowest_acceptable_pn, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &pn);
1010 pn_key = wmem_new(pinfo->pool, mka_ki_pn_t)((mka_ki_pn_t*)wmem_alloc((pinfo->pool), sizeof(mka_ki_pn_t
)))
;
1011 memcpy(pn_key->ki, ki, MKA_KI_LEN16U);
1012 pn_key->pn = pn;
1013 p_add_proto_data(pinfo->pool, pinfo, proto_mka, OLD_KEY7, pn_key);
1014 } else {
1015 proto_tree_add_item(sak_use_set_tree, hf_mka_old_lowest_acceptable_pn, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
1016 }
1017 offset += 4;
1018 }
1019 else
1020 {
1021 proto_tree_add_expert(sak_use_set_tree, pinfo, &ei_mka_undecoded, tvb, offset, param_body_len);
1022 }
1023
1024 return sak_use_set_tree;
1025}
1026
1027static void
1028mka_sci_map_copy(void *key, void *value, void *user_data) {
1029 wmem_map_t *target_map = (wmem_map_t*)user_data;
1030 uint8_t *sci = (uint8_t*)key;
1031
1032 // The key here (SCI) is already in file scope (a pointer to a result in
1033 // the dissector global MI->SCI map), and the value is a GUINT_TO_POINTER,
1034 // so we don't need to wmem_memdup anything.
1035 wmem_map_insert(target_map, sci, value);
1036}
1037
1038static proto_tree *
1039dissect_distributed_sak(proto_tree *mka_tree, packet_info *pinfo, tvbuff_t *tvb, int offset, uint16_t param_body_len) {
1040 proto_tree *distributed_sak_tree;
1041 proto_item *ti;
1042
1043 ti = proto_tree_add_item(mka_tree, hf_mka_distributed_sak_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
1044 distributed_sak_tree = proto_item_add_subtree(ti, ett_mka_distributed_sak_set);
1045
1046 proto_tree_add_uint(distributed_sak_tree, hf_mka_param_set_type, tvb, offset, 1, DISTRIBUTED_SAK_TYPE4);
1047 offset += 1;
1048
1049 /* distributed AN is used later if use of MKA is enabled */
1050 uint8_t distributed_an = ((tvb_get_uint8(tvb, offset) & 0xC0) >> 6);
1051
1052 proto_tree_add_item(distributed_sak_tree, hf_mka_distributed_an, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1053 proto_tree_add_item(distributed_sak_tree, hf_mka_confidentiality_offset, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1054 /* XXX - The offset > 0 (2, 3) here must match the macsec capability (3) in the basic parameter set. */
1055 offset += 1;
1056
1057 proto_tree_add_uint(distributed_sak_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
1058 offset += 2;
1059
1060 if (param_body_len == 0) // Plain text
1061 {
1062 // Nothing
1063 }
1064 else if ((DISTRIBUTED_SAK_AES128_BODY_LEN28 == param_body_len) || (DISTRIBUTED_SAK_AES128_XPN_BODY_LEN36 <= param_body_len)) { // GCM-AES-128, GCM-AES-XPN-128, GCM-AES-256, GCM-AES-XPN-256
1065 uint64_t cipher_suite = MACSEC_GCM_AES_1280x0080C20001000001UL; // Default if not specified
1066 uint16_t wrappedlen = WRAPPED_KEY_LEN(AES128_KEY_LEN)((16) + 8);
1067 uint32_t kn;
1068 mka_sak_info_key_t *sak_info;
1069 uint8_t *sak;
1070
1071 proto_tree_add_item_ret_uint(distributed_sak_tree, hf_mka_key_number, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &kn);
1072 offset += 4;
1073
1074 /* For AES256, the wrapped key is longer and an 8 byte cipher suite is inserted before the wrapped key data. */
1075 if (DISTRIBUTED_SAK_AES128_XPN_BODY_LEN36 <= param_body_len) {
1076 proto_tree_add_item_ret_uint64(distributed_sak_tree, hf_mka_macsec_cipher_suite, tvb, offset, CIPHER_SUITE_LEN8, ENC_BIG_ENDIAN0x00000000, &cipher_suite);
1077 offset += CIPHER_SUITE_LEN8;
1078 switch (cipher_suite) {
1079 case MACSEC_GCM_AES_XPN_1280x0080C20001000003UL:
1080 break;
1081
1082 case MACSEC_GCM_AES_XPN_2560x0080C20001000004UL:
1083 case MACSEC_GCM_AES_2560x0080C20001000002UL:
1084 wrappedlen = WRAPPED_KEY_LEN(AES256_KEY_LEN)((32) + 8);
1085 break;
1086 default:
1087 proto_tree_add_expert(distributed_sak_tree, pinfo, &ei_mka_undecoded, tvb, offset, param_body_len - 12);
1088 goto out;
1089 }
1090 }
1091
1092 /* Add the wrapped key data. */
1093 const uint8_t *wrappedkey = tvb_memdup(pinfo->pool, tvb, offset, wrappedlen);
1094 proto_tree_add_item(distributed_sak_tree, hf_mka_aes_key_wrap_sak, tvb, offset, wrappedlen, ENC_NA0x00000000);
1095 offset += wrappedlen;
Value stored to 'offset' is never read
1096
1097 /* Attempt to unwrap the key using the KEK for the CKN. */
1098 /* Fetch the KEK for the CKN in the basic parameter set. */
1099 mka_ckn_info_t *rec = p_get_proto_data(pinfo->pool, pinfo, proto_mka, CKN_KEY0);
1100 if (NULL((void*)0) == rec) {
1101 ws_info("no record for CKN")do { if (1) { ws_log_full("MKA", LOG_LEVEL_INFO, ((void*)0), -
1, ((void*)0), "no record for CKN"); } } while (0)
;
1102 goto out;
1103 }
1104
1105 /* Look up the CKN and if found in the table, use the KEK associated with it. */
1106 ws_debug("CKN entry name: %s", rec->name)do { if (1) { ws_log_full("MKA", LOG_LEVEL_DEBUG, "epan/dissectors/packet-mka.c"
, 1106, __func__, "CKN entry name: %s", rec->name); } } while
(0)
;
1107
1108 /* If no KEK available, skip the decode. */
1109 mka_ckn_info_key_t *key = &(rec->key);
1110 if ((NULL((void*)0) == key) || (0 == key->kek_len)) {
1111 goto out;
1112 }
1113
1114 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
1115 /* Open the cipher context. */
1116 gcry_cipher_hd_t hd;
1117 if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_AESWRAP, 0)) {
1118 ws_warning("failed to open cipher context")do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 1118, __func__, "failed to open cipher context"); } } while
(0)
;
1119 goto out;
1120 }
1121
1122 if (gcry_cipher_setkey(hd, key->kek, key->kek_len)) {
1123 ws_warning("failed to set KEK")do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 1123, __func__, "failed to set KEK"); } } while (0)
;
1124 gcry_cipher_close(hd);
1125 goto out;
1126 }
1127
1128 sak_info = get_or_create_sak_info(rec, distributed_an, pinfo->num);
1129
1130 /* Unwrap the key with the KEK. */
1131 sak = sak_info->sak;
1132 sak_info->sak_len = wrappedlen - WRAPPED_KEY_IV_LEN8;
1133 if (gcry_cipher_decrypt(hd, sak, sak_info->sak_len, wrappedkey, wrappedlen) ) {
1134 ws_info("failed to unwrap SAK")do { if (1) { ws_log_full("MKA", LOG_LEVEL_INFO, ((void*)0), -
1, ((void*)0), "failed to unwrap SAK"); } } while (0)
;
1135 memset(sak, 0, MKA_MAX_SAK_LEN((32)));
1136 sak_info->sak_len = 0;
1137 gcry_cipher_close(hd);
1138 goto out;
1139 }
1140
1141 /* Add the Key Identifier */
1142 uint8_t *mi = p_get_proto_data(pinfo->pool, pinfo, proto_mka, MI_KEY2);
1143 /* This is added in the Basic Parameter Set, which is always dissected. */
1144 DISSECTOR_ASSERT(mi != NULL)((void) ((mi != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-mka.c"
, 1144, "mi != ((void*)0)"))))
;
1145 memcpy(sak_info->ki, mi, MKA_MI_LEN12U);
1146 phtonu32(&sak_info->ki[MKA_MI_LEN12U], kn);
1147
1148 sak_info->cipher_suite = cipher_suite;
1149 wmem_map_t *sci_map = p_get_proto_data(pinfo->pool, pinfo, proto_mka, PEER_SCI_KEY4);
1150 if (sci_map) {
1151 wmem_map_foreach(sci_map, mka_sci_map_copy, sak_info->sci_map);
1152 }
1153 wmem_array_t *mi_array = p_get_proto_data(pinfo->pool, pinfo, proto_mka, PEER_MI_KEY5);
1154 if (mi_array) {
1155 wmem_array_append(sak_info->mi_array, wmem_array_get_raw(mi_array), wmem_array_get_count(mi_array));
1156 }
1157 if (cipher_suite == MACSEC_GCM_AES_XPN_1280x0080C20001000003UL || cipher_suite == MACSEC_GCM_AES_XPN_2560x0080C20001000004UL) {
1158 /* 802.1AE-2018 10.7.8 SAK creation
1159 * "The 64 least significant bits of the Salt are the 64 least significant
1160 * bits of the MKA Key Server’s Member Identifier (MI), the 16 next most
1161 * significant bits of the Salt comprise the exclusive-or of the 16 next
1162 * most significant bits of that MI with the 16 most significant bits of
1163 * the 32-bit MKA Key Number (KN), and the 16 most significant bits of
1164 * the Salt comprise the exclusive-or of the 16 most significant bits of
1165 * that MI with the 16 least significant bits of the KN.
1166 */
1167 uint32_t mi_upper = pntohu32(mi);
1168 mi_upper ^= (kn >> 16);
1169 mi_upper ^= (kn & UINT16_MAX(65535)) << 16;
1170 phtonu32(mi, mi_upper);
1171 memcpy(sak_info->salt, mi, MACSEC_XPN_SALT_LEN12U);
1172 }
1173
1174 /* Close the cipher context. */
1175 gcry_cipher_close(hd);
1176
1177 p_add_proto_data(pinfo->pool, pinfo, proto_mka, SAK_KEY3, sak_info);
1178
1179 if (ws_log_msg_is_active(WS_LOG_DOMAIN"MKA", LOG_LEVEL_DEBUG)) {
1180 char *sak_str = bytes_to_str_maxlen(pinfo->pool, sak, sak_info->sak_len, 0);
1181 ws_debug("unwrapped sak: %s", sak_str)do { if (1) { ws_log_full("MKA", LOG_LEVEL_DEBUG, "epan/dissectors/packet-mka.c"
, 1181, __func__, "unwrapped sak: %s", sak_str); } } while (0
)
;
1182 }
1183 } else {
1184 /* Do not try to create on the second pass, only retrieve. */
1185 sak_info = get_sak_info(rec, distributed_an, pinfo->num);
1186 if (!sak_info)
1187 goto out;
1188 }
1189
1190 /* Add the unwrapped SAK to the output. */
1191 tvbuff_t *sak_tvb = tvb_new_child_real_data(tvb, sak_info->sak, sak_info->sak_len, sak_info->sak_len);
1192 add_new_data_source(pinfo, sak_tvb, "Unwrapped SAK");
1193 proto_tree_add_item(distributed_sak_tree, hf_mka_aes_key_wrap_unwrapped_sak, sak_tvb, 0, sak_info->sak_len, ENC_NA0x00000000);
1194 }
1195 else
1196 {
1197 proto_tree_add_expert(distributed_sak_tree, pinfo, &ei_mka_undecoded, tvb, offset, param_body_len);
1198 }
1199
1200out:
1201 return distributed_sak_tree;
1202}
1203
1204static proto_tree *
1205dissect_distributed_cak(proto_tree *mka_tree, packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, uint16_t param_body_len) {
1206 proto_tree *distributed_cak_tree;
1207 proto_item *ti;
1208 uint16_t cak_len;
1209
1210 ti = proto_tree_add_item(mka_tree, hf_mka_distributed_cak_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
1211 distributed_cak_tree = proto_item_add_subtree(ti, ett_mka_distributed_cak_set);
1212
1213 proto_tree_add_uint(distributed_cak_tree, hf_mka_param_set_type, tvb, offset, 1, DISTRIBUTED_CAK_TYPE5);
1214 offset += 2;
1215
1216 proto_tree_add_uint(distributed_cak_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
1217 offset += 2;
1218
1219 proto_tree_add_item(distributed_cak_tree, hf_mka_aes_key_wrap_cak, tvb, offset, 24, ENC_NA0x00000000);
1220 offset += 24;
1221
1222 cak_len = param_body_len - 24;
1223 proto_tree_add_item(distributed_cak_tree, hf_mka_cak_name, tvb, offset, cak_len, ENC_NA0x00000000);
1224 mka_add_ckn_info(distributed_cak_tree, tvb, offset, cak_len);
1225
1226 return distributed_cak_tree;
1227}
1228
1229static proto_tree *
1230dissect_kmd(proto_tree *mka_tree, packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, uint16_t param_body_len) {
1231 proto_tree *kmd_set_tree;
1232 proto_item *ti;
1233
1234 ti = proto_tree_add_item(mka_tree, hf_mka_kmd_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
1235 kmd_set_tree = proto_item_add_subtree(ti, ett_mka_kmd_set);
1236
1237 proto_tree_add_uint(kmd_set_tree, hf_mka_param_set_type, tvb, offset, 1, KMD_TYPE6);
1238 offset += 2;
1239
1240 proto_tree_add_uint(kmd_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
1241 offset += 2;
1242
1243 // Ref 802.1X-2020, 12.6 KMD: A string of up to 253 UTF-8 characters.
1244 proto_tree_add_item(kmd_set_tree, hf_mka_kmd, tvb, offset, param_body_len, ENC_UTF_80x00000002);
1245
1246 return kmd_set_tree;
1247}
1248
1249static proto_tree *
1250dissect_announcement(proto_tree *mka_tree, packet_info *pinfo, tvbuff_t *tvb, int offset, uint16_t param_body_len) {
1251 proto_tree *announcement_set_tree;
1252 proto_item *ti;
1253 int offset2;
1254
1255 ti = proto_tree_add_item(mka_tree, hf_mka_announcement_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
1256 announcement_set_tree = proto_item_add_subtree(ti, ett_mka_announcement_set);
1257
1258 proto_tree_add_uint(announcement_set_tree, hf_mka_param_set_type, tvb, offset, 1, ANNOUNCEMENT_TYPE7);
1259 offset += 2;
1260
1261 proto_tree_add_uint(announcement_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
1262 offset += 2;
1263
1264 offset2 = 0;
1265 while (offset2 + 2 <= param_body_len) {
1266 proto_tree *tlv_tree;
1267 uint8_t tlv_type = ((tvb_get_uint8(tvb, offset + offset2)) & 0xfe ) >> 1;
1268 uint16_t tlv_length = (tvb_get_ntohs(tvb, offset + offset2)) & 0x01ff;
1269
1270 if (offset2 + 2 + tlv_length > param_body_len) {
1271 break;
1272 }
1273
1274 ti = proto_tree_add_none_format(announcement_set_tree, hf_mka_tlv_entry, tvb, offset + offset2, tlv_length + 2, "TLV entry: %s",
1275 val_to_str(pinfo->pool, tlv_type, macsec_tlvs, "unknown TLV type: %d"));
1276 tlv_tree = proto_item_add_subtree(ti, ett_mka_tlv);
1277
1278 proto_tree_add_item(tlv_tree, hf_mka_tlv_type, tvb, offset + offset2, 1, ENC_NA0x00000000);
1279 proto_tree_add_item(tlv_tree, hf_mka_tlv_info_string_length, tvb, offset + offset2, 2, ENC_BIG_ENDIAN0x00000000);
1280 offset2 += 2;
1281
1282 if (tlv_length > 0) {
1283 // See IEEE 802.1X-2010, Section 11.11.1, Figure 11-15 and Section 11.12
1284 switch (tlv_type) {
1285 case 112: // MACsec Cipher Suites
1286 for (uint16_t tlv_item_offset = 0; tlv_item_offset + 10 <= tlv_length; tlv_item_offset += 8) {
1287 proto_tree *cipher_suite_entry;
1288 uint64_t cipher_suite_id = tvb_get_uint64(tvb, offset + offset2 + tlv_item_offset + 2, ENC_BIG_ENDIAN0x00000000);
1289 uint16_t cipher_suite_cap = tvb_get_uint16(tvb, offset + offset2 + tlv_item_offset, ENC_BIG_ENDIAN0x00000000) & 0x0003;
1290
1291 ti = proto_tree_add_none_format(tlv_tree, hf_mka_tlv_entry, tvb, offset + offset2, tlv_length + 2, "Cipher Suite: %s, %s",
1292 val64_to_str_wmem(pinfo->pool, cipher_suite_id, macsec_cipher_suite_vals, "Unknown Cipher Suite (0x%" PRIx64"l" "x" ")"),
1293 val_to_str(pinfo->pool, cipher_suite_cap, macsec_capability_type_vals, "Unknown Capability (%d)"));
1294 cipher_suite_entry = proto_item_add_subtree(ti, ett_mka_cipher_suite_entry);
1295
1296 proto_tree_add_item(cipher_suite_entry, hf_mka_tlv_cipher_suite_impl_cap, tvb, offset + offset2 + tlv_item_offset, 2, ENC_BIG_ENDIAN0x00000000);
1297 tlv_item_offset += 2;
1298 proto_tree_add_item(cipher_suite_entry, hf_mka_macsec_cipher_suite, tvb, offset + offset2 + tlv_item_offset, 8, ENC_BIG_ENDIAN0x00000000);
1299 }
1300 break;
1301
1302 case 113: // Key Management Domain
1303 proto_tree_add_item(tlv_tree, hf_mka_kmd, tvb, offset + offset2, tlv_length, ENC_UTF_80x00000002);
1304 break;
1305
1306 case 111: // Access Information
1307 case 114: // NID (Network Identifier)
1308 proto_tree_add_expert(tlv_tree, pinfo, &ei_mka_unimplemented, tvb, offset + offset2, tlv_length);
1309 proto_tree_add_item(tlv_tree, hf_mka_tlv_data, tvb, offset + offset2, tlv_length, ENC_NA0x00000000);
1310 break;
1311
1312 default:
1313 proto_tree_add_item(tlv_tree, hf_mka_tlv_data, tvb, offset + offset2, tlv_length, ENC_NA0x00000000);
1314 }
1315 offset2 += tlv_length;
1316 }
1317 }
1318
1319 return announcement_set_tree;;
1320}
1321
1322static proto_tree *
1323dissect_xpn(proto_tree *mka_tree, packet_info *pinfo, tvbuff_t *tvb, int offset, uint16_t param_body_len) {
1324 proto_tree *xpn_set_tree;
1325 proto_item *ti;
1326 uint32_t pn_msb;
1327 mka_ki_pn_t *pn_key;
1328 uint8_t *mi, *sci = NULL((void*)0);
1329
1330 ti = proto_tree_add_item(mka_tree, hf_mka_xpn_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
1331 xpn_set_tree = proto_item_add_subtree(ti, ett_mka_xpn_set);
1332
1333 proto_tree_add_uint(xpn_set_tree, hf_mka_param_set_type, tvb, offset, 1, XPN_TYPE8);
1334 offset += 1;
1335
1336 proto_tree_add_item(xpn_set_tree, hf_mka_suspension_time, tvb, offset, 1, ENC_NA0x00000000);
1337 offset += 1;
1338
1339 proto_tree_add_uint(xpn_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
1340 offset += 2;
1341
1342 /* Based on samples, we should be able to assume that the spec is followed
1343 * and the XPN parameter set appears after the MACsec SAK Use set */
1344 pn_key = p_get_proto_data(pinfo->pool, pinfo, proto_mka, LATEST_KEY6);
1345 if (pn_key) {
1346 proto_tree_add_item_ret_uint(xpn_set_tree, hf_mka_latest_lowest_accept_pn_msb, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &pn_msb);
1347 pn_key->pn |= ((uint64_t)pn_msb << 32);
1348 mi = p_get_proto_data(pinfo->pool, pinfo, proto_mka, MI_KEY2);
1349 sci = wmem_map_lookup(mka_mi_sci_map, mi);
1350 DISSECTOR_ASSERT(sci)((void) ((sci) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-mka.c", 1350, "sci"))))
;
1351 update_lpn(pn_key, sci, pinfo->num);
1352 } else {
1353 proto_tree_add_item(xpn_set_tree, hf_mka_latest_lowest_accept_pn_msb, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
1354 }
1355 offset += 4;
1356
1357 pn_key = p_get_proto_data(pinfo->pool, pinfo, proto_mka, OLD_KEY7);
1358 if (pn_key) {
1359 proto_tree_add_item_ret_uint(xpn_set_tree, hf_mka_old_lowest_accept_pn_msb, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &pn_msb);
1360 pn_key->pn |= ((uint64_t)pn_msb << 32);
1361 if (sci == NULL((void*)0)) {
1362 mi = p_get_proto_data(pinfo->pool, pinfo, proto_mka, MI_KEY2);
1363 sci = wmem_map_lookup(mka_mi_sci_map, mi);
1364 DISSECTOR_ASSERT(sci)((void) ((sci) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-mka.c", 1364, "sci"))))
;
1365 }
1366 update_lpn(pn_key, sci, pinfo->num);
1367 } else {
1368 proto_tree_add_item(xpn_set_tree, hf_mka_old_lowest_accept_pn_msb, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
1369 }
1370
1371 return xpn_set_tree;
1372}
1373
1374static proto_tree *
1375dissect_icv(proto_tree *mka_tree, packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, uint16_t param_body_len) {
1376 proto_tree *icv_set_tree;
1377 proto_item *ti;
1378
1379 ti = proto_tree_add_item(mka_tree, hf_mka_icv_set, tvb, offset, 4, ENC_NA0x00000000);
1380 icv_set_tree = proto_item_add_subtree(ti, ett_mka_icv_set);
1381
1382 proto_tree_add_uint(icv_set_tree, hf_mka_param_set_type, tvb, offset, 1, ICV_TYPE255);
1383 offset += 2;
1384
1385 proto_tree_add_uint(icv_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
1386
1387 return icv_set_tree;
1388}
1389
1390static proto_tree *
1391dissect_unknown_param_set(proto_tree *mka_tree, packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, uint16_t param_body_len, uint8_t param_set_type) {
1392 proto_tree *param_set_tree;
1393 proto_item *ti;
1394
1395 ti = proto_tree_add_item(mka_tree, hf_mka_unknown_set, tvb, offset, param_body_len + 4, ENC_NA0x00000000);
1396 param_set_tree = proto_item_add_subtree(ti, ett_mka_unknown_set);
1397
1398 proto_tree_add_uint(param_set_tree, hf_mka_param_set_type, tvb, offset, 1, param_set_type);
1399 offset += 2;
1400
1401 proto_tree_add_uint(param_set_tree, hf_mka_param_body_length, tvb, offset, 2, param_body_len);
1402 offset += 2;
1403
1404 proto_tree_add_item(param_set_tree, hf_mka_unknown_param_set, tvb, offset, param_body_len, ENC_NA0x00000000);
1405
1406 return param_set_tree;
1407}
1408
1409static uint8_t*
1410calculate_icv(packet_info *pinfo, size_t icv_len) {
1411 /* IEEE Std 802.1X-2020 9.4.1 Message authentication
1412 *
1413 * Each protocol data unit (MKPDU) transmitted is integrity protected by an
1414 * 128 bit ICV, generated by AES-CMAC using the ICK (9.3):
1415 *
1416 * ICV = AES-CMAC(ICK, M, 128)
1417 * M = DA + SA + (MSDU – ICV)
1418 *
1419 * In other words, M comprises the concatenation of the destination and source
1420 * MAC addresses, each represented by a sequence of 6 octets in canonical
1421 * format order, with the MSDU (MAC Service Data Unit) of the MKPDU including
1422 * the allocated Ethertype, and up to but not including, the generated ICV.
1423 *
1424 * NOTE—M comprises the whole of what is often referred to as ‘the frame’
1425 * considered from the point of view of the MAC Service provided by Common
1426 * Port of the SecY (Figure 6-2) or PAC (Figure 6-6) supporting MKPDU
1427 * transmission. The description does not use the term ‘frame’, because that
1428 * Common Port could be supported by additional VLAN tags or other tags
1429 * (consider the upper SecY shown in Figure 7-17) prior to transmission of a
1430 * MAC frame by a system. Any such additional tags would not be covered by
1431 * the ICV, and would be removed prior to MKPDU reception by a peer PAE.
1432 */
1433
1434 if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
1435 return p_get_proto_data(wmem_file_scope(), pinfo, proto_mka, ICV_KEY1);
1436 }
1437
1438 gcry_error_t err;
1439 mka_ckn_info_t *rec = p_get_proto_data(pinfo->pool, pinfo, proto_mka, CKN_KEY0);
1440 proto_eapol_key_frame_t *eapol_frame = p_get_proto_data(pinfo->pool, pinfo, proto_eapol, EAPOL_KEY_FRAME_KEY0);
1441
1442 if (rec == NULL((void*)0) || eapol_frame == NULL((void*)0) || pinfo->dl_dst.type != AT_ETHER || pinfo->dl_src.type != AT_ETHER) {
1443 return NULL((void*)0);
1444 }
1445
1446 if (eapol_frame->len < icv_len) {
1447 return NULL((void*)0);
1448 }
1449
1450 /* Look up the CKN and if found, use the ICK associated with it. */
1451 ws_debug("CKN entry name: %s", rec->name)do { if (1) { ws_log_full("MKA", LOG_LEVEL_DEBUG, "epan/dissectors/packet-mka.c"
, 1451, __func__, "CKN entry name: %s", rec->name); } } while
(0)
;
1452
1453 /* If no ICK available, skip the calculation. */
1454 mka_ckn_info_key_t *key = &(rec->key);
1455 if ((NULL((void*)0) == key) || (0 == key->ick_len)) {
1456 return NULL((void*)0);
1457 }
1458
1459 /* Open the MAC context. */
1460 gcry_mac_hd_t hd;
1461 if ((err = gcry_mac_open(&hd, GCRY_MAC_CMAC_AES, 0, NULL((void*)0)))) {
1462 ws_warning("failed to open MAC context: %s", gcry_strerror(err))do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 1462, __func__, "failed to open MAC context: %s", gcry_strerror
(err)); } } while (0)
;
1463 return NULL((void*)0);
1464 }
1465
1466 if ((err = gcry_mac_setkey(hd, key->ick, key->ick_len))) {
1467 ws_warning("failed to set ICK: %s", gcry_strerror(err))do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 1467, __func__, "failed to set ICK: %s", gcry_strerror(err)
); } } while (0)
;
1468 goto failed;
1469 }
1470
1471 uint8_t *icv_calc = (uint8_t*)wmem_alloc0(wmem_file_scope(), icv_len);
1472 uint8_t eapol_ethertype[2];
1473 phtonu16(eapol_ethertype, ETHERTYPE_EAPOL0x888E);
1474 wmem_array_t *ethhdr = wmem_array_sized_new(pinfo->pool, sizeof(uint8_t), pinfo->dst.len + pinfo->src.len + 2);
1475 wmem_array_append(ethhdr, pinfo->dst.data, pinfo->dst.len);
1476 wmem_array_append(ethhdr, pinfo->src.data, pinfo->src.len);
1477 wmem_array_append(ethhdr, eapol_ethertype, sizeof(eapol_ethertype));
1478 if ((err = gcry_mac_write(hd, wmem_array_get_raw(ethhdr), wmem_array_get_count(ethhdr)))) {
1479 ws_warning("failed to update MAC: %s", gcry_strerror(err))do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 1479, __func__, "failed to update MAC: %s", gcry_strerror(err
)); } } while (0)
;
1480 goto failed;
1481 }
1482 if ((err = gcry_mac_write(hd, eapol_frame->data, eapol_frame->len - icv_len))) {
1483 ws_warning("failed to update MAC: %s", gcry_strerror(err))do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 1483, __func__, "failed to update MAC: %s", gcry_strerror(err
)); } } while (0)
;
1484 goto failed;
1485 }
1486 if ((err = gcry_mac_read(hd, icv_calc, &icv_len))) {
1487 ws_warning("failed to read MAC: %s", gcry_strerror(err))do { if (1) { ws_log_full("MKA", LOG_LEVEL_WARNING, "epan/dissectors/packet-mka.c"
, 1487, __func__, "failed to read MAC: %s", gcry_strerror(err
)); } } while (0)
;
1488 goto failed;
1489 }
1490
1491 /* Close the MAC context. */
1492 gcry_mac_close(hd);
1493 p_add_proto_data(wmem_file_scope(), pinfo, proto_mka, ICV_KEY1, icv_calc);
1494 return icv_calc;
1495
1496failed:
1497 gcry_mac_close(hd);
1498 return NULL((void*)0);
1499}
1500
1501/*
1502 * Ref 802.1X-2020, Figure 11-7
1503 */
1504static uint8_t
1505start_parameter_set(tvbuff_t *tvb, int offset, uint16_t *param_body_len) {
1506 *param_body_len = tvb_get_ntohs(tvb, offset + 2) & 0x0fff;
1507 return tvb_get_uint8(tvb, offset);
1508}
1509
1510static int
1511finalize_parameter_set(proto_tree *param_set_tree, tvbuff_t *tvb, int offset, uint8_t param_set_type, uint16_t param_body_len) {
1512 if (param_set_type != ICV_TYPE255) {
1513 unsigned padding_len;
1514
1515 offset += 4 + param_body_len;
1516 padding_len = WS_PADDING_TO_4(param_body_len)((4U - ((param_body_len) % 4U)) % 4U);
1517 if (padding_len != 0) {
1518 proto_tree_add_item(param_set_tree, hf_mka_padding, tvb, offset, padding_len, ENC_NA0x00000000);
1519
1520 offset += padding_len;
1521 }
1522 } else {
1523 offset += 4;
1524 }
1525
1526 return offset;
1527}
1528
1529static int
1530dissect_mka(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused))) {
1531 int offset = 0;
1532 uint8_t mka_version_type;
1533 uint8_t param_set_type;
1534 proto_tree *param_set_tree;
1535 uint16_t param_body_len;
1536 uint16_t icv_len = DEFAULT_ICV_LEN16;
1537 proto_item *ti;
1538 proto_tree *mka_tree;
1539
1540 col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAPOL-MKA");
1541 col_clear(pinfo->cinfo, COL_INFO);
1542
1543 ti = proto_tree_add_item(tree, proto_mka, tvb, 0, -1, ENC_NA0x00000000);
1544 mka_tree = proto_item_add_subtree(ti, ett_mka);
1545
1546 /*
1547 * Basic Parameter set is always the first parameter set, dissect it first !
1548 */
1549 mka_version_type = start_parameter_set(tvb, offset, &param_body_len);
1550
1551 /*
1552 * The 802.1X-2010 spec specifies support for MKA version 1 only.
1553 * The 802.1Xbx-2014 spec specifies support for MKA version 2.
1554 * The 802.1Xck-2018 spec specifies support for MKA version 3.
1555 */
1556 mka_version_type = tvb_get_uint8(tvb, offset);
1557 if ((mka_version_type < 1) || (mka_version_type > 3)) {
1558 expert_add_info(pinfo, ti, &ei_unexpected_data);
1559 }
1560
1561 param_set_tree = dissect_basic_paramset(mka_tree, pinfo, tvb, offset, param_body_len);
1562 offset = finalize_parameter_set(param_set_tree, tvb, offset, 0, param_body_len);
1563
1564 while(tvb_reported_length_remaining(tvb, offset) > icv_len) {
1565 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL((void*)0), "%s",
1566 val_to_str_const(tvb_get_uint8(tvb, offset), param_set_type_vals, "Unknown"));
1567 param_set_type = start_parameter_set(tvb, offset, &param_body_len);
1568 switch (param_set_type) {
1569 case LIVE_PEER_LIST_TYPE1:
1570 param_set_tree = dissect_live_peer_list(mka_tree, pinfo, tvb, offset, param_body_len, (mka_version_type == 3));
1571 break;
1572
1573 case POTENTIAL_PEER_LIST_TYPE2:
1574 param_set_tree = dissect_potential_peer_list(mka_tree, pinfo, tvb, offset, param_body_len);
1575 break;
1576
1577 case MACSEC_SAK_USE_TYPE3:
1578 param_set_tree = dissect_sak_use(mka_tree, pinfo, tvb, offset, param_body_len);
1579 break;
1580
1581 case DISTRIBUTED_SAK_TYPE4:
1582 param_set_tree = dissect_distributed_sak(mka_tree, pinfo, tvb, offset, param_body_len);
1583 break;
1584
1585 case DISTRIBUTED_CAK_TYPE5:
1586 param_set_tree = dissect_distributed_cak(mka_tree, pinfo, tvb, offset, param_body_len);
1587 break;
1588
1589 case KMD_TYPE6:
1590 param_set_tree = dissect_kmd(mka_tree, pinfo, tvb, offset, param_body_len);
1591 break;
1592
1593 case ANNOUNCEMENT_TYPE7:
1594 param_set_tree = dissect_announcement(mka_tree, pinfo, tvb, offset, param_body_len);
1595 break;
1596
1597 case XPN_TYPE8:
1598 param_set_tree = dissect_xpn(mka_tree, pinfo, tvb, offset, param_body_len);
1599 break;
1600
1601 case ICV_TYPE255:
1602 // This ICV indicator does not include the ICV itself, see IEEE 802.1X-2010, Section 11.11.1
1603 param_set_tree = dissect_icv(mka_tree, pinfo, tvb, offset, param_body_len);
1604 icv_len = param_body_len;
1605 break;
1606
1607 default:
1608 param_set_tree = dissect_unknown_param_set(mka_tree, pinfo, tvb, offset, param_body_len, param_set_type);
1609 break;
1610 }
1611
1612 offset = finalize_parameter_set(param_set_tree, tvb, offset, param_set_type, param_body_len);
1613 }
1614
1615 const uint8_t *icv_calc = calculate_icv(pinfo, icv_len);
1616 proto_tree_add_checksum_bytes(mka_tree, tvb, offset, hf_mka_icv, hf_mka_icv_status, &ei_mka_icv_bad, pinfo, icv_calc, icv_len, icv_calc ? PROTO_CHECKSUM_VERIFY0x01 : PROTO_CHECKSUM_NO_FLAGS0x00);
1617
1618 return tvb_captured_length(tvb);
1619}
1620
1621void
1622proto_register_mka(void) {
1623 module_t *mka_module;
1624 expert_module_t *expert_mka = NULL((void*)0);
1625
1626 uat_t *mka_ckn_info_uat = NULL((void*)0);
1627
1628 static ei_register_info ei[] = {
1629 { &ei_mka_icv_bad, {
1630 "mka.icv.bad", PI_CHECKSUM0x01000000, PI_ERROR0x00800000, "Bad ICV", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
1631
1632 { &ei_mka_undecoded, {
1633 "mka.expert.undecoded_data", PI_UNDECODED0x05000000, PI_WARN0x00600000, "Undecoded data", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
1634 { &ei_unexpected_data, {
1635 "mka.expert.unexpected_data", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Unexpected data", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
1636 { &ei_mka_unimplemented, {
1637 "mka.expert.unimplemented", PI_UNDECODED0x05000000, PI_WARN0x00600000, "Announcement TLV not handled, if you want this implemented please contact the wireshark developers", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}}
1638 };
1639
1640 static hf_register_info hf[] = {
1641 { &hf_mka_version_id, { "MKA Version Identifier", "mka.version_id", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1642 { &hf_mka_basic_param_set, { "Basic Parameter set", "mka.basic_param_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1643 { &hf_mka_live_peer_list_set, { "Live Peer List Parameter set", "mka.live_peer_list_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1644 { &hf_mka_potential_peer_list_set, { "Potential Peer List Parameter set", "mka.potential_peer_list_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1645 { &hf_mka_macsec_sak_use_set, { "MACsec SAK Use parameter set", "mka.macsec_sak_use_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1646 { &hf_mka_distributed_sak_set, { "Distributed SAK parameter set", "mka.distributed_sak_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1647 { &hf_mka_distributed_cak_set, { "Distributed CAK parameter set", "mka.distributed_cak_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1648 { &hf_mka_kmd_set, { "Key Management Domain set", "mka.kmd_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1649 { &hf_mka_announcement_set, { "Announcement parameter set", "mka.announcement_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1650 { &hf_mka_xpn_set, { "Extended Packet Numbering set", "mka.xpn_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1651 { &hf_mka_unknown_set, { "Unknown parameter set", "mka.unknown_set", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1652 { &hf_mka_unknown_param_set, { "Unknown parameter set", "mka.unknown_param_set", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1653 { &hf_mka_icv_set, { "Integrity Check Value Indicator", "mka.icv_indicator", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1654 { &hf_mka_param_set_type, { "Parameter set type", "mka.param_set_type", FT_UINT8, BASE_DEC, VALS(param_set_type_vals)((0 ? (const struct _value_string*)0 : ((param_set_type_vals)
)))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1655
1656 { &hf_mka_keyserver_priority, { "Key Server Priority", "mka.ks_prio", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1657 { &hf_mka_key_server, { "Key Server", "mka.key_server", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1658 { &hf_mka_macsec_desired, { "MACsec Desired", "mka.macsec_desired", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1659 { &hf_mka_macsec_capability, { "MACsec Capability", "mka.macsec_capability", FT_UINT8, BASE_DEC, VALS(macsec_capability_type_vals)((0 ? (const struct _value_string*)0 : ((macsec_capability_type_vals
))))
, 0x30, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1660 { &hf_mka_param_body_length, { "Parameter set body length", "mka.param_body_length", FT_UINT16, BASE_DEC, NULL((void*)0), 0x0fff, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1661 { &hf_mka_sci, { "SCI", "mka.sci", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1662 { &hf_mka_sci_system_identifier, { "System Identifier", "mka.sci.system_identifier", FT_ETHER, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1663 { &hf_mka_sci_port_identifier, { "Port Identifier", "mka.sci.port_identifier", FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1664 { &hf_mka_actor_mi, { "Actor Member Identifier", "mka.actor_mi", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1665 { &hf_mka_actor_mn, { "Actor Message Number", "mka.actor_mn", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1666 { &hf_mka_algo_agility, { "Algorithm Agility", "mka.algo_agility", FT_UINT32, BASE_HEX, VALS(algo_agility_vals)((0 ? (const struct _value_string*)0 : ((algo_agility_vals)))
)
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1667 { &hf_mka_cak_name, { "CAK Name", "mka.cak_name", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1668 { &hf_mka_cak_name_info, { "CAK Name Info", "mka.cak_name.info", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1669
1670 { &hf_mka_padding, { "Padding", "mka.padding", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1671
1672 { &hf_mka_key_server_ssci, { "Key Server SSCI (LSB)", "mka.key_server_ssci", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, "Only present combined with Distributed SAK parameter set with XPN cipher suite", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1673 { &hf_mka_peer_mi, { "Peer Member Identifier", "mka.peer_mi", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1674 { &hf_mka_peer_mn, { "Peer Message Number", "mka.peer_mn", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1675
1676 { &hf_mka_latest_key_an, { "Latest Key AN", "mka.latest_key_an", FT_UINT8, BASE_DEC, NULL((void*)0), 0xc0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1677 { &hf_mka_latest_key_tx, { "Latest Key tx", "mka.latest_key_tx", FT_BOOLEAN, 8, NULL((void*)0), 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1678 { &hf_mka_latest_key_rx, { "Latest Key rx", "mka.latest_key_rx", FT_BOOLEAN, 8, NULL((void*)0), 0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1679 { &hf_mka_old_key_an, { "Old Key AN", "mka.old_key_an", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0c, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1680 { &hf_mka_old_key_tx, { "Old Key tx", "mka.old_key_tx", FT_BOOLEAN, 8, NULL((void*)0), 0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1681 { &hf_mka_old_key_rx, { "Old Key rx", "mka.old_key_rx", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1682 { &hf_mka_plain_tx, { "Plain tx", "mka.plain_tx", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1683 { &hf_mka_plain_rx, { "Plain rx", "mka.plain_rx", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1684 { &hf_mka_delay_protect, { "Delay protect", "mka.delay_protect", FT_BOOLEAN, 8, NULL((void*)0), 0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1685 { &hf_mka_latest_key_server_mi, { "Latest Key: Key Server Member Identifier", "mka.latest_key_server_mi", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1686 { &hf_mka_latest_key_number, { "Latest Key: Key Number", "mka.latest_key_number", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1687 { &hf_mka_latest_lowest_acceptable_pn, { "Latest Key: Lowest Acceptable PN (32 LSB)", "mka.latest_lowest_acceptable_pn", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1688 { &hf_mka_old_key_server_mi, { "Old Key: Key Server Member Identifier", "mka.old_key_server_mi", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1689 { &hf_mka_old_key_number, { "Old Key: Key Number", "mka.old_key_number", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1690 { &hf_mka_old_lowest_acceptable_pn, { "Old Key: Lowest Acceptable PN (32 LSB)", "mka.old_lowest_acceptable_pn", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1691
1692 { &hf_mka_distributed_an, { "Distributed AN", "mka.distributed_an", FT_UINT8, BASE_DEC, NULL((void*)0), 0xc0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1693 { &hf_mka_confidentiality_offset, { "Confidentiality Offset", "mka.confidentiality_offset", FT_UINT8, BASE_DEC, VALS(confidentiality_offset_vals)((0 ? (const struct _value_string*)0 : ((confidentiality_offset_vals
))))
, 0x30, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1694 { &hf_mka_key_number, { "Key Number", "mka.key_number", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1695 { &hf_mka_aes_key_wrap_sak, { "AES Key Wrap of SAK", "mka.aes_key_wrap_sak", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1696 { &hf_mka_aes_key_wrap_unwrapped_sak, { "Unwrapped SAK", "mka.aes_key_wrap_unwrapped_sak", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1697 { &hf_mka_aes_key_wrap_cak, { "AES Key Wrap of CAK", "mka.aes_key_wrap_cak", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1698 { &hf_mka_macsec_cipher_suite, { "MACsec Cipher Suite", "mka.macsec_cipher_suite", FT_UINT64, BASE_HEX|BASE_VAL64_STRING0x00000400, VALS64(macsec_cipher_suite_vals)((0 ? (const struct _val64_string*)0 : ((macsec_cipher_suite_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1699
1700 { &hf_mka_kmd, { "Key Management Domain", "mka.kmd", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1701
1702 { &hf_mka_suspension_time, { "Suspension time", "mka.suspension_time", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1703 { &hf_mka_latest_lowest_accept_pn_msb, { "Latest Key: Lowest Acceptable PN (32 MSB)", "mka.latest_lowest_acceptable_pn_msb", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1704 { &hf_mka_old_lowest_accept_pn_msb, { "Old Key: Lowest Acceptable PN (32 MSB)", "mka.old_lowest_acceptable_pn_msb", FT_UINT32, BASE_DEC_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1705
1706 { &hf_mka_icv, { "Integrity Check Value", "mka.icv", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1707 { &hf_mka_icv_status, { "ICV Status", "mka.icv.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals)((0 ? (const struct _value_string*)0 : ((proto_checksum_vals)
)))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1708
1709 { &hf_mka_tlv_entry, { "TLV Entry", "mka.tlv_entry", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1710 { &hf_mka_tlv_type, { "TLV Type", "mka.tlv_type", FT_UINT8, BASE_DEC, VALS(macsec_tlvs)((0 ? (const struct _value_string*)0 : ((macsec_tlvs)))), 0xfe, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1711 { &hf_mka_tlv_info_string_length, { "TLV Info String Length", "mka.tlv_info_string_len", FT_UINT16, BASE_DEC, NULL((void*)0), 0x01ff, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1712 { &hf_mka_tlv_data, { "TLV Data", "mka.tlv_data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1713 { &hf_mka_tlv_cipher_suite_impl_cap, { "Cipher Suite Implementation Capabilities", "mka.tlv.cipher_suite_impl_cap", FT_UINT16, BASE_DEC, VALS(macsec_capability_type_vals)((0 ? (const struct _value_string*)0 : ((macsec_capability_type_vals
))))
, 0x0003, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1714 };
1715
1716 static int *ett[] = {
1717 &ett_mka,
1718 &ett_mka_sci,
1719 &ett_mka_basic_param_set,
1720 &ett_mka_live_peer_list_set,
1721 &ett_mka_potential_peer_list_set,
1722 &ett_mka_sak_use_set,
1723 &ett_mka_distributed_sak_set,
1724 &ett_mka_distributed_cak_set,
1725 &ett_mka_kmd_set,
1726 &ett_mka_announcement_set,
1727 &ett_mka_xpn_set,
1728 &ett_mka_unknown_set,
1729 &ett_mka_icv_set,
1730 &ett_mka_tlv,
1731 &ett_mka_cipher_suite_entry
1732 };
1733
1734 proto_mka = proto_register_protocol("MACsec Key Agreement", "EAPOL-MKA", "mka");
1735 register_dissector("mka", dissect_mka, proto_mka);
1736
1737 proto_register_field_array(proto_mka, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1738 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1739
1740 expert_mka = expert_register_protocol(proto_mka);
1741 expert_register_field_array(expert_mka, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1742
1743 mka_module = prefs_register_protocol(proto_mka, NULL((void*)0));
1744
1745 mka_mi_sci_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), mka_mi_hash, mka_mi_equal);
1746
1747 mka_ckn_sak_map = wmem_multimap_new_autoreset(wmem_epan_scope(), wmem_file_scope(), mka_sak_key_hash, mka_sak_key_equal);
1748 mka_ki_pn_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), mka_ki_hash, mka_ki_equal);
1749
1750 /* UAT: CKN info */
1751 static uat_field_t mka_ckn_uat_fields[] = {
1752 UAT_FLD_BUFFER(mka_ckn_uat_data, ckn, "CKN", "The CKN as byte array"){"ckn", "CKN", PT_TXTMOD_HEXBYTES,{0,mka_ckn_uat_data_ckn_set_cb
,mka_ckn_uat_data_ckn_tostr_cb},{0,0,0},0,"The CKN as byte array"
,((void*)0)}
,
1753 UAT_FLD_CSTRING(mka_ckn_uat_data, name, "Info", "CKN information string to be displayed"){"name", "Info", PT_TXTMOD_STRING,{uat_fld_chk_str,mka_ckn_uat_data_name_set_cb
,mka_ckn_uat_data_name_tostr_cb},{0,0,0},0,"CKN information string to be displayed"
,((void*)0)}
,
1754 UAT_FLD_BUFFER(mka_ckn_uat_data, cak, "CAK", "The CAK as byte array"){"cak", "CAK", PT_TXTMOD_HEXBYTES,{0,mka_ckn_uat_data_cak_set_cb
,mka_ckn_uat_data_cak_tostr_cb},{0,0,0},0,"The CAK as byte array"
,((void*)0)}
,
1755 UAT_END_FIELDS{((void*)0),((void*)0),PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,((void
*)0)}
1756 };
1757
1758 mka_ckn_info_uat = uat_new("CKN/CAK Info",
1759 sizeof(mka_ckn_info_t), /* record size */
1760 DATAFILE_CKN_INFO"mka_ckn_info", /* filename */
1761 true1, /* from profile */
1762 (void **) &mka_ckn_uat_data, /* data_ptr */
1763 &num_mka_ckn_uat_data, /* numitems_ptr */
1764 UAT_AFFECTS_DISSECTION0x00000001, /* but not fields */
1765 NULL((void*)0), /* help */
1766 ckn_info_copy_cb, /* copy callback */
1767 ckn_info_update_cb, /* update callback */
1768 ckn_info_free_cb, /* free callback */
1769 ckn_info_post_update_cb, /* post update callback */
1770 ckn_info_reset_cb, /* reset callback */
1771 mka_ckn_uat_fields /* UAT field definitions */
1772 );
1773
1774 uat_set_default_values(mka_ckn_info_uat, mka_ckn_info_uat_defaults_);
1775 prefs_register_uat_preference(mka_module, "ckn_info", "CKN/CAK Info", "A table to define CKNs and CAKs", mka_ckn_info_uat);
1776}
1777
1778void
1779proto_reg_handoff_mka(void) {
1780 static dissector_handle_t mka_handle;
1781
1782 mka_handle = create_dissector_handle(dissect_mka, proto_mka);
1783 dissector_add_uint("eapol.type", EAPOL_MKA5, mka_handle);
1784
1785 proto_eapol = proto_get_id_by_filter_name("eapol");
1786}
1787
1788/*
1789 * Editor modelines
1790 *
1791 * Local Variables:
1792 * c-basic-offset: 2
1793 * tab-width: 8
1794 * indent-tabs-mode: nil
1795 * End:
1796 *
1797 * ex: set shiftwidth=2 tabstop=8 expandtab:
1798 * :indentSize=2:tabSize=8:noTabs=true:
1799 */