### Bug Summary

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

### Annotated Source Code

Press '?' to see keyboard shortcuts

Show analyzer invocation
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-12-100331-3641-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-mka.c

Keyboard shortcuts:

- Use 'j/k' keys for keyboard navigation
- Use 'Shift+S' to show/hide relevant lines
- Use '?' to toggle this window

Close
Show only relevant lines Show control flow arrows

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 <maisheri.hitesh@gmail.com>
5 | *
6 | * Wireshark - Network traffic analyzer
7 | * By Gerald Combs <gerald@wireshark.org>
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 |
71 | void proto_register_mka(void);
72 | void proto_reg_handoff_mka(void);
73 |
74 | static int proto_mka;
75 | static int proto_eapol;
76 |
77 | static int hf_mka_version_id;
78 | static int hf_mka_basic_param_set;
79 | static int hf_mka_live_peer_list_set;
80 | static int hf_mka_potential_peer_list_set;
81 | static int hf_mka_macsec_sak_use_set;
82 | static int hf_mka_distributed_sak_set;
83 | static int hf_mka_distributed_cak_set;
84 | static int hf_mka_kmd_set;
85 | static int hf_mka_announcement_set;
86 | static int hf_mka_xpn_set;
87 | static int hf_mka_unknown_set;
88 | static int hf_mka_unknown_param_set;
89 | static int hf_mka_icv_set;
90 | static int hf_mka_param_set_type;
91 |
92 | static int hf_mka_keyserver_priority;
93 | static int hf_mka_key_server;
94 | static int hf_mka_macsec_desired;
95 | static int hf_mka_macsec_capability;
96 | static int hf_mka_param_body_length;
97 | static int hf_mka_sci;
98 | static int hf_mka_sci_system_identifier;
99 | static int hf_mka_sci_port_identifier;
100 | static int hf_mka_actor_mi;
101 | static int hf_mka_actor_mn;
102 | static int hf_mka_algo_agility;
103 | static int hf_mka_cak_name;
104 | static int hf_mka_cak_name_info;
105 |
106 | static int hf_mka_padding;
107 |
108 | static int hf_mka_key_server_ssci;
109 | static int hf_mka_peer_mi;
110 | static int hf_mka_peer_mn;
111 |
112 | static int hf_mka_latest_key_an;
113 | static int hf_mka_latest_key_tx;
114 | static int hf_mka_latest_key_rx;
115 | static int hf_mka_old_key_an;
116 | static int hf_mka_old_key_tx;
117 | static int hf_mka_old_key_rx;
118 | static int hf_mka_plain_tx;
119 | static int hf_mka_plain_rx;
120 | static int hf_mka_delay_protect;
121 | static int hf_mka_latest_key_server_mi;
122 | static int hf_mka_latest_key_number;
123 | static int hf_mka_latest_lowest_acceptable_pn;
124 | static int hf_mka_old_key_server_mi;
125 | static int hf_mka_old_key_number;
126 | static int hf_mka_old_lowest_acceptable_pn;
127 |
128 | static int hf_mka_distributed_an;
129 | static int hf_mka_confidentiality_offset;
130 | static int hf_mka_key_number;
131 | static int hf_mka_aes_key_wrap_sak;
132 | static int hf_mka_aes_key_wrap_unwrapped_sak;
133 | static int hf_mka_macsec_cipher_suite;
134 | static int hf_mka_aes_key_wrap_cak;
135 |
136 | static int hf_mka_kmd;
137 |
138 | static int hf_mka_suspension_time;
139 | static int hf_mka_latest_lowest_accept_pn_msb;
140 | static int hf_mka_old_lowest_accept_pn_msb;
141 |
142 | static int hf_mka_icv;
143 | static int hf_mka_icv_status;
144 |
145 | static int hf_mka_tlv_entry;
146 | static int hf_mka_tlv_type;
147 | static int hf_mka_tlv_info_string_length;
148 | static int hf_mka_tlv_data;
149 | static int hf_mka_tlv_cipher_suite_impl_cap;
150 |
151 | static expert_field ei_mka_icv_bad;
152 | static expert_field ei_mka_undecoded;
153 | static expert_field ei_unexpected_data;
154 | static expert_field ei_mka_unimplemented;
155 |
156 | static int ett_mka;
157 | static int ett_mka_sci;
158 | static int ett_mka_basic_param_set;
159 | static int ett_mka_live_peer_list_set;
160 | static int ett_mka_potential_peer_list_set;
161 | static int ett_mka_sak_use_set;
162 | static int ett_mka_distributed_sak_set;
163 | static int ett_mka_distributed_cak_set;
164 | static int ett_mka_kmd_set;
165 | static int ett_mka_announcement_set;
166 | static int ett_mka_xpn_set;
167 | static int ett_mka_unknown_set;
168 | static int ett_mka_icv_set;
169 | static int ett_mka_tlv;
170 | static int ett_mka_cipher_suite_entry;
171 |
172 | static 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 |
185 | static 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 |
193 | static const value_string algo_agility_vals[] = {
194 | { 0x0080C201, "IEEE Std 802.1X-2020" },
195 | { 0, NULL((void*)0) }
196 | };
197 |
198 | static 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. */
209 | static 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 |
219 | static 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 |
231 | static wmem_map_t *mka_mi_sci_map;
232 | static wmem_multimap_t *mka_ckn_sak_map;
233 | static wmem_map_t *mka_ki_pn_map;
234 |
235 | static const char *mka_ckn_info_uat_defaults_[] = { NULL((void*)0), "", "" };
236 |
237 | static mka_ckn_info_t *mka_ckn_uat_data = NULL((void*)0);
238 | static unsigned num_mka_ckn_uat_data = 0;
239 | static GHashTable *ht_mka_ckn = NULL((void*)0);
240 |
241 | UAT_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; }
242 | UAT_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; }
243 | UAT_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. */
246 | static unsigned
247 | mka_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 |
339 | static void
340 | mka_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 |
347 | static void
348 | mka_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 |
355 | static unsigned
356 | ckn_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 |
370 | static int
371 | ckn_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 |
380 | static void *
381 | ckn_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 |
394 | static bool_Bool
395 | ckn_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 |
419 | static void
420 | ckn_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 |
428 | static void
429 | ckn_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 |
436 | static void
437 | ckn_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 */
459 | static mka_ckn_info_t *
460 | ckn_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. */
472 | const mka_ckn_info_t *
473 | get_mka_ckn_table(void) {
474 | return (const mka_ckn_info_t *)mka_ckn_uat_data;
475 | }
476 |
477 | /* Get the size of the table. */
478 | unsigned
479 | get_mka_ckn_table_count(void) {
480 | return num_mka_ckn_uat_data;
481 | }
482 |
483 | static unsigned
484 | mka_sci_hash(const void *key) {
485 | return wmem_strong_hash(key, MACSEC_SCI_LEN8U);
486 | }
487 |
488 | static gboolean
489 | mka_sci_equal(const void *k1, const void *k2) {
490 | return memcmp(k1, k2, MACSEC_SCI_LEN8U) == 0;
491 | }
492 |
493 | static unsigned
494 | mka_mi_hash(const void *key) {
495 | return wmem_strong_hash(key, MKA_MI_LEN12U);
496 | }
497 |
498 | static gboolean
499 | mka_mi_equal(const void *k1, const void *k2) {
500 | return memcmp(k1, k2, MKA_MI_LEN12U) == 0;
501 | }
502 |
503 | typedef struct _mka_ki_pn_t {
504 | uint8_t ki[MKA_KI_LEN16U];
505 | uint64_t pn;
506 | } mka_ki_pn_t;
507 |
508 | typedef 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 |
513 | static unsigned
514 | mka_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 |
519 | static gboolean
520 | mka_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. */
533 | uint64_t
534 | mka_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 |
549 | static void
550 | update_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 |
586 | typedef struct _mka_sak_key_t {
587 | const mka_ckn_info_t *ckn_info;
588 | uint8_t an;
589 | } mka_sak_key_t;
590 |
591 | static unsigned
592 | mka_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 |
598 | static gboolean
599 | mka_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. */
609 | mka_sak_info_key_t *
610 | mka_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. */
617 | static mka_sak_info_key_t *
618 | get_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 |
624 | static mka_sak_info_key_t *
625 | get_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 |
639 | static mka_ckn_info_t *
640 | mka_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 |
657 | static proto_tree *
658 | dissect_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 |
727 | static int
728 | sort_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 |
737 | static proto_tree *
738 | dissect_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 |
908 | static proto_tree *
909 | dissect_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 |
939 | static proto_tree *
940 | dissect_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;
| Value stored to 'offset' is never read
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 |
1027 | static void
1028 | mka_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 |
1038 | static proto_tree *
1039 | dissect_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;
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 |
1200 | out:
1201 | return distributed_sak_tree;
1202 | }
1203 |
1204 | static proto_tree *
1205 | dissect_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 |
1229 | static proto_tree *
1230 | dissect_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 |
1249 | static proto_tree *
1250 | dissect_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 |
1322 | static proto_tree *
1323 | dissect_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 |
1374 | static proto_tree *
1375 | dissect_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 |
1390 | static proto_tree *
1391 | dissect_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 |
1409 | static uint8_t*
1410 | calculate_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 |
1496 | failed:
1497 | gcry_mac_close(hd);
1498 | return NULL((void*)0);
1499 | }
1500 |
1501 | /*
1502 | * Ref 802.1X-2020, Figure 11-7
1503 | */
1504 | static uint8_t
1505 | start_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 |
1510 | static int
1511 | finalize_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 |
1529 | static int
1530 | dissect_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 |
1621 | void
1622 | proto_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 |
1778 | void
1779 | proto_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 | */