/src/wireshark/epan/dissectors/packet-zbee-security.c
Line | Count | Source |
1 | | /* packet-zbee-security.c |
2 | | * Dissector helper routines for encrypted ZigBee frames. |
3 | | * By Owen Kirby <osk@exegin.com>; portions by Fred Fierling <fff@exegin.com> |
4 | | * Copyright 2009 Exegin Technologies Limited |
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 Files */ |
14 | | #include "config.h" |
15 | | |
16 | 0 | #define WS_LOG_DOMAIN "zcl" |
17 | | |
18 | | #include <wireshark.h> |
19 | | #include <epan/packet.h> |
20 | | #include <epan/exceptions.h> |
21 | | |
22 | | #include <epan/prefs.h> |
23 | | #include <epan/expert.h> |
24 | | #include <epan/uat.h> |
25 | | #include <epan/proto_data.h> |
26 | | |
27 | | /* We require libgcrypt in order to decrypt ZigBee packets. Without it the best |
28 | | * we can do is parse the security header and give up. |
29 | | */ |
30 | | #include <wsutil/wsgcrypt.h> |
31 | | #include <wsutil/pint.h> |
32 | | |
33 | | #include "packet-ieee802154.h" |
34 | | #include "packet-zbee.h" |
35 | | #include "packet-zbee-nwk.h" |
36 | | #include "packet-zbee-aps.h" /* for ZBEE_APS_CMD_KEY_LENGTH */ |
37 | | #include "packet-zbee-security.h" |
38 | | |
39 | | void proto_reg_handoff_zbee_security(void); |
40 | | |
41 | | /* Helper Functions */ |
42 | | static void zbee_sec_key_hash(uint8_t *, uint8_t, uint8_t *); |
43 | | static void zbee_sec_make_nonce (zbee_security_packet *, uint8_t *); |
44 | | static bool zbee_sec_decrypt_payload(zbee_security_packet *, const uint8_t *, const unsigned, uint8_t *, |
45 | | unsigned, unsigned, uint8_t *); |
46 | | static bool zbee_security_parse_key(const char *, uint8_t *, bool); |
47 | | |
48 | | /* Field pointers. */ |
49 | | static int hf_zbee_sec_field; |
50 | | static int hf_zbee_sec_level; |
51 | | static int hf_zbee_sec_key_id; |
52 | | static int hf_zbee_sec_nonce; |
53 | | static int hf_zbee_sec_verified_fc; |
54 | | static int hf_zbee_sec_counter; |
55 | | static int hf_zbee_sec_src64; |
56 | | static int hf_zbee_sec_key_seqno; |
57 | | static int hf_zbee_sec_mic; |
58 | | static int hf_zbee_sec_key; |
59 | | static int hf_zbee_sec_key_origin; |
60 | | static int hf_zbee_sec_decryption_key; |
61 | | |
62 | | /* Subtree pointers. */ |
63 | | static int ett_zbee_sec; |
64 | | static int ett_zbee_sec_control; |
65 | | |
66 | | static expert_field ei_zbee_sec_encrypted_payload; |
67 | | static expert_field ei_zbee_sec_encrypted_payload_sliced; |
68 | | static expert_field ei_zbee_sec_extended_source_unknown; |
69 | | |
70 | | /* Cached protocol identifiers */ |
71 | | static int proto_zbee_nwk; |
72 | | static int proto_ieee802154; |
73 | | |
74 | | static const value_string zbee_sec_key_names[] = { |
75 | | { ZBEE_SEC_KEY_LINK, "Link Key" }, |
76 | | { ZBEE_SEC_KEY_NWK, "Network Key" }, |
77 | | { ZBEE_SEC_KEY_TRANSPORT, "Key-Transport Key" }, |
78 | | { ZBEE_SEC_KEY_LOAD, "Key-Load Key" }, |
79 | | { 0, NULL } |
80 | | }; |
81 | | |
82 | | #if 0 |
83 | | /* These aren't really used anymore, as ZigBee no longer includes them in the |
84 | | * security control field. If we were to display them all we would ever see is |
85 | | * security level 0. |
86 | | */ |
87 | | static const value_string zbee_sec_level_names[] = { |
88 | | { ZBEE_SEC_NONE, "None" }, |
89 | | { ZBEE_SEC_MIC32, "No Encryption, 32-bit MIC" }, |
90 | | { ZBEE_SEC_MIC64, "No Encryption, 64-bit MIC" }, |
91 | | { ZBEE_SEC_MIC128, "No Encryption, 128-bit MIC" }, |
92 | | { ZBEE_SEC_ENC, "Encryption, No MIC" }, |
93 | | { ZBEE_SEC_ENC_MIC32, "Encryption, 32-bit MIC" }, |
94 | | { ZBEE_SEC_ENC_MIC64, "Encryption, 64-bit MIC" }, |
95 | | { ZBEE_SEC_ENC_MIC128, "Encryption, 128-bit MIC" }, |
96 | | { 0, NULL } |
97 | | }; |
98 | | #endif |
99 | | |
100 | | /* The ZigBee security level, in enum_val_t for the security preferences. */ |
101 | | static const enum_val_t zbee_sec_level_enums[] = { |
102 | | { "None", "No Security", ZBEE_SEC_NONE }, |
103 | | { "MIC32", "No Encryption, 32-bit Integrity Protection", ZBEE_SEC_MIC32 }, |
104 | | { "MIC64", "No Encryption, 64-bit Integrity Protection", ZBEE_SEC_MIC64 }, |
105 | | { "MIC128", "No Encryption, 128-bit Integrity Protection", ZBEE_SEC_MIC128 }, |
106 | | { "ENC", "AES-128 Encryption, No Integrity Protection", ZBEE_SEC_ENC }, |
107 | | { "ENC-MIC32", "AES-128 Encryption, 32-bit Integrity Protection", ZBEE_SEC_ENC_MIC32 }, |
108 | | { "ENC-MIC64", "AES-128 Encryption, 64-bit Integrity Protection", ZBEE_SEC_ENC_MIC64 }, |
109 | | { "ENC-MIC128", "AES-128 Encryption, 128-bit Integrity Protection", ZBEE_SEC_ENC_MIC128 }, |
110 | | { NULL, NULL, 0 } |
111 | | }; |
112 | | |
113 | | static int gPREF_zbee_sec_level = ZBEE_SEC_ENC_MIC32; |
114 | | static uat_t *zbee_sec_key_table_uat; |
115 | | |
116 | | static const value_string byte_order_vals[] = { |
117 | | { 0, "Normal"}, |
118 | | { 1, "Reverse"}, |
119 | | { 0, NULL } |
120 | | }; |
121 | | |
122 | | /* UAT Key Entry */ |
123 | | typedef struct _uat_key_record_t { |
124 | | char *string; |
125 | | uint8_t byte_order; |
126 | | char *label; |
127 | | } uat_key_record_t; |
128 | | |
129 | | UAT_CSTRING_CB_DEF(uat_key_records, string, uat_key_record_t) |
130 | | UAT_VS_DEF(uat_key_records, byte_order, uat_key_record_t, uint8_t, 0, "Normal") |
131 | | UAT_CSTRING_CB_DEF(uat_key_records, label, uat_key_record_t) |
132 | | |
133 | | static GSList *zbee_pc_keyring; |
134 | | static uat_key_record_t *uat_key_records; |
135 | | static unsigned num_uat_key_records; |
136 | | |
137 | 0 | static void* uat_key_record_copy_cb(void* n, const void* o, size_t siz _U_) { |
138 | 0 | uat_key_record_t* new_key = (uat_key_record_t *)n; |
139 | 0 | const uat_key_record_t* old_key = (const uat_key_record_t *)o; |
140 | |
|
141 | 0 | new_key->string = g_strdup(old_key->string); |
142 | 0 | new_key->label = g_strdup(old_key->label); |
143 | 0 | new_key->byte_order = old_key->byte_order; |
144 | |
|
145 | 0 | return new_key; |
146 | 0 | } |
147 | | |
148 | 0 | static bool uat_key_record_update_cb(void* r, char** err) { |
149 | 0 | uat_key_record_t* rec = (uat_key_record_t *)r; |
150 | 0 | uint8_t key[ZBEE_SEC_CONST_KEYSIZE]; |
151 | |
|
152 | 0 | if (rec->string == NULL) { |
153 | 0 | *err = g_strdup("Key can't be blank"); |
154 | 0 | return false; |
155 | 0 | } else { |
156 | 0 | g_strstrip(rec->string); |
157 | |
|
158 | 0 | if (rec->string[0] != 0) { |
159 | 0 | *err = NULL; |
160 | 0 | if ( !zbee_security_parse_key(rec->string, key, rec->byte_order) ) { |
161 | 0 | *err = ws_strdup_printf("Expecting %d hexadecimal bytes or\n" |
162 | 0 | "a %d character double-quoted string", ZBEE_SEC_CONST_KEYSIZE, ZBEE_SEC_CONST_KEYSIZE); |
163 | 0 | return false; |
164 | 0 | } |
165 | 0 | } else { |
166 | 0 | *err = g_strdup("Key can't be blank"); |
167 | 0 | return false; |
168 | 0 | } |
169 | 0 | } |
170 | 0 | return true; |
171 | 0 | } |
172 | | |
173 | 0 | static void uat_key_record_free_cb(void*r) { |
174 | 0 | uat_key_record_t* key = (uat_key_record_t *)r; |
175 | |
|
176 | 0 | g_free(key->string); |
177 | 0 | g_free(key->label); |
178 | 0 | } |
179 | | |
180 | | static void zbee_free_key_record(void *ptr) |
181 | 0 | { |
182 | 0 | key_record_t *k = (key_record_t *)ptr; |
183 | |
|
184 | 0 | g_free(k->label); |
185 | 0 | g_free(k); |
186 | 0 | } |
187 | | |
188 | 14 | static void uat_key_record_post_update(void) { |
189 | 14 | unsigned i; |
190 | 14 | key_record_t key_record; |
191 | 14 | uint8_t key[ZBEE_SEC_CONST_KEYSIZE]; |
192 | | |
193 | | /* empty the key ring */ |
194 | 14 | if (zbee_pc_keyring) { |
195 | 0 | g_slist_free_full(zbee_pc_keyring, zbee_free_key_record); |
196 | 0 | zbee_pc_keyring = NULL; |
197 | 0 | } |
198 | | |
199 | | /* Load the pre-configured slist from the UAT. */ |
200 | 14 | for (i=0; (uat_key_records) && (i<num_uat_key_records) ; i++) { |
201 | 0 | if (zbee_security_parse_key(uat_key_records[i].string, key, uat_key_records[i].byte_order)) { |
202 | 0 | key_record.frame_num = ZBEE_SEC_PC_KEY; /* means it's a user PC key */ |
203 | 0 | key_record.label = g_strdup(uat_key_records[i].label); |
204 | 0 | memcpy(key_record.key, key, ZBEE_SEC_CONST_KEYSIZE); |
205 | 0 | zbee_pc_keyring = g_slist_prepend(zbee_pc_keyring, g_memdup2(&key_record, sizeof(key_record_t))); |
206 | 0 | } |
207 | 0 | } |
208 | 14 | } |
209 | | |
210 | | /* |
211 | | * Enable this macro to use libgcrypt's CBC_MAC mode for the authentication |
212 | | * phase. Unfortunately, this is broken, and I don't know why. However, using |
213 | | * the messier EBC mode (to emulate CCM*) still works fine. |
214 | | */ |
215 | | #if 0 |
216 | | #define ZBEE_SEC_USE_GCRYPT_CBC_MAC |
217 | | #endif |
218 | | /*FUNCTION:------------------------------------------------------ |
219 | | * NAME |
220 | | * zbee_security_register |
221 | | * DESCRIPTION |
222 | | * Called by proto_register_zbee_nwk() to initialize the security |
223 | | * dissectors. |
224 | | * PARAMETERS |
225 | | * module_t zbee_prefs - Prefs module to load preferences under. |
226 | | * RETURNS |
227 | | * none |
228 | | *--------------------------------------------------------------- |
229 | | */ |
230 | | void zbee_security_register(module_t *zbee_prefs, int proto) |
231 | 14 | { |
232 | 14 | static hf_register_info hf[] = { |
233 | 14 | { &hf_zbee_sec_field, |
234 | 14 | { "Security Control Field", "zbee.sec.field", FT_UINT8, BASE_HEX, NULL, |
235 | 14 | 0x0, NULL, HFILL }}, |
236 | | |
237 | 14 | { &hf_zbee_sec_level, |
238 | 14 | { "Security Level", "zbee.sec.sec_level", FT_UINT8, BASE_HEX, NULL, |
239 | 14 | ZBEE_SEC_CONTROL_LEVEL, NULL, HFILL }}, |
240 | | |
241 | 14 | { &hf_zbee_sec_key_id, |
242 | 14 | { "Key Id", "zbee.sec.key_id", FT_UINT8, BASE_HEX, VALS(zbee_sec_key_names), |
243 | 14 | ZBEE_SEC_CONTROL_KEY, NULL, HFILL }}, |
244 | | |
245 | 14 | { &hf_zbee_sec_nonce, |
246 | 14 | { "Extended Nonce", "zbee.sec.ext_nonce", FT_BOOLEAN, 8, NULL, ZBEE_SEC_CONTROL_NONCE, |
247 | 14 | NULL, HFILL }}, |
248 | | |
249 | 14 | { &hf_zbee_sec_verified_fc, |
250 | 14 | { "Require Verified Frame Counter", "zbee.sec.verified_fc", FT_UINT8, BASE_HEX, NULL, |
251 | 14 | ZBEE_SEC_CONTROL_VERIFIED_FC, NULL, HFILL }}, |
252 | | |
253 | 14 | { &hf_zbee_sec_counter, |
254 | 14 | { "Frame Counter", "zbee.sec.counter", FT_UINT32, BASE_DEC, NULL, 0x0, |
255 | 14 | NULL, HFILL }}, |
256 | | |
257 | 14 | { &hf_zbee_sec_src64, |
258 | 14 | { "Extended Source", "zbee.sec.src64", FT_EUI64, BASE_NONE, NULL, 0x0, |
259 | 14 | NULL, HFILL }}, |
260 | | |
261 | 14 | { &hf_zbee_sec_key_seqno, |
262 | 14 | { "Key Sequence Number", "zbee.sec.key_seqno", FT_UINT8, BASE_DEC, NULL, 0x0, |
263 | 14 | NULL, HFILL }}, |
264 | | |
265 | 14 | { &hf_zbee_sec_mic, |
266 | 14 | { "Message Integrity Code", "zbee.sec.mic", FT_BYTES, BASE_NONE, NULL, 0x0, |
267 | 14 | NULL, HFILL }}, |
268 | | |
269 | 14 | { &hf_zbee_sec_key, |
270 | 14 | { "Key", "zbee.sec.key", FT_BYTES, BASE_NONE, NULL, 0x0, |
271 | 14 | NULL, HFILL }}, |
272 | | |
273 | 14 | { &hf_zbee_sec_key_origin, |
274 | 14 | { "Key Origin", "zbee.sec.key.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
275 | 14 | NULL, HFILL }}, |
276 | | |
277 | 14 | { &hf_zbee_sec_decryption_key, |
278 | 14 | { "Key Label", "zbee.sec.decryption_key", FT_STRING, BASE_NONE, NULL, 0x0, |
279 | 14 | NULL, HFILL }} |
280 | 14 | }; |
281 | | |
282 | 14 | static int *ett[] = { |
283 | 14 | &ett_zbee_sec, |
284 | 14 | &ett_zbee_sec_control |
285 | 14 | }; |
286 | | |
287 | 14 | static ei_register_info ei[] = { |
288 | 14 | { &ei_zbee_sec_encrypted_payload, { "zbee_sec.encrypted_payload", PI_UNDECODED, PI_WARN, "Encrypted Payload", EXPFILL }}, |
289 | 14 | { &ei_zbee_sec_encrypted_payload_sliced, { "zbee_sec.encrypted_payload_sliced", PI_UNDECODED, PI_WARN, "Encrypted payload, cut short when capturing - can't decrypt", EXPFILL }}, |
290 | 14 | { &ei_zbee_sec_extended_source_unknown, { "zbee_sec.extended_source_unknown", PI_PROTOCOL, PI_NOTE, "Extended Source: Unknown", EXPFILL }}, |
291 | 14 | }; |
292 | | |
293 | 14 | expert_module_t* expert_zbee_sec; |
294 | | |
295 | 14 | static uat_field_t key_uat_fields[] = { |
296 | 14 | UAT_FLD_CSTRING(uat_key_records, string, "Key", |
297 | 14 | "A 16-byte key in hexadecimal with optional dash-,\n" |
298 | 14 | "colon-, or space-separator characters, or a\n" |
299 | 14 | "a 16-character string in double-quotes."), |
300 | 14 | UAT_FLD_VS(uat_key_records, byte_order, "Byte Order", byte_order_vals, |
301 | 14 | "Byte order of key."), |
302 | 14 | UAT_FLD_CSTRING(uat_key_records, label, "Label", "User label for key."), |
303 | 14 | UAT_END_FIELDS |
304 | 14 | }; |
305 | | |
306 | | /* If no prefs module was supplied, register our own. */ |
307 | 14 | if (zbee_prefs == NULL) { |
308 | 14 | zbee_prefs = prefs_register_protocol(proto, NULL); |
309 | 14 | } |
310 | | |
311 | | /* Register preferences */ |
312 | 14 | prefs_register_enum_preference(zbee_prefs, "seclevel", "Security Level", |
313 | 14 | "Specifies the security level to use in the\n" |
314 | 14 | "decryption process. This value is ignored\n" |
315 | 14 | "for ZigBee 2004 and unsecured networks.", |
316 | 14 | &gPREF_zbee_sec_level, zbee_sec_level_enums, false); |
317 | | |
318 | 14 | zbee_sec_key_table_uat = uat_new("Pre-configured Keys", |
319 | 14 | sizeof(uat_key_record_t), |
320 | 14 | "zigbee_pc_keys", |
321 | 14 | true, |
322 | 14 | &uat_key_records, |
323 | 14 | &num_uat_key_records, |
324 | 14 | UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */ |
325 | 14 | NULL, /* TODO: ptr to help manual? */ |
326 | 14 | uat_key_record_copy_cb, |
327 | 14 | uat_key_record_update_cb, |
328 | 14 | uat_key_record_free_cb, |
329 | 14 | uat_key_record_post_update, |
330 | 14 | NULL, |
331 | 14 | key_uat_fields ); |
332 | | |
333 | 14 | prefs_register_uat_preference(zbee_prefs, |
334 | 14 | "key_table", |
335 | 14 | "Pre-configured Keys", |
336 | 14 | "Pre-configured link or network keys.", |
337 | 14 | zbee_sec_key_table_uat); |
338 | | |
339 | 14 | proto_register_field_array(proto, hf, array_length(hf)); |
340 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
341 | 14 | expert_zbee_sec = expert_register_protocol(proto); |
342 | 14 | expert_register_field_array(expert_zbee_sec, ei, array_length(ei)); |
343 | | |
344 | 14 | } /* zbee_security_register */ |
345 | | |
346 | | void proto_reg_handoff_zbee_security(void) |
347 | 14 | { |
348 | 14 | proto_zbee_nwk = proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK); |
349 | 14 | proto_ieee802154 = proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN); |
350 | 14 | } |
351 | | |
352 | | |
353 | | /*FUNCTION:------------------------------------------------------ |
354 | | * NAME |
355 | | * zbee_security_parse_key |
356 | | * DESCRIPTION |
357 | | * Parses a key string from left to right into a buffer with |
358 | | * increasing (normal byte order) or decreasing (reverse byte |
359 | | * order) address. |
360 | | * PARAMETERS |
361 | | * const char *key_str - pointer to the string |
362 | | * uint8_t *key_buf - destination buffer in memory |
363 | | * bool big_end - fill key_buf with incrementing address |
364 | | * RETURNS |
365 | | * bool |
366 | | *--------------------------------------------------------------- |
367 | | */ |
368 | | static bool |
369 | | zbee_security_parse_key(const char *key_str, uint8_t *key_buf, bool byte_order) |
370 | 0 | { |
371 | 0 | int i, j; |
372 | 0 | char temp; |
373 | 0 | bool string_mode = false; |
374 | | |
375 | | /* Clear the key. */ |
376 | 0 | memset(key_buf, 0, ZBEE_SEC_CONST_KEYSIZE); |
377 | 0 | if (key_str == NULL) { |
378 | 0 | return false; |
379 | 0 | } |
380 | | |
381 | | /* |
382 | | * Attempt to parse the key string. The key string must |
383 | | * be at least 16 pairs of hexidecimal digits with the |
384 | | * following optional separators: ':', '-', " ", or 16 |
385 | | * alphanumeric characters after a double-quote. |
386 | | */ |
387 | 0 | if ( (temp = *key_str++) == '"') { |
388 | 0 | string_mode = true; |
389 | 0 | temp = *key_str++; |
390 | 0 | } |
391 | |
|
392 | 0 | j = byte_order?ZBEE_SEC_CONST_KEYSIZE-1:0; |
393 | 0 | for (i=ZBEE_SEC_CONST_KEYSIZE-1; i>=0; i--) { |
394 | 0 | if ( string_mode ) { |
395 | 0 | if ( g_ascii_isprint(temp) ) { |
396 | 0 | key_buf[j] = temp; |
397 | 0 | temp = *key_str++; |
398 | 0 | } else { |
399 | 0 | return false; |
400 | 0 | } |
401 | 0 | } |
402 | 0 | else { |
403 | | /* If this character is a separator, skip it. */ |
404 | 0 | if ( (temp == ':') || (temp == '-') || (temp == ' ') ) temp = *(key_str++); |
405 | | |
406 | | /* Process a nibble. */ |
407 | 0 | if ( g_ascii_isxdigit (temp) ) key_buf[j] = g_ascii_xdigit_value(temp)<<4; |
408 | 0 | else return false; |
409 | | |
410 | | /* Get the next nibble. */ |
411 | 0 | temp = *(key_str++); |
412 | | |
413 | | /* Process another nibble. */ |
414 | 0 | if ( g_ascii_isxdigit (temp) ) key_buf[j] |= g_ascii_xdigit_value(temp); |
415 | 0 | else return false; |
416 | | |
417 | | /* Get the next nibble. */ |
418 | 0 | temp = *(key_str++); |
419 | 0 | } |
420 | | |
421 | | /* Move key_buf pointer */ |
422 | 0 | if ( byte_order ) { |
423 | 0 | j--; |
424 | 0 | } else { |
425 | 0 | j++; |
426 | 0 | } |
427 | |
|
428 | 0 | } /* for */ |
429 | | |
430 | | /* If we get this far, then the key was good. */ |
431 | 0 | return true; |
432 | 0 | } /* zbee_security_parse_key */ |
433 | | |
434 | | /*FUNCTION:------------------------------------------------------ |
435 | | * NAME |
436 | | * dissect_zbee_secure |
437 | | * DESCRIPTION |
438 | | * Dissects and decrypts secured ZigBee frames. |
439 | | * |
440 | | * Will return a valid tvbuff only if security processing was |
441 | | * successful. If processing fails, then this function will |
442 | | * handle internally and return NULL. |
443 | | * PARAMETERS |
444 | | * tvbuff_t *tvb - pointer to buffer containing raw packet. |
445 | | * packet_info *pinfo - pointer to packet information fields |
446 | | * proto_tree *tree - pointer to data tree Wireshark uses to display packet. |
447 | | * unsigned offset - pointer to the start of the auxiliary security header. |
448 | | * uint64_t src64 - extended source address, or 0 if unknown. |
449 | | * RETURNS |
450 | | * tvbuff_t * |
451 | | *--------------------------------------------------------------- |
452 | | */ |
453 | | tvbuff_t * |
454 | | dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, unsigned offset) |
455 | 63 | { |
456 | 63 | proto_tree *sec_tree; |
457 | | |
458 | 63 | zbee_security_packet packet; |
459 | 63 | unsigned mic_len; |
460 | 63 | unsigned payload_len; |
461 | 63 | tvbuff_t *payload_tvb; |
462 | | |
463 | 63 | proto_item *ti; |
464 | 63 | proto_item *key_item; |
465 | 63 | uint8_t *enc_buffer; |
466 | 63 | uint8_t *dec_buffer; |
467 | 63 | bool decrypted; |
468 | 63 | GSList **nwk_keyring; |
469 | 63 | GSList *GSList_i; |
470 | 63 | key_record_t *key_rec = NULL; |
471 | 63 | zbee_nwk_hints_t *nwk_hints; |
472 | 63 | ieee802154_hints_t *ieee_hints; |
473 | 63 | ieee802154_map_rec *map_rec = NULL; |
474 | | |
475 | 63 | static int * const sec_flags[] = { |
476 | 63 | &hf_zbee_sec_level, |
477 | 63 | &hf_zbee_sec_key_id, |
478 | 63 | &hf_zbee_sec_nonce, |
479 | 63 | &hf_zbee_sec_verified_fc, |
480 | 63 | NULL |
481 | 63 | }; |
482 | | |
483 | | /* Init */ |
484 | 63 | memset(&packet, 0, sizeof(zbee_security_packet)); |
485 | | |
486 | | /* Get pointers to any useful frame data from lower layers */ |
487 | 63 | nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_zbee_nwk, 0); |
488 | 63 | ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0); |
489 | | |
490 | | /* Create a subtree for the security information. */ |
491 | 63 | sec_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_zbee_sec, NULL, "ZigBee Security Header"); |
492 | | |
493 | | /* Get and display the Security control field */ |
494 | 63 | packet.control = tvb_get_uint8(tvb, offset); |
495 | | |
496 | | /* Patch the security level. */ |
497 | 63 | packet.control &= ~ZBEE_SEC_CONTROL_LEVEL; |
498 | 63 | packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level); |
499 | | |
500 | | /* |
501 | | * Eww, I think I just threw up a little... ZigBee requires this field |
502 | | * to be patched before computing the MIC, but we don't have write-access |
503 | | * to the tvbuff. So we need to allocate a copy of the whole thing just |
504 | | * so we can fix these 3 bits. Memory allocated by tvb_memdup(pinfo->pool,...) |
505 | | * is automatically freed before the next packet is processed. |
506 | | */ |
507 | 63 | enc_buffer = (uint8_t *)tvb_memdup(pinfo->pool, tvb, 0, tvb_captured_length(tvb)); |
508 | | /* |
509 | | * Override the const qualifiers and patch the security level field, we |
510 | | * know it is safe to overide the const qualifiers because we just |
511 | | * allocated this memory via tvb_memdup(pinfo->pool,...). |
512 | | */ |
513 | 63 | enc_buffer[offset] = packet.control; |
514 | 63 | packet.level = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL); |
515 | 63 | packet.key_id = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY); |
516 | 63 | packet.nonce = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE); |
517 | | |
518 | 63 | proto_tree_add_bitmask(sec_tree, tvb, offset, hf_zbee_sec_field, ett_zbee_sec_control, sec_flags, ENC_NA); |
519 | 63 | offset += 1; |
520 | | |
521 | | /* Get and display the frame counter field. */ |
522 | 63 | packet.counter = tvb_get_letohl(tvb, offset); |
523 | 63 | proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, 4, packet.counter); |
524 | 63 | offset += 4; |
525 | | |
526 | 63 | if (packet.nonce) { |
527 | | /* Get and display the source address of the device that secured this payload. */ |
528 | 38 | packet.src64 = tvb_get_letoh64(tvb, offset); |
529 | 38 | proto_tree_add_item(sec_tree, hf_zbee_sec_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN); |
530 | 38 | #if 1 |
531 | 38 | if (!pinfo->fd->visited) { |
532 | 36 | switch ( packet.key_id ) { |
533 | 10 | case ZBEE_SEC_KEY_LINK: |
534 | 10 | if (nwk_hints && ieee_hints) { |
535 | | /* Map this long address with the nwk layer short address. */ |
536 | 10 | nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src, |
537 | 10 | ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num); |
538 | 10 | } |
539 | 10 | break; |
540 | | |
541 | 13 | case ZBEE_SEC_KEY_NWK: |
542 | 13 | if (ieee_hints) { |
543 | | /* Map this long address with the ieee short address. */ |
544 | 13 | ieee_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, ieee_hints->src16, |
545 | 13 | ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num); |
546 | 13 | if (nwk_hints && !nwk_hints->map_rec) { |
547 | | /* Map this long address with the nwk layer short address. */ |
548 | 7 | nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src, |
549 | 7 | ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num); |
550 | 7 | } |
551 | 13 | } |
552 | 13 | break; |
553 | | |
554 | | /* We ignore the extended source addresses used to encrypt payloads with these |
555 | | * types of keys, because they can emerge from APS tunnels created by nodes whose |
556 | | * short address is not recorded in the packet. */ |
557 | 4 | case ZBEE_SEC_KEY_TRANSPORT: |
558 | 13 | case ZBEE_SEC_KEY_LOAD: |
559 | 13 | break; |
560 | 36 | } |
561 | 36 | } |
562 | 38 | #endif |
563 | 38 | offset += 8; |
564 | 38 | } |
565 | 25 | else { |
566 | | /* Look for a source address in hints */ |
567 | 25 | switch ( packet.key_id ) { |
568 | 5 | case ZBEE_SEC_KEY_NWK: |
569 | | /* use the ieee extended source address for NWK decryption */ |
570 | 5 | if ( ieee_hints && (map_rec = ieee_hints->map_rec) ) |
571 | 2 | packet.src64 = map_rec->addr64; |
572 | 3 | else |
573 | 3 | proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0); |
574 | 5 | break; |
575 | | |
576 | 19 | default: |
577 | | /* use the nwk extended source address for APS decryption */ |
578 | 19 | if ( nwk_hints && (map_rec = nwk_hints->map_rec) ) |
579 | 13 | { |
580 | 13 | switch (nwk_hints->relay_type) |
581 | 13 | { |
582 | 1 | case ZBEE_APS_RELAY_DOWNSTREAM: |
583 | 1 | { |
584 | 1 | ieee802154_short_addr addr16; |
585 | | /* In case of downstream Relay must use long address |
586 | | * of ZC. Seek for it in the address translation |
587 | | * table. */ |
588 | 1 | addr16.addr = 0; |
589 | | /* Zigbee Direct packets relayed over BLE interface will not have IEEE/MAC |
590 | | * header. As a result 'ieee_hints' can be NULL. */ |
591 | 1 | if (ieee_hints) |
592 | 1 | { |
593 | 1 | addr16.pan = ieee_hints->src_pan; |
594 | 1 | } |
595 | 1 | map_rec = (ieee802154_map_rec *) g_hash_table_lookup(zbee_nwk_map.short_table, &addr16); |
596 | 1 | if (map_rec) |
597 | 0 | { |
598 | 0 | packet.src64 = map_rec->addr64; |
599 | 0 | } |
600 | 1 | } |
601 | 1 | break; |
602 | 0 | case ZBEE_APS_RELAY_UPSTREAM: |
603 | | /* In case of downstream Relay must use long address of Joiner from the Relay message */ |
604 | 0 | packet.src64 = nwk_hints->joiner_addr64; |
605 | 0 | break; |
606 | 12 | default: |
607 | 12 | packet.src64 = map_rec->addr64; |
608 | 12 | break; |
609 | 13 | } |
610 | 13 | } |
611 | 6 | else |
612 | 6 | proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0); |
613 | 19 | break; |
614 | 25 | } |
615 | 25 | } |
616 | | |
617 | 62 | if (packet.key_id == ZBEE_SEC_KEY_NWK) { |
618 | | /* Get and display the key sequence number. */ |
619 | 18 | packet.key_seqno = tvb_get_uint8(tvb, offset); |
620 | 18 | proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, 1, packet.key_seqno); |
621 | 18 | offset += 1; |
622 | 18 | } |
623 | | |
624 | | /* Determine the length of the MIC. */ |
625 | 62 | switch (packet.level) { |
626 | 0 | case ZBEE_SEC_ENC: |
627 | 0 | case ZBEE_SEC_NONE: |
628 | 0 | default: |
629 | 0 | mic_len=0; |
630 | 0 | break; |
631 | | |
632 | 59 | case ZBEE_SEC_ENC_MIC32: |
633 | 59 | case ZBEE_SEC_MIC32: |
634 | 59 | mic_len=4; |
635 | 59 | break; |
636 | | |
637 | 0 | case ZBEE_SEC_ENC_MIC64: |
638 | 0 | case ZBEE_SEC_MIC64: |
639 | 0 | mic_len=8; |
640 | 0 | break; |
641 | | |
642 | 0 | case ZBEE_SEC_ENC_MIC128: |
643 | 0 | case ZBEE_SEC_MIC128: |
644 | 0 | mic_len=16; |
645 | 0 | break; |
646 | 62 | } /* switch */ |
647 | | |
648 | | /* Empty payload has to be security checked as well, |
649 | | * since it contains MIC authentication tag */ |
650 | 59 | payload_len = tvb_reported_length_remaining(tvb, offset+mic_len); |
651 | | |
652 | | /********************************************** |
653 | | * Perform Security Operations on the Frame * |
654 | | ********************************************** |
655 | | */ |
656 | 59 | if ((packet.level == ZBEE_SEC_NONE) || |
657 | 59 | (packet.level == ZBEE_SEC_MIC32) || |
658 | 59 | (packet.level == ZBEE_SEC_MIC64) || |
659 | 59 | (packet.level == ZBEE_SEC_MIC128)) { |
660 | | |
661 | | /* Payload is only integrity protected. Just return the sub-tvbuff. */ |
662 | 0 | return tvb_new_subset_length(tvb, offset, payload_len); |
663 | 0 | } |
664 | | |
665 | | /* Have we captured all the payload? */ |
666 | 59 | if (tvb_captured_length_remaining(tvb, offset+mic_len) < payload_len |
667 | 42 | || !tvb_bytes_exist(tvb, offset+payload_len, mic_len) /* there are at least enough bytes for MIC */ ) { |
668 | | /* |
669 | | * No - don't try to decrypt it. |
670 | | * |
671 | | * XXX - it looks as if the decryption code is assuming we have the |
672 | | * MIC, which won't be the case if the packet was cut short. Is |
673 | | * that in fact that case, or can we still make this work with a |
674 | | * partially-captured packet? |
675 | | */ |
676 | | /* Add expert info. */ |
677 | 24 | expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload_sliced); |
678 | | /* Create a buffer for the undecrypted payload. */ |
679 | 24 | payload_tvb = tvb_new_subset_length(tvb, offset, payload_len); |
680 | | /* Dump the payload to the data dissector. */ |
681 | 24 | call_data_dissector(payload_tvb, pinfo, tree); |
682 | | /* Couldn't decrypt, so return NULL. */ |
683 | 24 | return NULL; |
684 | 24 | } |
685 | | |
686 | | /* Get and display the MIC. */ |
687 | 35 | if (mic_len) { |
688 | | /* Display the MIC. */ |
689 | 35 | proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (int)(tvb_reported_length(tvb)-mic_len), |
690 | 35 | mic_len, ENC_NA); |
691 | 35 | } |
692 | | |
693 | | /* Allocate memory to decrypt the payload into. |
694 | | * If there is no payload, dec_buffer will be NULL */ |
695 | 35 | dec_buffer = (uint8_t *)wmem_alloc(pinfo->pool, payload_len); |
696 | | |
697 | 35 | decrypted = false; |
698 | 35 | if ( packet.src64 ) { |
699 | 32 | if (pinfo->fd->visited) { |
700 | 0 | if ( nwk_hints ) { |
701 | | /* Use previously found key */ |
702 | 0 | switch ( packet.key_id ) { |
703 | 0 | case ZBEE_SEC_KEY_NWK: |
704 | 0 | if ( (key_rec = nwk_hints->nwk) ) { |
705 | 0 | decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, |
706 | 0 | payload_len, mic_len, nwk_hints->nwk->key); |
707 | 0 | } |
708 | 0 | break; |
709 | | |
710 | 0 | default: |
711 | 0 | if ( (key_rec = nwk_hints->link) ) { |
712 | 0 | decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, |
713 | 0 | payload_len, mic_len, nwk_hints->link->key); |
714 | 0 | } |
715 | 0 | break; |
716 | 0 | } |
717 | 0 | } |
718 | 0 | } /* ( !pinfo->fd->visited ) */ |
719 | 32 | else { |
720 | | /* We only search for sniffed keys in the first pass, |
721 | | * to save time, and because decrypting with keys |
722 | | * transported in future packets is cheating */ |
723 | | |
724 | | /* Lookup NWK and link key in hash for this pan. */ |
725 | | /* This overkill approach is a placeholder for a hash that looks up |
726 | | * a key ring for a link key associated with a pair of devices. |
727 | | */ |
728 | 32 | if ( nwk_hints ) { |
729 | 32 | nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan); |
730 | | |
731 | 32 | if ( nwk_keyring ) { |
732 | 13 | GSList_i = *nwk_keyring; |
733 | 40 | while ( GSList_i && !decrypted ) { |
734 | 27 | decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, |
735 | 27 | payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key); |
736 | | |
737 | 27 | if (decrypted) { |
738 | | /* save pointer to the successful key record */ |
739 | 0 | switch (packet.key_id) { |
740 | 0 | case ZBEE_SEC_KEY_NWK: |
741 | 0 | key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data); |
742 | 0 | break; |
743 | | |
744 | 0 | default: |
745 | 0 | key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data); |
746 | 0 | break; |
747 | 0 | } |
748 | 27 | } else { |
749 | 27 | GSList_i = g_slist_next(GSList_i); |
750 | 27 | } |
751 | 27 | } |
752 | 13 | } |
753 | | |
754 | | /* Loop through user's password table for preconfigured keys, our last resort */ |
755 | 32 | GSList_i = zbee_pc_keyring; |
756 | 32 | while ( GSList_i && !decrypted ) { |
757 | 0 | decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, |
758 | 0 | payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key); |
759 | |
|
760 | 0 | if (decrypted) { |
761 | | /* save pointer to the successful key record */ |
762 | 0 | switch (packet.key_id) { |
763 | 0 | case ZBEE_SEC_KEY_NWK: |
764 | 0 | key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data); |
765 | 0 | break; |
766 | | |
767 | 0 | default: |
768 | 0 | key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data); |
769 | 0 | break; |
770 | 0 | } |
771 | 0 | } else { |
772 | 0 | GSList_i = g_slist_next(GSList_i); |
773 | 0 | } |
774 | 0 | } |
775 | 32 | } |
776 | 32 | } /* ( ! pinfo->fd->visited ) */ |
777 | 32 | } /* ( packet.src64 ) */ |
778 | | |
779 | 35 | if ( decrypted ) { |
780 | 0 | if ( tree && key_rec ) { |
781 | | /* Key is not present in decrypted payload, so its length may not match bytes length */ |
782 | 0 | key_item = proto_tree_add_bytes_with_length(sec_tree, hf_zbee_sec_key, tvb, 0, 0, key_rec->key, ZBEE_SEC_CONST_KEYSIZE); |
783 | 0 | proto_item_set_generated(key_item); |
784 | |
|
785 | 0 | if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) { |
786 | 0 | ti = proto_tree_add_string(sec_tree, hf_zbee_sec_decryption_key, tvb, 0, 0, key_rec->label); |
787 | 0 | } else { |
788 | 0 | ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0, |
789 | 0 | key_rec->frame_num); |
790 | 0 | } |
791 | 0 | proto_item_set_generated(ti); |
792 | 0 | } |
793 | | |
794 | | /* Found a key that worked, setup the new tvbuff_t and return */ |
795 | 0 | if(dec_buffer != NULL) { |
796 | 0 | payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len); |
797 | 0 | add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload"); |
798 | 0 | } |
799 | 0 | else { |
800 | | /* Only MIC authentication tag was checked */ |
801 | 0 | payload_tvb = NULL; |
802 | 0 | } |
803 | | |
804 | | /* Done! */ |
805 | 0 | return payload_tvb; |
806 | 0 | } |
807 | | |
808 | | /* Add expert info. */ |
809 | 35 | expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload); |
810 | | /* Create a buffer for the undecrypted payload. */ |
811 | 35 | payload_tvb = tvb_new_subset_length(tvb, offset, payload_len); |
812 | | /* Dump the payload to the data dissector. */ |
813 | 35 | call_data_dissector(payload_tvb, pinfo, tree); |
814 | | /* Couldn't decrypt, so return NULL. */ |
815 | 35 | return NULL; |
816 | 35 | } /* dissect_zbee_secure */ |
817 | | |
818 | | /*FUNCTION:------------------------------------------------------ |
819 | | * NAME |
820 | | * zbee_sec_decrypt_payload |
821 | | * DESCRIPTION |
822 | | * Creates a nonce and decrypts a secured payload. |
823 | | * PARAMETERS |
824 | | * char *nonce - Nonce Buffer. |
825 | | * zbee_security_packet *packet - Security information. |
826 | | * RETURNS |
827 | | * void |
828 | | *--------------------------------------------------------------- |
829 | | */ |
830 | | static bool |
831 | | zbee_sec_decrypt_payload(zbee_security_packet *packet, const uint8_t *enc_buffer, const unsigned offset, uint8_t *dec_buffer, |
832 | | unsigned payload_len, unsigned mic_len, uint8_t *key) |
833 | 27 | { |
834 | 27 | uint8_t nonce[ZBEE_SEC_CONST_NONCE_LEN]; |
835 | 27 | uint8_t buffer[ZBEE_SEC_CONST_BLOCKSIZE+1]; |
836 | 27 | uint8_t *key_buffer = buffer; |
837 | | |
838 | 27 | switch (packet->key_id) { |
839 | 3 | case ZBEE_SEC_KEY_NWK: |
840 | | /* Decrypt with the PAN's current network key */ |
841 | 7 | case ZBEE_SEC_KEY_LINK: |
842 | | /* Decrypt with the unhashed link key assigned by the trust center to this |
843 | | * source/destination pair */ |
844 | 7 | key_buffer = key; |
845 | 7 | break; |
846 | | |
847 | 7 | case ZBEE_SEC_KEY_TRANSPORT: |
848 | | /* Decrypt with a Key-Transport key, a hashed link key that protects network |
849 | | * keys sent from the trust center */ |
850 | 7 | zbee_sec_key_hash(key, 0x00, buffer); |
851 | 7 | key_buffer = buffer; |
852 | 7 | break; |
853 | | |
854 | 13 | case ZBEE_SEC_KEY_LOAD: |
855 | | /* Decrypt with a Key-Load key, a hashed link key that protects link keys |
856 | | * sent from the trust center. */ |
857 | 13 | zbee_sec_key_hash(key, 0x02, buffer); |
858 | 13 | key_buffer = buffer; |
859 | 13 | break; |
860 | | |
861 | 0 | default: |
862 | 0 | break; |
863 | 27 | } /* switch */ |
864 | | |
865 | | /* Perform Decryption. */ |
866 | 27 | zbee_sec_make_nonce(packet, nonce); |
867 | | |
868 | 27 | if ( zbee_sec_ccm_decrypt(key_buffer, /* key */ |
869 | 27 | nonce, /* Nonce */ |
870 | 27 | enc_buffer, /* a, length l(a) */ |
871 | 27 | enc_buffer+offset, /* c, length l(c) = l(m) + M */ |
872 | 27 | dec_buffer, /* m, length l(m) */ |
873 | 27 | offset, /* l(a) */ |
874 | 27 | payload_len, /* l(m) */ |
875 | 27 | mic_len) ) { /* M */ |
876 | 0 | return true; |
877 | 0 | } |
878 | 27 | else return false; |
879 | 27 | } |
880 | | |
881 | | /*FUNCTION:------------------------------------------------------ |
882 | | * NAME |
883 | | * zbee_sec_make_nonce |
884 | | * DESCRIPTION |
885 | | * Fills in the ZigBee security nonce from the provided security |
886 | | * packet structure. |
887 | | * PARAMETERS |
888 | | * zbee_security_packet *packet - Security information. |
889 | | * char *nonce - Nonce Buffer. |
890 | | * RETURNS |
891 | | * void |
892 | | *--------------------------------------------------------------- |
893 | | */ |
894 | | static void |
895 | | zbee_sec_make_nonce(zbee_security_packet *packet, uint8_t *nonce) |
896 | 27 | { |
897 | | /* First 8 bytes are the extended source address (little endian). */ |
898 | 27 | phtoleu64(nonce, packet->src64); |
899 | 27 | nonce += 8; |
900 | | /* Next 4 bytes are the frame counter (little endian). */ |
901 | 27 | phtoleu32(nonce, packet->counter); |
902 | 27 | nonce += 4; |
903 | | /* Next byte is the security control field. */ |
904 | 27 | *(nonce) = packet->control; |
905 | 27 | } /* zbee_sec_make_nonce */ |
906 | | |
907 | | /*FUNCTION:------------------------------------------------------ |
908 | | * NAME |
909 | | * zbee_sec_ccm_decrypt |
910 | | * DESCRIPTION |
911 | | * Performs the Reverse CCM* Transformation (specified in |
912 | | * section A.3 of ZigBee Specification (053474r17). |
913 | | * |
914 | | * The length of parameter c (l(c)) is derived from the length |
915 | | * of the payload and length of the MIC tag. Input buffer a |
916 | | * will NOT be modified. |
917 | | * |
918 | | * When l_m is 0, then there is no payload to encrypt (ie: the |
919 | | * payload is in plaintext), and this function will perform |
920 | | * MIC verification only. When l_m is 0, m may be NULL. |
921 | | * PARAMETERS |
922 | | * char *key - ZigBee Security Key (must be ZBEE_SEC_CONST_KEYSIZE) in length. |
923 | | * char *nonce - ZigBee CCM* Nonce (must be ZBEE_SEC_CONST_NONCE_LEN) in length. |
924 | | * char *a - CCM* Parameter a (must be l(a) in length). Additional data covered |
925 | | * by the authentication process. |
926 | | * char *c - CCM* Parameter c (must be l(c) = l(m) + M in length). Encrypted |
927 | | * payload + encrypted authentication tag U. |
928 | | * char *m - CCM* Output (must be l(m) in length). Decrypted Payload. |
929 | | * unsigned l_a - l(a), length of CCM* parameter a. |
930 | | * unsigned l_m - l(m), length of expected payload. |
931 | | * unsigned M - M, length of CCM* authentication tag. |
932 | | * RETURNS |
933 | | * bool - true if successful. |
934 | | *--------------------------------------------------------------- |
935 | | */ |
936 | | bool |
937 | | zbee_sec_ccm_decrypt(const uint8_t *key, /* Input */ |
938 | | const uint8_t *nonce, /* Input */ |
939 | | const uint8_t *a, /* Input */ |
940 | | const uint8_t *c, /* Input */ |
941 | | uint8_t *m, /* Output */ |
942 | | unsigned l_a, /* sizeof(a) */ |
943 | | unsigned l_m, /* sizeof(m) */ |
944 | | unsigned M) /* sizeof(c) - sizeof(m) = sizeof(MIC) */ |
945 | 31 | { |
946 | 31 | uint8_t cipher_in[ZBEE_SEC_CONST_BLOCKSIZE]; |
947 | 31 | uint8_t cipher_out[ZBEE_SEC_CONST_BLOCKSIZE]; |
948 | 31 | uint8_t decrypted_mic[ZBEE_SEC_CONST_BLOCKSIZE]; |
949 | 31 | unsigned i, j; |
950 | | /* Cipher Instance. */ |
951 | 31 | gcry_cipher_hd_t cipher_hd; |
952 | | |
953 | | /* Sanity-Check. */ |
954 | 31 | if (M > ZBEE_SEC_CONST_BLOCKSIZE) return false; |
955 | | /* |
956 | | * The CCM* counter is L bytes in length, ensure that the payload |
957 | | * isn't long enough to overflow it. |
958 | | */ |
959 | 31 | if ((1 + (l_a/ZBEE_SEC_CONST_BLOCKSIZE)) > (1<<(ZBEE_SEC_CONST_L*8))) return false; |
960 | | |
961 | | /****************************************************** |
962 | | * Step 1: Encryption/Decryption Transformation |
963 | | ****************************************************** |
964 | | */ |
965 | | /* Create the CCM* counter block A0 */ |
966 | 31 | memset(cipher_in, 0, ZBEE_SEC_CONST_BLOCKSIZE); |
967 | 31 | cipher_in[0] = ZBEE_SEC_CCM_FLAG_L; |
968 | 31 | memcpy(cipher_in + 1, nonce, ZBEE_SEC_CONST_NONCE_LEN); |
969 | | /* |
970 | | * The encryption/decryption process of CCM* works in CTR mode. Open a CTR |
971 | | * mode cipher for this phase. NOTE: The 'counter' part of the CCM* counter |
972 | | * block is the last two bytes, and is big-endian. |
973 | | */ |
974 | 31 | if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) { |
975 | 0 | return false; |
976 | 0 | } |
977 | | /* Set the Key. */ |
978 | 31 | if (gcry_cipher_setkey(cipher_hd, key, ZBEE_SEC_CONST_KEYSIZE)) { |
979 | 0 | gcry_cipher_close(cipher_hd); |
980 | 0 | return false; |
981 | 0 | } |
982 | | /* Set the counter. */ |
983 | 31 | if (gcry_cipher_setctr(cipher_hd, cipher_in, ZBEE_SEC_CONST_BLOCKSIZE)) { |
984 | 0 | gcry_cipher_close(cipher_hd); |
985 | 0 | return false; |
986 | 0 | } |
987 | | /* |
988 | | * Copy the MIC into the stack buffer. We need to feed the cipher a full |
989 | | * block when decrypting the MIC (so that the payload starts on the second |
990 | | * block). However, the MIC may be less than a full block so use a fixed |
991 | | * size buffer to store the MIC, letting the CTR cipher overstep the MIC |
992 | | * if need be. |
993 | | */ |
994 | 31 | memset(decrypted_mic, 0, ZBEE_SEC_CONST_BLOCKSIZE); |
995 | 31 | memcpy(decrypted_mic, c + l_m, M); |
996 | | /* Encrypt/Decrypt the MIC in-place. */ |
997 | 31 | if (gcry_cipher_encrypt(cipher_hd, decrypted_mic, ZBEE_SEC_CONST_BLOCKSIZE, decrypted_mic, ZBEE_SEC_CONST_BLOCKSIZE)) { |
998 | 0 | gcry_cipher_close(cipher_hd); |
999 | 0 | return false; |
1000 | 0 | } |
1001 | | /* Encrypt/Decrypt the payload. */ |
1002 | 31 | if (gcry_cipher_encrypt(cipher_hd, m, l_m, c, l_m)) { |
1003 | 0 | gcry_cipher_close(cipher_hd); |
1004 | 0 | return false; |
1005 | 0 | } |
1006 | | /* Done with the CTR Cipher. */ |
1007 | 31 | gcry_cipher_close(cipher_hd); |
1008 | | |
1009 | | /****************************************************** |
1010 | | * Step 3: Authentication Transformation |
1011 | | ****************************************************** |
1012 | | */ |
1013 | 31 | if (M == 0) { |
1014 | | /* There is no authentication tag. We're done! */ |
1015 | 2 | return true; |
1016 | 2 | } |
1017 | | /* |
1018 | | * The authentication process in CCM* operates in CBC-MAC mode, but |
1019 | | * unfortunately, the input to the CBC-MAC process needs some substantial |
1020 | | * transformation and padding before we can feed it into the CBC-MAC |
1021 | | * algorithm. Instead we will operate in ECB mode and perform the |
1022 | | * transformation and padding on the fly. |
1023 | | * |
1024 | | * I also think that libgcrypt requires the input to be memory-aligned |
1025 | | * when using CBC-MAC mode, in which case can't just feed it with data |
1026 | | * from the packet buffer. All things considered it's just a lot easier |
1027 | | * to use ECB mode and do CBC-MAC manually. |
1028 | | */ |
1029 | | /* Re-open the cipher in ECB mode. */ |
1030 | 29 | if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0)) { |
1031 | 0 | return false; |
1032 | 0 | } |
1033 | | /* Re-load the key. */ |
1034 | 29 | if (gcry_cipher_setkey(cipher_hd, key, ZBEE_SEC_CONST_KEYSIZE)) { |
1035 | 0 | gcry_cipher_close(cipher_hd); |
1036 | 0 | return false; |
1037 | 0 | } |
1038 | | /* Generate the first cipher block B0. */ |
1039 | 29 | cipher_in[0] = ZBEE_SEC_CCM_FLAG_M(M) | |
1040 | 29 | ZBEE_SEC_CCM_FLAG_ADATA(l_a) | |
1041 | 29 | ZBEE_SEC_CCM_FLAG_L; |
1042 | 29 | memcpy(cipher_in+sizeof(char), nonce, ZBEE_SEC_CONST_NONCE_LEN); |
1043 | 87 | for (i=0;i<ZBEE_SEC_CONST_L; i++) { |
1044 | 58 | cipher_in[(ZBEE_SEC_CONST_BLOCKSIZE-1)-i] = (l_m >> (8*i)) & 0xff; |
1045 | 58 | } /* for */ |
1046 | | /* Generate the first cipher block, X1 = E(Key, 0^128 XOR B0). */ |
1047 | 29 | if (gcry_cipher_encrypt(cipher_hd, cipher_out, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, ZBEE_SEC_CONST_BLOCKSIZE)) { |
1048 | 0 | gcry_cipher_close(cipher_hd); |
1049 | 0 | return false; |
1050 | 0 | } |
1051 | | /* |
1052 | | * We avoid mallocing() big chunks of memory by recycling small stack |
1053 | | * buffers for the encryption process. Throughout this process, j is always |
1054 | | * pointed to the position within the current buffer. |
1055 | | */ |
1056 | 29 | j = 0; |
1057 | | /* AuthData = L(a) || a || Padding || m || Padding |
1058 | | * Where L(a) = |
1059 | | * - an empty string if l(a) == 0. |
1060 | | * - 2-octet encoding of l(a) if 0 < l(a) < (2^16 - 2^8) |
1061 | | * - 0xff || 0xfe || 4-octet encoding of l(a) if (2^16 - 2^8) <= l(a) < 2^32 |
1062 | | * - 0xff || 0xff || 8-octet encoding of l(a) |
1063 | | * But for ZigBee, the largest packet size we should ever see is 2^7, so we |
1064 | | * are only really concerned with the first two cases. |
1065 | | * |
1066 | | * To generate the MIC tag CCM* operates similar to CBC-MAC mode. Each block |
1067 | | * of AuthData is XOR'd with the last block of cipher output to produce the |
1068 | | * next block of cipher output. Padding sections have the minimum non-negative |
1069 | | * length such that the padding ends on a block boundary. Padded bytes are 0. |
1070 | | */ |
1071 | 29 | if (l_a > 0) { |
1072 | | /* Process L(a) into the cipher block. */ |
1073 | 29 | cipher_in[j] = cipher_out[j] ^ ((l_a >> 8) & 0xff); |
1074 | 29 | j++; |
1075 | 29 | cipher_in[j] = cipher_out[j] ^ ((l_a >> 0) & 0xff); |
1076 | 29 | j++; |
1077 | | /* Process a into the cipher block. */ |
1078 | 1.74k | for (i=0;i<l_a;i++,j++) { |
1079 | 1.72k | if (j>=ZBEE_SEC_CONST_BLOCKSIZE) { |
1080 | | /* Generate the next cipher block. */ |
1081 | 95 | if (gcry_cipher_encrypt(cipher_hd, cipher_out, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, |
1082 | 95 | ZBEE_SEC_CONST_BLOCKSIZE)) { |
1083 | 0 | gcry_cipher_close(cipher_hd); |
1084 | 0 | return false; |
1085 | 0 | } |
1086 | | /* Reset j to point back to the start of the new cipher block. */ |
1087 | 95 | j = 0; |
1088 | 95 | } |
1089 | | /* Cipher in = cipher_out ^ a */ |
1090 | 1.72k | cipher_in[j] = cipher_out[j] ^ a[i]; |
1091 | 1.72k | } /* for */ |
1092 | | /* Process padding into the cipher block. */ |
1093 | 235 | for (;j<ZBEE_SEC_CONST_BLOCKSIZE;j++) |
1094 | 206 | cipher_in[j] = cipher_out[j]; |
1095 | 29 | } |
1096 | | /* Process m into the cipher block. */ |
1097 | 5.82k | for (i=0; i<l_m; i++, j++) { |
1098 | 5.79k | if (j>=ZBEE_SEC_CONST_BLOCKSIZE) { |
1099 | | /* Generate the next cipher block. */ |
1100 | 374 | if (gcry_cipher_encrypt(cipher_hd, cipher_out, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, |
1101 | 374 | ZBEE_SEC_CONST_BLOCKSIZE)) { |
1102 | 0 | gcry_cipher_close(cipher_hd); |
1103 | 0 | return false; |
1104 | 0 | } |
1105 | | /* Reset j to point back to the start of the new cipher block. */ |
1106 | 374 | j = 0; |
1107 | 374 | } |
1108 | | /* Cipher in = cipher out ^ m */ |
1109 | 5.79k | cipher_in[j] = cipher_out[j] ^ m[i]; |
1110 | 5.79k | } /* for */ |
1111 | | /* Padding. */ |
1112 | 214 | for (;j<ZBEE_SEC_CONST_BLOCKSIZE;j++) |
1113 | 185 | cipher_in[j] = cipher_out[j]; |
1114 | | /* Generate the last cipher block, which will be the MIC tag. */ |
1115 | 29 | if (gcry_cipher_encrypt(cipher_hd, cipher_out, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, ZBEE_SEC_CONST_BLOCKSIZE)) { |
1116 | 0 | gcry_cipher_close(cipher_hd); |
1117 | 0 | return false; |
1118 | 0 | } |
1119 | | /* Done with the Cipher. */ |
1120 | 29 | gcry_cipher_close(cipher_hd); |
1121 | | |
1122 | | /* Compare the MIC's */ |
1123 | 29 | return (memcmp(cipher_out, decrypted_mic, M) == 0); |
1124 | 29 | } /* zbee_ccm_decrypt */ |
1125 | | |
1126 | | /*FUNCTION:------------------------------------------------------ |
1127 | | * NAME |
1128 | | * zbee_sec_hash |
1129 | | * DESCRIPTION |
1130 | | * ZigBee Cryptographic Hash Function, described in ZigBee |
1131 | | * specification sections B.1.3 and B.6. |
1132 | | * |
1133 | | * This is a Matyas-Meyer-Oseas hash function using the AES-128 |
1134 | | * cipher. We use the ECB mode of libgcrypt to get a raw block |
1135 | | * cipher. |
1136 | | * |
1137 | | * Input may be any length, and the output must be exactly 1-block in length. |
1138 | | * |
1139 | | * Implements the function: |
1140 | | * Hash(text) = Hash[t]; |
1141 | | * Hash[0] = 0^(blocksize). |
1142 | | * Hash[i] = E(Hash[i-1], M[i]) XOR M[j]; |
1143 | | * M[i] = i'th block of text, with some padding and flags concatenated. |
1144 | | * PARAMETERS |
1145 | | * uint8_t * input - Hash Input (any length). |
1146 | | * uint8_t input_len - Hash Input Length. |
1147 | | * uint8_t * output - Hash Output (exactly one block in length). |
1148 | | * RETURNS |
1149 | | * void |
1150 | | *--------------------------------------------------------------- |
1151 | | */ |
1152 | | static void |
1153 | | zbee_sec_hash(uint8_t *input, unsigned input_len, uint8_t *output) |
1154 | 40 | { |
1155 | 40 | uint8_t cipher_in[ZBEE_SEC_CONST_BLOCKSIZE]; |
1156 | 40 | unsigned i, j; |
1157 | | /* Cipher Instance. */ |
1158 | 40 | gcry_cipher_hd_t cipher_hd; |
1159 | | |
1160 | | /* Clear the first hash block (Hash0). */ |
1161 | 40 | memset(output, 0, ZBEE_SEC_CONST_BLOCKSIZE); |
1162 | | /* Create the cipher instance in ECB mode. */ |
1163 | 40 | if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0)) { |
1164 | 0 | return; /* Failed. */ |
1165 | 0 | } |
1166 | | /* Create the subsequent hash blocks using the formula: Hash[i] = E(Hash[i-1], M[i]) XOR M[i] |
1167 | | * |
1168 | | * because we can't guarantee that M will be exactly a multiple of the |
1169 | | * block size, we will need to copy it into local buffers and pad it. |
1170 | | * |
1171 | | * Note that we check for the next cipher block at the end of the loop |
1172 | | * rather than the start. This is so that if the input happens to end |
1173 | | * on a block boundary, the next cipher block will be generated for the |
1174 | | * start of the padding to be placed into. |
1175 | | */ |
1176 | 40 | i = 0; |
1177 | 40 | j = 0; |
1178 | 1.02k | while (i<input_len) { |
1179 | | /* Copy data into the cipher input. */ |
1180 | 980 | cipher_in[j++] = input[i++]; |
1181 | | /* Check if this cipher block is done. */ |
1182 | 980 | if (j >= ZBEE_SEC_CONST_BLOCKSIZE) { |
1183 | | /* We have reached the end of this block. Process it with the |
1184 | | * cipher, note that the Key input to the cipher is actually |
1185 | | * the previous hash block, which we are keeping in output. |
1186 | | */ |
1187 | 60 | (void)gcry_cipher_setkey(cipher_hd, output, ZBEE_SEC_CONST_BLOCKSIZE); |
1188 | 60 | (void)gcry_cipher_encrypt(cipher_hd, output, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, ZBEE_SEC_CONST_BLOCKSIZE); |
1189 | | /* Now we have to XOR the input into the hash block. */ |
1190 | 1.02k | for (j=0;j<ZBEE_SEC_CONST_BLOCKSIZE;j++) output[j] ^= cipher_in[j]; |
1191 | | /* Reset j to start again at the beginning at the next block. */ |
1192 | 60 | j = 0; |
1193 | 60 | } |
1194 | 980 | } /* for */ |
1195 | | /* Need to append the bit '1', followed by '0' padding long enough to end |
1196 | | * the hash input on a block boundary. However, because 'n' is 16, and 'l' |
1197 | | * will be a multiple of 8, the padding will be >= 7-bits, and we can just |
1198 | | * append the byte 0x80. |
1199 | | */ |
1200 | 40 | cipher_in[j++] = 0x80; |
1201 | | /* Pad with '0' until the current block is exactly 'n' bits from the |
1202 | | * end. |
1203 | | */ |
1204 | 540 | while (j!=(ZBEE_SEC_CONST_BLOCKSIZE-2)) { |
1205 | 500 | if (j >= ZBEE_SEC_CONST_BLOCKSIZE) { |
1206 | | /* We have reached the end of this block. Process it with the |
1207 | | * cipher, note that the Key input to the cipher is actually |
1208 | | * the previous hash block, which we are keeping in output. |
1209 | | */ |
1210 | 0 | (void)gcry_cipher_setkey(cipher_hd, output, ZBEE_SEC_CONST_BLOCKSIZE); |
1211 | 0 | (void)gcry_cipher_encrypt(cipher_hd, output, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, ZBEE_SEC_CONST_BLOCKSIZE); |
1212 | | /* Now we have to XOR the input into the hash block. */ |
1213 | 0 | for (j=0;j<ZBEE_SEC_CONST_BLOCKSIZE;j++) output[j] ^= cipher_in[j]; |
1214 | | /* Reset j to start again at the beginning at the next block. */ |
1215 | 0 | j = 0; |
1216 | 0 | } |
1217 | | /* Pad the input with 0. */ |
1218 | 500 | cipher_in[j++] = 0x00; |
1219 | 500 | } /* while */ |
1220 | | /* Add the 'n'-bit representation of 'l' to the end of the block. */ |
1221 | 40 | cipher_in[j++] = ((input_len * 8) >> 8) & 0xff; |
1222 | 40 | cipher_in[j] = ((input_len * 8) >> 0) & 0xff; |
1223 | | /* Process the last cipher block. */ |
1224 | 40 | (void)gcry_cipher_setkey(cipher_hd, output, ZBEE_SEC_CONST_BLOCKSIZE); |
1225 | 40 | (void)gcry_cipher_encrypt(cipher_hd, output, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, ZBEE_SEC_CONST_BLOCKSIZE); |
1226 | | /* XOR the last input block back into the cipher output to get the hash. */ |
1227 | 680 | for (j=0;j<ZBEE_SEC_CONST_BLOCKSIZE;j++) output[j] ^= cipher_in[j]; |
1228 | | /* Cleanup the cipher. */ |
1229 | 40 | gcry_cipher_close(cipher_hd); |
1230 | | /* Done */ |
1231 | 40 | } /* zbee_sec_hash */ |
1232 | | |
1233 | | /*FUNCTION:------------------------------------------------------ |
1234 | | * NAME |
1235 | | * zbee_sec_key_hash |
1236 | | * DESCRIPTION |
1237 | | * ZigBee Keyed Hash Function. Described in ZigBee specification |
1238 | | * section B.1.4, and in FIPS Publication 198. Strictly speaking |
1239 | | * there is nothing about the Keyed Hash Function which restricts |
1240 | | * it to only a single byte input, but that's all ZigBee ever uses. |
1241 | | * |
1242 | | * This function implements the hash function: |
1243 | | * Hash(Key, text) = H((Key XOR opad) || H((Key XOR ipad) || text)); |
1244 | | * ipad = 0x36 repeated. |
1245 | | * opad = 0x5c repeated. |
1246 | | * H() = ZigBee Cryptographic Hash (B.1.3 and B.6). |
1247 | | * PARAMETERS |
1248 | | * uint8_t *key - ZigBee Security Key (must be ZBEE_SEC_CONST_KEYSIZE) in length. |
1249 | | * uint8_t input - ZigBee CCM* Nonce (must be ZBEE_SEC_CONST_NONCE_LEN) in length. |
1250 | | * uint8_t *hash_out - buffer into which the key-hashed output is placed |
1251 | | * RETURNS |
1252 | | * void |
1253 | | *--------------------------------------------------------------- |
1254 | | */ |
1255 | | static void |
1256 | | zbee_sec_key_hash(uint8_t *key, uint8_t input, uint8_t *hash_out) |
1257 | 20 | { |
1258 | 20 | uint8_t hash_in[2*ZBEE_SEC_CONST_BLOCKSIZE]; |
1259 | 20 | int i; |
1260 | 20 | static const uint8_t ipad = 0x36; |
1261 | 20 | static const uint8_t opad = 0x5c; |
1262 | | |
1263 | | /* Copy the key into hash_in and XOR with opad to form: (Key XOR opad) */ |
1264 | 340 | for (i=0; i<ZBEE_SEC_CONST_KEYSIZE; i++) hash_in[i] = key[i] ^ opad; |
1265 | | /* Copy the Key into hash_out and XOR with ipad to form: (Key XOR ipad) */ |
1266 | 340 | for (i=0; i<ZBEE_SEC_CONST_KEYSIZE; i++) hash_out[i] = key[i] ^ ipad; |
1267 | | /* Append the input byte to form: (Key XOR ipad) || text. */ |
1268 | 20 | hash_out[ZBEE_SEC_CONST_BLOCKSIZE] = input; |
1269 | | /* Hash the contents of hash_out and append the contents to hash_in to |
1270 | | * form: (Key XOR opad) || H((Key XOR ipad) || text). |
1271 | | */ |
1272 | 20 | zbee_sec_hash(hash_out, ZBEE_SEC_CONST_BLOCKSIZE+1, hash_in+ZBEE_SEC_CONST_BLOCKSIZE); |
1273 | | /* Hash the contents of hash_in to get the final result. */ |
1274 | 20 | zbee_sec_hash(hash_in, 2*ZBEE_SEC_CONST_BLOCKSIZE, hash_out); |
1275 | 20 | } /* zbee_sec_key_hash */ |
1276 | | |
1277 | | /** |
1278 | | *Add NWK or APS key into NWK keyring |
1279 | | * |
1280 | | *@param pinfo pointer to packet information fields |
1281 | | *@param key APS or NWK key |
1282 | | */ |
1283 | | void zbee_sec_add_key_to_keyring(packet_info *pinfo, const uint8_t *key) |
1284 | 27 | { |
1285 | 27 | GSList **nwk_keyring; |
1286 | 27 | key_record_t key_record; |
1287 | 27 | zbee_nwk_hints_t *nwk_hints; |
1288 | | |
1289 | | /* Update the key ring for this pan */ |
1290 | 27 | if ( !pinfo->fd->visited && (nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, |
1291 | 27 | proto_zbee_nwk, 0))) { |
1292 | 27 | nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan); |
1293 | 27 | if ( !nwk_keyring ) { |
1294 | 11 | nwk_keyring = (GSList **)g_malloc0(sizeof(GSList*)); |
1295 | 11 | g_hash_table_insert(zbee_table_nwk_keyring, |
1296 | 11 | g_memdup2(&nwk_hints->src_pan, sizeof(nwk_hints->src_pan)), nwk_keyring); |
1297 | 11 | } |
1298 | | |
1299 | 27 | if ( nwk_keyring ) { |
1300 | 27 | if ( !*nwk_keyring || |
1301 | 16 | memcmp( ((key_record_t *)((GSList *)(*nwk_keyring))->data)->key, key, |
1302 | 23 | ZBEE_APS_CMD_KEY_LENGTH) ) { |
1303 | | /* Store a new or different key in the key ring */ |
1304 | 23 | key_record.frame_num = pinfo->num; |
1305 | 23 | key_record.label = NULL; |
1306 | 23 | memcpy(&key_record.key, key, ZBEE_APS_CMD_KEY_LENGTH); |
1307 | 23 | *nwk_keyring = g_slist_prepend(*nwk_keyring, g_memdup2(&key_record, sizeof(key_record_t))); |
1308 | 23 | } |
1309 | 27 | } |
1310 | 27 | } |
1311 | 27 | } /* nwk_add_key_to_keyring */ |
1312 | | |
1313 | | /** |
1314 | | *Add NWK or APS key into NWK keyring |
1315 | | * |
1316 | | *@param pinfo pointer to packet information fields |
1317 | | *@param key APS or NWK key |
1318 | | */ |
1319 | | void zbee_sec_add_key_to_keyring_panid(packet_info *pinfo, const uint8_t *key, int panid) |
1320 | 0 | { |
1321 | 0 | GSList **nwk_keyring; |
1322 | 0 | key_record_t key_record; |
1323 | | |
1324 | | /* Update the key ring for this pan */ |
1325 | 0 | if ( !pinfo->fd->visited ) { |
1326 | 0 | nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &panid); |
1327 | 0 | if ( !nwk_keyring ) { |
1328 | 0 | nwk_keyring = (GSList **)g_malloc0(sizeof(GSList*)); |
1329 | 0 | g_hash_table_insert(zbee_table_nwk_keyring, |
1330 | 0 | g_memdup2(&panid, sizeof(panid)), nwk_keyring); |
1331 | 0 | } |
1332 | |
|
1333 | 0 | if ( nwk_keyring ) { |
1334 | 0 | if ( !*nwk_keyring || |
1335 | 0 | memcmp( ((key_record_t *)((GSList *)(*nwk_keyring))->data)->key, key, |
1336 | 0 | ZBEE_APS_CMD_KEY_LENGTH) ) { |
1337 | | /* Store a new or different key in the key ring */ |
1338 | 0 | key_record.frame_num = pinfo->num; |
1339 | 0 | key_record.label = NULL; |
1340 | 0 | memcpy(&key_record.key, key, ZBEE_APS_CMD_KEY_LENGTH); |
1341 | 0 | *nwk_keyring = g_slist_prepend(*nwk_keyring, g_memdup2(&key_record, sizeof(key_record_t))); |
1342 | 0 | } |
1343 | 0 | } |
1344 | 0 | } |
1345 | 0 | } /* zbee_sec_add_key_to_keyring_panid */ |
1346 | | |
1347 | | /** |
1348 | | *Get key from keyring |
1349 | | * |
1350 | | *@param label key label |
1351 | | *@param key NWK key |
1352 | | */ |
1353 | | bool zbee_sec_get_key_from_keyring(const char *label, uint8_t *key) |
1354 | 0 | { |
1355 | 0 | GSList *GSList_i; |
1356 | | /* Loop through user's password table for preconfigured keys, our last resort */ |
1357 | 0 | GSList_i = zbee_pc_keyring; |
1358 | 0 | while ( GSList_i ) { |
1359 | 0 | key_record_t * rec = (key_record_t *)GSList_i->data; |
1360 | 0 | ws_debug("'%s': %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", rec->label, (uint8_t)rec->key[0x0], (uint8_t)rec->key[0x1], (uint8_t)rec->key[0x2], (uint8_t)rec->key[0x3], (uint8_t)rec->key[0x4], (uint8_t)rec->key[0x5], (uint8_t)rec->key[0x6], (uint8_t)rec->key[0x7], (uint8_t)rec->key[0x8], (uint8_t)rec->key[0x9], (uint8_t)rec->key[0xA], (uint8_t)rec->key[0xB], (uint8_t)rec->key[0xC], (uint8_t)rec->key[0xD], (uint8_t)rec->key[0xE], (uint8_t)rec->key[0xF]); |
1361 | |
|
1362 | 0 | if(!strcmp(label, rec->label)){ |
1363 | 0 | memcpy(key, rec->key, ZBEE_SEC_CONST_KEYSIZE); |
1364 | 0 | return 1; |
1365 | 0 | } |
1366 | | |
1367 | 0 | GSList_i = g_slist_next(GSList_i); |
1368 | 0 | } |
1369 | 0 | return 0; |
1370 | 0 | } /* zbee_sec_get_key_from_keyring */ |
1371 | | |
1372 | | /* |
1373 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1374 | | * |
1375 | | * Local variables: |
1376 | | * c-basic-offset: 4 |
1377 | | * tab-width: 8 |
1378 | | * indent-tabs-mode: nil |
1379 | | * End: |
1380 | | * |
1381 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
1382 | | * :indentSize=4:tabSize=8:noTabs=true: |
1383 | | */ |