packet-ldap: fix regression for SASL handling
[wireshark-sm.git] / epan / crypt / dot11decrypt.c
blobfaa50dcbd4fd073eca4c93ada6020a26209899a8
1 /* dot11decrypt.c
3 * Copyright (c) 2006 CACE Technologies, Davis (California)
4 * All rights reserved.
6 * SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
7 */
9 /****************************************************************************/
10 /* File includes */
12 #include "config.h"
14 #include <glib.h>
16 #include <wsutil/wsgcrypt.h>
17 #include <wsutil/crc32.h>
18 #include <wsutil/pint.h>
19 #include <wsutil/glib-compat.h>
21 #include <epan/proto.h> /* for DISSECTOR_ASSERT. */
22 #include <epan/tvbuff.h>
23 #include <epan/to_str.h>
24 #include <epan/strutil.h>
26 #include "dot11decrypt_util.h"
27 #include "dot11decrypt_system.h"
28 #include "dot11decrypt_int.h"
30 #include "dot11decrypt_debug.h"
32 #include "wep-wpadefs.h"
35 /****************************************************************************/
36 static int Dot11DecryptGetKckLen(int akm);
37 static int Dot11DecryptGetTkLen(int cipher);
38 static int Dot11DecryptGetKekLen(int akm);
39 static int Dot11DecryptGetPtkLen(int akm, int cipher);
40 static int Dot11DecryptGetHashAlgoFromAkm(int akm);
42 /****************************************************************************/
43 /* Constant definitions */
45 /* EAPOL definitions */
46 /**
47 * Length of the EAPOL-Key key confirmation key (KCK) used to calculate
48 * MIC over EAPOL frame and validate an EAPOL packet (128 bits)
50 #define DOT11DECRYPT_WPA_KCK_LEN 16
51 /**
52 *Offset of the Key MIC in the EAPOL packet body
54 #define DOT11DECRYPT_WPA_MICKEY_OFFSET 77
55 /**
56 * Maximum length of the EAPOL packet (it depends on the maximum MAC
57 * frame size)
59 #define DOT11DECRYPT_WPA_MAX_EAPOL_LEN 4095
60 /**
61 * EAPOL Key Descriptor Version 1, used for all EAPOL-Key frames to and
62 * from a STA when neither the group nor pairwise ciphers are CCMP for
63 * Key Descriptor 1.
64 * @note
65 * Defined in 802.11i-2004, page 78
67 #define DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP 1
68 /**
69 * EAPOL Key Descriptor Version 2, used for all EAPOL-Key frames to and
70 * from a STA when either the pairwise or the group cipher is AES-CCMP
71 * for Key Descriptor 2.
72 * /note
73 * Defined in 802.11i-2004, page 78
75 #define DOT11DECRYPT_WPA_KEY_VER_AES_CCMP 2
77 /** Define EAPOL Key Descriptor type values: use 254 for WPA and 2 for WPA2 **/
78 #define DOT11DECRYPT_RSN_WPA_KEY_DESCRIPTOR 254
79 #define DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR 2
81 /* PMK to PTK derive functions */
82 #define DOT11DECRYPT_DERIVE_USING_PRF 0
83 #define DOT11DECRYPT_DERIVE_USING_KDF 1
84 /****************************************************************************/
87 /****************************************************************************/
88 /* Macro definitions */
90 extern const UINT32 crc32_table[256];
91 #define CRC(crc, ch) (crc = (crc >> 8) ^ crc32_table[(crc ^ (ch)) & 0xff])
93 #define KCK_OFFSET(akm) (0)
94 #define KEK_OFFSET(akm) ((KCK_OFFSET(akm) + Dot11DecryptGetKckLen(akm) / 8))
95 #define TK_OFFSET(akm) ((KEK_OFFSET(akm) + Dot11DecryptGetKekLen(akm) / 8))
97 #define DOT11DECRYPT_GET_KCK(ptk, akm) (ptk + KCK_OFFSET(akm))
98 #define DOT11DECRYPT_GET_KEK(ptk, akm) (ptk + KEK_OFFSET(akm))
99 #define DOT11DECRYPT_GET_TK_TKIP(ptk) (ptk + 32)
100 #define DOT11DECRYPT_GET_TK(ptk, akm) (ptk + TK_OFFSET(akm))
102 #define DOT11DECRYPT_IEEE80211_OUI(oui) (pntoh24(oui) == 0x000fac)
104 /****************************************************************************/
106 /****************************************************************************/
107 /* Type definitions */
109 /* Internal function prototype declarations */
111 #ifdef __cplusplus
112 extern "C" {
113 #endif
116 * It is a step of the PBKDF2 (specifically the PKCS #5 v2.0) defined in
117 * the RFC 2898 to derive a key (used as PMK in WPA)
118 * @param ppbytes [IN] pointer to a password (sequence of between 8 and
119 * 63 ASCII encoded characters)
120 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
121 * encoded characters
122 * @param iterations [IN] times to hash the password (4096 for WPA)
123 * @param count [IN] ???
124 * @param output [OUT] pointer to a preallocated buffer of
125 * SHA1_DIGEST_LEN characters that will contain a part of the key
127 static INT Dot11DecryptRsnaPwd2PskStep(
128 const guint8 *ppbytes,
129 const guint passLength,
130 const CHAR *ssid,
131 const size_t ssidLength,
132 const INT iterations,
133 const INT count,
134 UCHAR *output)
138 * It calculates the passphrase-to-PSK mapping reccomanded for use with
139 * RSNAs. This implementation uses the PBKDF2 method defined in the RFC
140 * 2898.
141 * @param passphrase [IN] pointer to a password (sequence of between 8 and
142 * 63 ASCII encoded characters)
143 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
144 * encoded characters
145 * @param output [OUT] calculated PSK (to use as PMK in WPA)
146 * @note
147 * Described in 802.11i-2004, page 165
149 static INT Dot11DecryptRsnaPwd2Psk(
150 const CHAR *passphrase,
151 const CHAR *ssid,
152 const size_t ssidLength,
153 UCHAR *output)
156 static INT Dot11DecryptRsnaMng(
157 UCHAR *decrypt_data,
158 guint mac_header_len,
159 guint *decrypt_len,
160 PDOT11DECRYPT_KEY_ITEM key,
161 DOT11DECRYPT_SEC_ASSOCIATION *sa)
164 static INT Dot11DecryptWepMng(
165 PDOT11DECRYPT_CONTEXT ctx,
166 UCHAR *decrypt_data,
167 guint mac_header_len,
168 guint *decrypt_len,
169 PDOT11DECRYPT_KEY_ITEM key,
170 DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
173 static INT Dot11DecryptRsna4WHandshake(
174 PDOT11DECRYPT_CONTEXT ctx,
175 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
176 const guint8 *eapol_raw,
177 DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
178 const guint tot_len);
181 * It checks whether the specified key is corrected or not.
182 * @note
183 * For a standard WEP key the length will be changed to the standard
184 * length, and the type changed in a generic WEP key.
185 * @param key [IN] pointer to the key to validate
186 * @return
187 * - TRUE: the key contains valid fields and values
188 * - FALSE: the key has some invalid field or value
190 static INT Dot11DecryptValidateKey(
191 PDOT11DECRYPT_KEY_ITEM key)
194 static INT Dot11DecryptRsnaMicCheck(
195 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
196 UCHAR *eapol,
197 USHORT eapol_len,
198 UCHAR *KCK,
199 USHORT key_ver,
200 int akm)
203 #if GCRYPT_VERSION_NUMBER >= 0x010600
204 static gint
205 Dot11DecryptFtMicCheck(
206 const PDOT11DECRYPT_ASSOC_PARSED assoc_parsed,
207 const guint8 *kck,
208 size_t kck_len);
209 #endif
211 static PDOT11DECRYPT_SEC_ASSOCIATION
212 Dot11DecryptGetSa(
213 PDOT11DECRYPT_CONTEXT ctx,
214 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
217 static INT Dot11DecryptGetSaAddress(
218 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame,
219 DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
222 static const UCHAR * Dot11DecryptGetStaAddress(
223 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame)
226 static const UCHAR * Dot11DecryptGetBssidAddress(
227 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame)
230 static guint8
231 Dot11DecryptDerivePtk(
232 const DOT11DECRYPT_SEC_ASSOCIATION *sa,
233 const UCHAR *pmk,
234 size_t pmk_len,
235 const UCHAR snonce[32],
236 int key_version,
237 int akm,
238 int cipher,
239 guint8 *ptk, size_t *ptk_len);
241 static guint8
242 Dot11DecryptFtDerivePtk(
243 const PDOT11DECRYPT_CONTEXT ctx,
244 const DOT11DECRYPT_SEC_ASSOCIATION *sa,
245 const PDOT11DECRYPT_KEY_ITEM key,
246 const guint8 mdid[2],
247 const guint8 *snonce,
248 const guint8 *r0kh_id, size_t r0kh_id_len,
249 const guint8 *r1kh_id, size_t r1kh_id_len _U_,
250 int akm, int cipher,
251 guint8 *ptk, size_t *ptk_len);
254 * @param sa [IN/OUT] pointer to SA that will hold the key
255 * @param data [IN] Frame
256 * @param offset_rsne [IN] RSNE IE offset in the frame
257 * @param offset_fte [IN] Fast BSS Transition IE offset in the frame
258 * @param offset_timeout [IN] Timeout Interval IE offset in the frame
259 * @param offset_link [IN] Link Identifier IE offset in the frame
260 * @param action [IN] Tdls Action code (response or confirm)
262 * @return
263 * DOT11DECRYPT_RET_SUCCESS if Key has been sucessfully derived (and MIC verified)
264 * DOT11DECRYPT_RET_UNSUCCESS otherwise
266 static INT
267 Dot11DecryptTDLSDeriveKey(
268 PDOT11DECRYPT_SEC_ASSOCIATION sa,
269 const guint8 *data,
270 guint offset_rsne,
271 guint offset_fte,
272 guint offset_timeout,
273 guint offset_link,
274 guint8 action)
276 #ifdef __cplusplus
278 #endif
280 /****************************************************************************/
282 /****************************************************************************/
283 /* Exported function definitions */
285 #ifdef __cplusplus
286 extern "C" {
287 #endif
289 const guint8 broadcast_mac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
291 #define TKIP_GROUP_KEY_LEN 32
292 #define CCMP_GROUP_KEY_LEN 16
294 #define EAPOL_RSN_KEY_LEN 95
296 /* Minimum possible key data size (at least one GTK KDE with CCMP key) */
297 #define GROUP_KEY_MIN_LEN 8 + CCMP_GROUP_KEY_LEN
298 /* Minimum possible group key msg size (group key msg using CCMP as cipher)*/
299 #define GROUP_KEY_PAYLOAD_LEN_MIN \
300 (EAPOL_RSN_KEY_LEN + GROUP_KEY_MIN_LEN)
302 static void
303 Dot11DecryptCopyKey(PDOT11DECRYPT_SEC_ASSOCIATION sa, PDOT11DECRYPT_KEY_ITEM key)
305 if (key!=NULL) {
306 if (sa->key!=NULL)
307 memcpy(key, sa->key, sizeof(DOT11DECRYPT_KEY_ITEM));
308 else
309 memset(key, 0, sizeof(DOT11DECRYPT_KEY_ITEM));
310 key->KeyData.Wpa.PtkLen = sa->wpa.ptk_len;
311 memcpy(key->KeyData.Wpa.Ptk, sa->wpa.ptk, sa->wpa.ptk_len);
312 key->KeyData.Wpa.Akm = sa->wpa.akm;
313 key->KeyData.Wpa.Cipher = sa->wpa.cipher;
314 if (sa->wpa.key_ver==DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP)
315 key->KeyType=DOT11DECRYPT_KEY_TYPE_TKIP;
316 else if (sa->wpa.key_ver == 0 || sa->wpa.key_ver == 3 ||
317 sa->wpa.key_ver == DOT11DECRYPT_WPA_KEY_VER_AES_CCMP)
319 switch (sa->wpa.cipher) {
320 case 1:
321 key->KeyType = DOT11DECRYPT_KEY_TYPE_WEP_40;
322 break;
323 case 2:
324 key->KeyType = DOT11DECRYPT_KEY_TYPE_TKIP;
325 break;
326 case 4:
327 key->KeyType = DOT11DECRYPT_KEY_TYPE_CCMP;
328 break;
329 case 5:
330 key->KeyType = DOT11DECRYPT_KEY_TYPE_WEP_104;
331 break;
332 case 8:
333 key->KeyType = DOT11DECRYPT_KEY_TYPE_GCMP;
334 break;
335 case 9:
336 key->KeyType = DOT11DECRYPT_KEY_TYPE_GCMP_256;
337 break;
338 case 10:
339 key->KeyType = DOT11DECRYPT_KEY_TYPE_CCMP_256;
340 break;
341 default:
342 key->KeyType = DOT11DECRYPT_KEY_TYPE_UNKNOWN;
343 break;
344 /* NOT SUPPORTED YET
345 case 3: Reserved
346 case 6: BIP-CMAC-128
347 case 7: Group addressed traffic not allowed
348 case 11: BIP-GMAC-128
349 case 12: BIP-GMAC-256
350 case 13: BIP-CMAC-256 */
356 static guint8*
357 Dot11DecryptRc4KeyData(const guint8 *decryption_key, guint decryption_key_len,
358 const guint8 *encrypted_keydata, guint encrypted_keydata_len)
360 gcry_cipher_hd_t rc4_handle;
361 guint8 dummy[256] = { 0 };
362 guint8 *decrypted_key = NULL;
364 if (gcry_cipher_open (&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
365 return NULL;
367 if (gcry_cipher_setkey(rc4_handle, decryption_key, decryption_key_len)) {
368 gcry_cipher_close(rc4_handle);
369 return NULL;
371 decrypted_key = (guint8 *)g_memdup2(encrypted_keydata, encrypted_keydata_len);
372 if (!decrypted_key) {
373 gcry_cipher_close(rc4_handle);
374 return NULL;
377 /* Do dummy 256 iterations of the RC4 algorithm (per 802.11i, Draft 3.0, p. 97 line 6) */
378 gcry_cipher_decrypt(rc4_handle, dummy, 256, NULL, 0);
379 gcry_cipher_decrypt(rc4_handle, decrypted_key, encrypted_keydata_len, NULL, 0);
380 gcry_cipher_close(rc4_handle);
381 return decrypted_key;
384 static int
385 AES_unwrap(
386 const guint8 *kek,
387 guint16 kek_len,
388 const guint8 *cipher_text,
389 guint16 cipher_len,
390 guint8 *output,
391 guint16 *output_len)
393 gcry_cipher_hd_t handle;
395 if (kek == NULL || cipher_len < 16 || cipher_text == NULL) {
396 return 1; /* "should not happen" */
398 if (gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_AESWRAP, 0)) {
399 return 1;
401 if (gcry_cipher_setkey(handle, kek, kek_len)) {
402 gcry_cipher_close(handle);
403 return 1;
405 if (gcry_cipher_decrypt(handle, output, cipher_len - 8, cipher_text, cipher_len)) {
406 gcry_cipher_close(handle);
407 return 1;
409 *output_len = cipher_len - 8;
410 gcry_cipher_close(handle);
411 return 0;
415 Dot11DecryptDecryptKeyData(PDOT11DECRYPT_CONTEXT ctx,
416 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
417 const UCHAR bssid[DOT11DECRYPT_MAC_LEN],
418 const UCHAR sta[DOT11DECRYPT_MAC_LEN],
419 UCHAR *decrypted_data, guint *decrypted_len,
420 PDOT11DECRYPT_KEY_ITEM key)
422 guint8 key_version;
423 const guint8 *key_data;
424 guint16 key_bytes_len = 0; /* Length of the total key data field */
425 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
426 PDOT11DECRYPT_SEC_ASSOCIATION sa;
428 /* search for a cached Security Association for current BSSID and AP */
429 memcpy(id.bssid, bssid, DOT11DECRYPT_MAC_LEN);
430 memcpy(id.sta, sta, DOT11DECRYPT_MAC_LEN);
431 sa = Dot11DecryptGetSa(ctx, &id);
432 if (sa == NULL || !sa->validKey) {
433 DEBUG_PRINT_LINE("No valid SA for BSSID found", DEBUG_LEVEL_3);
434 return DOT11DECRYPT_RET_UNSUCCESS;
437 /* Decrypt GTK using KEK portion of PTK */
438 guint8 *decryption_key = DOT11DECRYPT_GET_KEK(sa->wpa.ptk, sa->wpa.akm);
439 guint decryption_key_len = Dot11DecryptGetKekLen(sa->wpa.akm) / 8;
441 /* We skip verifying the MIC of the key. If we were implementing a WPA supplicant we'd want to verify, but for a sniffer it's not needed. */
443 /* Preparation for decrypting the group key - determine group key data length */
444 /* depending on whether the pairwise key is TKIP or AES encryption key */
445 key_version = eapol_parsed->key_version;
446 if (key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP){
447 /* TKIP */
448 key_bytes_len = eapol_parsed->key_len;
449 }else if (key_version == DOT11DECRYPT_WPA_KEY_VER_AES_CCMP){
450 /* AES */
451 key_bytes_len = eapol_parsed->key_data_len;
453 /* AES keys must be at least 128 bits = 16 bytes. */
454 if (key_bytes_len < 16) {
455 return DOT11DECRYPT_RET_UNSUCCESS;
457 } else {
458 /* XXX Ideally group cipher suite type from EAPOL message 2 of 4 should be used to */
459 /* determine key size. As we currently have no way to do this lookup check that key */
460 /* is at least 16 bytes (IEEE802.11-2016 Table 12-4 Cipher suite key lengths) */
461 key_bytes_len = eapol_parsed->key_data_len;
463 if (key_bytes_len < 16) {
464 return DOT11DECRYPT_RET_UNSUCCESS;
468 if ((key_bytes_len < GROUP_KEY_MIN_LEN) ||
469 (eapol_parsed->len < EAPOL_RSN_KEY_LEN) ||
470 (key_bytes_len > eapol_parsed->len - EAPOL_RSN_KEY_LEN)) {
471 return DOT11DECRYPT_RET_UNSUCCESS;
474 /* Encrypted key is in the information element field of the EAPOL key packet */
475 key_data = eapol_parsed->key_data;
477 DEBUG_DUMP("Encrypted Broadcast key:", key_data, key_bytes_len);
478 DEBUG_DUMP("KeyIV:", eapol_parsed->key_iv, 16);
479 DEBUG_DUMP("decryption_key:", decryption_key, decryption_key_len);
481 /* As we have no concept of the prior association request at this point, we need to deduce the */
482 /* group key cipher from the length of the key bytes. In WPA this is straightforward as the */
483 /* keybytes just contain the GTK, and the GTK is only in the group handshake, NOT the M3. */
484 /* In WPA2 its a little more tricky as the M3 keybytes contain an RSN_IE, but the group handshake */
485 /* does not. Also there are other (variable length) items in the keybytes which we need to account */
486 /* for to determine the true key length, and thus the group cipher. */
488 if (key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP){
489 /* TKIP key */
490 /* Per 802.11i, Draft 3.0 spec, section 8.5.2, p. 97, line 4-8, */
491 /* group key is decrypted using RC4. Concatenate the IV with the 16 byte EK (PTK+16) to get the decryption key */
492 guint8 new_key[32];
493 guint8 *data;
495 /* The WPA group key just contains the GTK bytes so deducing the type is straightforward */
496 /* Note - WPA M3 doesn't contain a group key so we'll only be here for the group handshake */
497 sa->wpa.key_ver = (key_bytes_len >=TKIP_GROUP_KEY_LEN)?DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP:DOT11DECRYPT_WPA_KEY_VER_AES_CCMP;
499 /* Build the full decryption key based on the IV and part of the pairwise key */
500 memcpy(new_key, eapol_parsed->key_iv, 16);
501 memcpy(new_key+16, decryption_key, 16);
502 DEBUG_DUMP("FullDecrKey:", new_key, 32);
503 data = Dot11DecryptRc4KeyData(new_key, 32, key_data, key_bytes_len);
504 if (!data) {
505 return DOT11DECRYPT_RET_UNSUCCESS;
507 memcpy(decrypted_data, data, key_bytes_len);
508 g_free(data);
509 } else {
510 /* Ideally AKM from EAPOL message 2 of 4 should be used to determine Key-wrap algoritm to use */
511 /* Though fortunately IEEE802.11-2016 Table 12-8 state that all AKMs use "NIST AES Key Wrap" */
512 /* algorithm so no AKM lookup is needed. */
514 /* Unwrap the key; the result is key_bytes_len in length */
515 if (AES_unwrap(decryption_key, decryption_key_len, key_data, key_bytes_len,
516 decrypted_data, &key_bytes_len)) {
517 return DOT11DECRYPT_RET_UNSUCCESS;
521 Dot11DecryptCopyKey(sa, key);
522 *decrypted_len = key_bytes_len;
523 return DOT11DECRYPT_RET_SUCCESS;
527 * @param ctx [IN] pointer to the current context
528 * @param id [IN] id of the association (composed by BSSID and MAC of
529 * the station)
530 * @return a pointer the the requested SA. NULL if it doesn't exist.
532 static PDOT11DECRYPT_SEC_ASSOCIATION
533 Dot11DecryptGetSa(
534 PDOT11DECRYPT_CONTEXT ctx,
535 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
537 return (DOT11DECRYPT_SEC_ASSOCIATION *)g_hash_table_lookup(ctx->sa_hash, id);
540 static PDOT11DECRYPT_SEC_ASSOCIATION
541 Dot11DecryptNewSa(const DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
543 PDOT11DECRYPT_SEC_ASSOCIATION sa = g_new0(DOT11DECRYPT_SEC_ASSOCIATION, 1);
544 if (sa != NULL) {
545 sa->saId = *id;
547 return sa;
550 static DOT11DECRYPT_SEC_ASSOCIATION *
551 Dot11DecryptPrependSa(
552 DOT11DECRYPT_SEC_ASSOCIATION *existing_sa,
553 DOT11DECRYPT_SEC_ASSOCIATION *new_sa)
555 DOT11DECRYPT_SEC_ASSOCIATION tmp_sa;
557 /* Add new SA first in list, but copy by value into existing record
558 * so that sa_hash need not be updated with new value */
559 tmp_sa = *existing_sa;
560 *existing_sa = *new_sa;
561 *new_sa = tmp_sa;
562 existing_sa->next = new_sa;
563 return existing_sa;
566 /* Add SA, keep existing (if any). Return pointer to newly inserted (first) SA */
567 static PDOT11DECRYPT_SEC_ASSOCIATION
568 Dot11DecryptAddSa(
569 PDOT11DECRYPT_CONTEXT ctx,
570 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
571 DOT11DECRYPT_SEC_ASSOCIATION *sa)
573 DOT11DECRYPT_SEC_ASSOCIATION *existing_sa = Dot11DecryptGetSa(ctx, id);
574 if (existing_sa != NULL) {
575 sa = Dot11DecryptPrependSa(existing_sa, sa);
576 } else {
577 void *key = g_memdup2(id, sizeof(DOT11DECRYPT_SEC_ASSOCIATION_ID));
578 g_hash_table_insert(ctx->sa_hash, key, sa);
580 return sa;
584 Dot11DecryptGetKCK(const PDOT11DECRYPT_KEY_ITEM key, const guint8 **kck)
586 if (!key || !kck) {
587 return 0;
589 *kck = DOT11DECRYPT_GET_KCK(key->KeyData.Wpa.Ptk, key->KeyData.Wpa.Akm);
590 return Dot11DecryptGetKckLen(key->KeyData.Wpa.Akm) / 8;
594 Dot11DecryptGetKEK(const PDOT11DECRYPT_KEY_ITEM key, const guint8 **kek)
596 if (!key || !kek) {
597 return 0;
599 *kek = DOT11DECRYPT_GET_KEK(key->KeyData.Wpa.Ptk, key->KeyData.Wpa.Akm);
600 return Dot11DecryptGetKekLen(key->KeyData.Wpa.Akm) / 8;
604 Dot11DecryptGetTK(const PDOT11DECRYPT_KEY_ITEM key, const guint8 **tk)
606 int len;
607 if (!key || !tk) {
608 return 0;
610 if (key->KeyType == DOT11DECRYPT_KEY_TYPE_TKIP) {
611 *tk = DOT11DECRYPT_GET_TK_TKIP(key->KeyData.Wpa.Ptk);
612 len = 16;
613 } else {
614 *tk = DOT11DECRYPT_GET_TK(key->KeyData.Wpa.Ptk, key->KeyData.Wpa.Akm);
615 len = Dot11DecryptGetTkLen(key->KeyData.Wpa.Cipher) / 8;
617 return len;
621 Dot11DecryptGetGTK(const PDOT11DECRYPT_KEY_ITEM key, const guint8 **gtk)
623 int len;
624 if (!key || !gtk) {
625 return 0;
628 /* GTK is stored in PTK at offset 32. See comment in Dot11DecryptCopyBroadcastKey */
629 *gtk = key->KeyData.Wpa.Ptk + 32;
630 if (key->KeyType == DOT11DECRYPT_KEY_TYPE_TKIP) {
631 len = 16;
632 } else {
633 len = Dot11DecryptGetTkLen(key->KeyData.Wpa.Cipher) / 8;
635 return len;
638 INT Dot11DecryptScanTdlsForKeys(
639 PDOT11DECRYPT_CONTEXT ctx,
640 const guint8 *data,
641 const guint tot_len)
643 guint offset = 0;
644 guint tot_len_left = tot_len;
645 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
646 PDOT11DECRYPT_SEC_ASSOCIATION sa;
647 const guint8 *initiator, *responder;
648 guint8 action;
649 guint status, offset_rsne = 0, offset_fte = 0, offset_link = 0, offset_timeout = 0;
650 DEBUG_PRINT_LINE("Authentication: TDLS Action Frame", DEBUG_LEVEL_3);
652 /* TDLS payload contains a TDLS Action field (802.11-2016 9.6.13) */
654 /* check if the packet is a TDLS response or confirm */
655 if (tot_len_left < 1) {
656 DEBUG_PRINT_LINE("Not EAPOL-Key", DEBUG_LEVEL_3);
657 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
659 action = data[offset];
660 if (action != 1 && action != 2) {
661 DEBUG_PRINT_LINE("Not Response nor confirm", DEBUG_LEVEL_3);
662 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
664 offset++;
665 tot_len_left--;
667 /* Check for SUCCESS (0) or SUCCESS_POWER_SAVE_MODE (85) Status Code */
668 if (tot_len_left < 5) {
669 DEBUG_PRINT_LINE("Not EAPOL-Key", DEBUG_LEVEL_3);
670 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
672 status=pntoh16(data + offset);
673 if (status != 0 && status != 85) {
674 DEBUG_PRINT_LINE("TDLS setup not successful", DEBUG_LEVEL_3);
675 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
678 /* skip Token + capabilities */
679 offset += 5;
681 /* search for RSN, Fast BSS Transition, Link Identifier and Timeout Interval IEs */
683 while(offset < (tot_len - 2)) {
684 guint8 element_id = data[offset];
685 guint8 length = data[offset + 1];
686 guint min_length = length;
687 switch (element_id) {
688 case 48: /* RSN (802.11-2016 9.4.2.35) */
689 offset_rsne = offset;
690 min_length = 1;
691 break;
692 case 55: /* FTE (802.11-2016 9.4.2.48) */
693 offset_fte = offset;
694 /* Plus variable length optional parameter(s) */
695 min_length = 2 + 16 + 32 + 32;
696 break;
697 case 56: /* Timeout Interval (802.11-2016 9.4.2.49) */
698 offset_timeout = offset;
699 min_length = 1 + 4;
700 break;
701 case 101: /* Link Identifier (802.11-2016 9.4.2.62) */
702 offset_link = offset;
703 min_length = 6 + 6 + 6;
704 break;
707 if (length < min_length || tot_len < offset + 2 + length) {
708 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
710 offset += 2 + length;
713 if (offset_rsne == 0 || offset_fte == 0 ||
714 offset_timeout == 0 || offset_link == 0)
716 DEBUG_PRINT_LINE("Cannot Find all necessary IEs", DEBUG_LEVEL_3);
717 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
720 DEBUG_PRINT_LINE("Found RSNE/Fast BSS/Timeout Interval/Link IEs", DEBUG_LEVEL_3);
722 /* Will create a Security Association between 2 STA. Need to get both MAC address */
723 initiator = &data[offset_link + 8];
724 responder = &data[offset_link + 14];
726 if (memcmp(initiator, responder, DOT11DECRYPT_MAC_LEN) < 0) {
727 memcpy(id.sta, initiator, DOT11DECRYPT_MAC_LEN);
728 memcpy(id.bssid, responder, DOT11DECRYPT_MAC_LEN);
729 } else {
730 memcpy(id.sta, responder, DOT11DECRYPT_MAC_LEN);
731 memcpy(id.bssid, initiator, DOT11DECRYPT_MAC_LEN);
734 /* Check if already derived this key */
735 sa = Dot11DecryptGetSa(ctx, &id);
736 PDOT11DECRYPT_SEC_ASSOCIATION iter_sa;
737 for (iter_sa = sa; iter_sa != NULL; iter_sa = iter_sa->next) {
738 if (iter_sa->validKey &&
739 memcmp(iter_sa->wpa.nonce, data + offset_fte + 52,
740 DOT11DECRYPT_WPA_NONCE_LEN) == 0)
742 /* Already have valid key for this SA, no need to redo key derivation */
743 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
746 /* We are opening a new session with the same two STA (previous sa will be kept if any) */
747 sa = Dot11DecryptNewSa(&id);
748 if (sa == NULL) {
749 return DOT11DECRYPT_RET_REQ_DATA;
751 if (Dot11DecryptTDLSDeriveKey(sa, data, offset_rsne, offset_fte,
752 offset_timeout, offset_link, action) == DOT11DECRYPT_RET_SUCCESS) {
753 Dot11DecryptAddSa(ctx, &id, sa);
754 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
756 g_free(sa);
757 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
760 static INT
761 Dot11DecryptCopyBroadcastKey(
762 PDOT11DECRYPT_CONTEXT ctx,
763 const guint8 *gtk, size_t gtk_len,
764 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
766 DOT11DECRYPT_SEC_ASSOCIATION_ID broadcast_id;
767 DOT11DECRYPT_SEC_ASSOCIATION *sa;
768 DOT11DECRYPT_SEC_ASSOCIATION *broadcast_sa;
770 if (!gtk || gtk_len == 0) {
771 DEBUG_PRINT_LINE("No broadcast key found", DEBUG_LEVEL_3);
772 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
774 if (gtk_len > DOT11DECRYPT_WPA_PTK_MAX_LEN - 32) {
775 DEBUG_PRINT_LINE("Broadcast key too large", DEBUG_LEVEL_3);
776 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
779 sa = Dot11DecryptGetSa(ctx, id);
780 if (sa == NULL) {
781 DEBUG_PRINT_LINE("No SA for BSSID found", DEBUG_LEVEL_3);
782 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
785 /* Broadcast SA for the current BSSID */
786 memcpy(broadcast_id.bssid, id->bssid, DOT11DECRYPT_MAC_LEN);
787 memcpy(broadcast_id.sta, broadcast_mac, DOT11DECRYPT_MAC_LEN);
789 broadcast_sa = Dot11DecryptNewSa(&broadcast_id);
790 if (broadcast_sa == NULL) {
791 DEBUG_PRINT_LINE("Failed to alloc broadcast sa", DEBUG_LEVEL_3);
792 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
795 /* Retrieve AKMS / cipher etc from handshake message 2 */
797 broadcast_sa->wpa.key_ver = sa->wpa.key_ver;
798 broadcast_sa->wpa.akm = sa->wpa.akm;
799 broadcast_sa->wpa.cipher = sa->wpa.tmp_group_cipher;
800 broadcast_sa->wpa.ptk_len = sa->wpa.ptk_len;
801 broadcast_sa->validKey = TRUE;
802 DEBUG_DUMP("Broadcast key:", gtk, gtk_len);
804 /* Since this is a GTK and its size is only 32 bytes (vs. the 64 byte size of a PTK),
805 * we fake it and put it in at a 32-byte offset so the Dot11DecryptRsnaMng() function
806 * will extract the right piece of the GTK for decryption. (The first 16 bytes of the
807 * GTK are used for decryption.) */
808 memset(broadcast_sa->wpa.ptk, 0, sizeof(broadcast_sa->wpa.ptk));
809 memcpy(broadcast_sa->wpa.ptk + 32, gtk, gtk_len);
810 Dot11DecryptAddSa(ctx, &broadcast_id, broadcast_sa);
811 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
814 static int
815 Dot11DecryptGroupHandshake(
816 PDOT11DECRYPT_CONTEXT ctx,
817 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
818 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
819 const guint tot_len)
822 if (GROUP_KEY_PAYLOAD_LEN_MIN > tot_len) {
823 DEBUG_PRINT_LINE("Message too short for Group Key", DEBUG_LEVEL_3);
824 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
826 if (eapol_parsed->msg_type != DOT11DECRYPT_HS_MSG_TYPE_GHS_1){
828 DEBUG_PRINT_LINE("Not Group handshake message 1", DEBUG_LEVEL_3);
829 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
831 return Dot11DecryptCopyBroadcastKey(ctx, eapol_parsed->gtk, eapol_parsed->gtk_len, id);
834 INT Dot11DecryptScanEapolForKeys(
835 PDOT11DECRYPT_CONTEXT ctx,
836 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
837 const guint8 *eapol_raw,
838 const guint tot_len,
839 const UCHAR bssid[DOT11DECRYPT_MAC_LEN],
840 const UCHAR sta[DOT11DECRYPT_MAC_LEN])
842 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
844 /* Callers provide these guarantees, so let's make them explicit. */
845 DISSECTOR_ASSERT(tot_len <= DOT11DECRYPT_EAPOL_MAX_LEN);
847 DEBUG_PRINT_LINE("Authentication: EAPOL packet", DEBUG_LEVEL_3);
849 /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */
850 if (/*eapol_parsed->key_type != 0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */
851 eapol_parsed->key_type != DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR && /* IEEE 802.11 Key Descriptor Type (WPA2) */
852 eapol_parsed->key_type != DOT11DECRYPT_RSN_WPA_KEY_DESCRIPTOR) /* 254 = RSN_KEY_DESCRIPTOR - WPA, */
854 DEBUG_PRINT_LINE("Not valid key descriptor type", DEBUG_LEVEL_3);
855 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
858 /* search for a cached Security Association for current BSSID and AP */
859 memcpy(id.bssid, bssid, DOT11DECRYPT_MAC_LEN);
860 memcpy(id.sta, sta, DOT11DECRYPT_MAC_LEN);
862 switch (eapol_parsed->msg_type) {
863 case DOT11DECRYPT_HS_MSG_TYPE_4WHS_1:
864 case DOT11DECRYPT_HS_MSG_TYPE_4WHS_2:
865 case DOT11DECRYPT_HS_MSG_TYPE_4WHS_3:
866 case DOT11DECRYPT_HS_MSG_TYPE_4WHS_4:
867 return Dot11DecryptRsna4WHandshake(ctx, eapol_parsed, eapol_raw,
868 &id, tot_len);
869 case DOT11DECRYPT_HS_MSG_TYPE_GHS_1:
870 return Dot11DecryptGroupHandshake(ctx, eapol_parsed, &id, tot_len);
871 case DOT11DECRYPT_HS_MSG_TYPE_INVALID:
872 default:
873 DEBUG_PRINT_LINE("Invalid message type", DEBUG_LEVEL_3);
874 break;
876 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
879 static int
880 Dot11DecryptGetNbrOfTkKeys(PDOT11DECRYPT_CONTEXT ctx)
882 int nbr = 0;
883 for (size_t i = 0; i < ctx->keys_nr; i++) {
884 if (ctx->keys[i].KeyType == DOT11DECRYPT_KEY_TYPE_TK) {
885 nbr++;
888 return nbr;
891 static int
892 Dot11DecryptUsingUserTk(
893 PDOT11DECRYPT_CONTEXT ctx,
894 UCHAR *decrypt_data,
895 guint mac_header_len,
896 guint *decrypt_len,
897 DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
898 DOT11DECRYPT_KEY_ITEM *used_key)
900 int ret = DOT11DECRYPT_RET_REQ_DATA;
901 DOT11DECRYPT_SEC_ASSOCIATION *sa = Dot11DecryptNewSa(id);
902 DOT11DECRYPT_KEY_ITEM *key;
903 if (sa == NULL) {
904 return ret;
907 sa->wpa.akm = 2;
908 sa->validKey = TRUE;
910 /* Try decrypt packet with all user TKs applicable ciphers */
911 for (size_t key_index = 0; key_index < ctx->keys_nr; key_index++) {
912 key = &ctx->keys[key_index];
913 if (key->KeyType != DOT11DECRYPT_KEY_TYPE_TK) {
914 continue;
916 int ciphers_to_try[4] = { 0 };
917 switch (key->Tk.Len) {
918 case DOT11DECRYPT_WEP_40_KEY_LEN:
919 case DOT11DECRYPT_WEP_104_KEY_LEN:
920 /* TBD implement */
921 continue;
922 case 256 / 8:
923 ciphers_to_try[0] = 9; /* GCMP-256 */
924 ciphers_to_try[1] = 10; /* CCMP-256 */
925 break;
926 case 128 / 8:
927 ciphers_to_try[0] = 4; /* CCMP-128 */
928 ciphers_to_try[1] = 8; /* GCMP-128 */
929 ciphers_to_try[2] = 2; /* TKIP */
930 break;
931 default:
932 continue;
935 sa->key = key;
937 for (int i = 0; ciphers_to_try[i] != 0; i++) {
938 sa->wpa.cipher = ciphers_to_try[i];
939 if (sa->wpa.cipher == 2 /* TKIP */) {
940 sa->wpa.key_ver = 1;
941 memcpy(DOT11DECRYPT_GET_TK_TKIP(sa->wpa.ptk),
942 key->Tk.Tk, key->Tk.Len);
943 } else {
944 sa->wpa.key_ver = 2;
945 sa->wpa.akm = 2;
946 memcpy(DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
947 key->Tk.Tk, key->Tk.Len);
949 sa->wpa.ptk_len = Dot11DecryptGetPtkLen(sa->wpa.akm, sa->wpa.cipher) / 8;
950 ret = Dot11DecryptRsnaMng(decrypt_data, mac_header_len, decrypt_len, used_key, sa);
951 if (ret == DOT11DECRYPT_RET_SUCCESS) {
952 /* Successfully decrypted using user TK. Add SA formed from user TK so that
953 * subsequent frames can be decrypted much faster using normal code path
954 * without trying each and every user TK entered.
956 Dot11DecryptAddSa(ctx, id, sa);
957 return ret;
961 g_free(sa);
962 return ret;
965 INT Dot11DecryptDecryptPacket(
966 PDOT11DECRYPT_CONTEXT ctx,
967 const guint8 *data,
968 const guint mac_header_len,
969 const guint tot_len,
970 UCHAR *decrypt_data,
971 guint *decrypt_len,
972 PDOT11DECRYPT_KEY_ITEM key)
974 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
975 DISSECTOR_ASSERT(decrypt_data);
976 DISSECTOR_ASSERT(decrypt_len);
978 #ifdef DOT11DECRYPT_DEBUG
979 #define MSGBUF_LEN 255
980 CHAR msgbuf[MSGBUF_LEN];
981 #endif
983 if (decrypt_len) {
984 *decrypt_len = 0;
986 if (ctx==NULL) {
987 DEBUG_PRINT_LINE("NULL context", DEBUG_LEVEL_5);
988 return DOT11DECRYPT_RET_REQ_DATA;
990 if (data==NULL || tot_len==0) {
991 DEBUG_PRINT_LINE("NULL data or length=0", DEBUG_LEVEL_5);
992 return DOT11DECRYPT_RET_REQ_DATA;
995 /* check correct packet size, to avoid wrong elaboration of encryption algorithms */
996 if (tot_len < (UINT)(mac_header_len+DOT11DECRYPT_CRYPTED_DATA_MINLEN)) {
997 DEBUG_PRINT_LINE("minimum length violated", DEBUG_LEVEL_5);
998 return DOT11DECRYPT_RET_WRONG_DATA_SIZE;
1001 /* Assume that the decrypt_data field is no more than this size. */
1002 if (tot_len > DOT11DECRYPT_MAX_CAPLEN) {
1003 DEBUG_PRINT_LINE("length too large", DEBUG_LEVEL_3);
1004 return DOT11DECRYPT_RET_UNSUCCESS;
1007 /* get STA/BSSID address */
1008 if (Dot11DecryptGetSaAddress((const DOT11DECRYPT_MAC_FRAME_ADDR4 *)(data), &id) != DOT11DECRYPT_RET_SUCCESS) {
1009 DEBUG_PRINT_LINE("STA/BSSID not found", DEBUG_LEVEL_5);
1010 return DOT11DECRYPT_RET_REQ_DATA;
1013 /* check if data is encrypted (use the WEP bit in the Frame Control field) */
1014 if (DOT11DECRYPT_WEP(data[1])==0) {
1015 return DOT11DECRYPT_RET_NO_DATA_ENCRYPTED;
1017 PDOT11DECRYPT_SEC_ASSOCIATION sa;
1019 /* create new header and data to modify */
1020 *decrypt_len = tot_len;
1021 memcpy(decrypt_data, data, *decrypt_len);
1023 /* encrypted data */
1024 DEBUG_PRINT_LINE("Encrypted data", DEBUG_LEVEL_3);
1026 /* check the Extension IV to distinguish between WEP encryption and WPA encryption */
1027 /* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */
1028 /* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */
1029 /* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */
1030 if (DOT11DECRYPT_EXTIV(data[mac_header_len + 3]) == 0) {
1031 DEBUG_PRINT_LINE("WEP encryption", DEBUG_LEVEL_3);
1032 return Dot11DecryptWepMng(ctx, decrypt_data, mac_header_len, decrypt_len, key, &id);
1033 } else {
1034 DEBUG_PRINT_LINE("TKIP or CCMP encryption", DEBUG_LEVEL_3);
1036 /* If the destination is a multicast address use the group key. This will not work if the AP is using
1037 more than one group key simultaneously. I've not seen this in practice, however.
1038 Usually an AP will rotate between the two key index values of 1 and 2 whenever
1039 it needs to change the group key to be used. */
1040 if (((const DOT11DECRYPT_MAC_FRAME_ADDR4 *)(data))->addr1[0] & 0x01) {
1041 DEBUG_PRINT_LINE("Broadcast/Multicast address. This is encrypted with a group key.", DEBUG_LEVEL_3);
1043 /* force STA address to broadcast MAC so we load the SA for the groupkey */
1044 memcpy(id.sta, broadcast_mac, DOT11DECRYPT_MAC_LEN);
1046 #ifdef DOT11DECRYPT_DEBUG
1047 g_snprintf(msgbuf, MSGBUF_LEN, "ST_MAC: %2X.%2X.%2X.%2X.%2X.%2X\t", id.sta[0],id.sta[1],id.sta[2],id.sta[3],id.sta[4],id.sta[5]);
1048 DEBUG_PRINT_LINE(msgbuf, DEBUG_LEVEL_3);
1049 #endif
1051 /* search for a cached Security Association for current BSSID and STA/broadcast MAC */
1052 int ret = DOT11DECRYPT_RET_REQ_DATA;
1053 sa = Dot11DecryptGetSa(ctx, &id);
1054 if (sa != NULL) {
1055 /* Decrypt the packet using the appropriate SA */
1056 ret = Dot11DecryptRsnaMng(decrypt_data, mac_header_len, decrypt_len, key, sa);
1058 if (ret != DOT11DECRYPT_RET_SUCCESS && Dot11DecryptGetNbrOfTkKeys(ctx) > 0) {
1059 /* Decryption with known SAs failed. Try decrypt with TK user entries */
1060 ret = Dot11DecryptUsingUserTk(ctx, decrypt_data, mac_header_len, decrypt_len, &id, key);
1062 return ret;
1064 return DOT11DECRYPT_RET_UNSUCCESS;
1067 INT Dot11DecryptSetKeys(
1068 PDOT11DECRYPT_CONTEXT ctx,
1069 DOT11DECRYPT_KEY_ITEM keys[],
1070 const size_t keys_nr)
1072 INT i;
1073 INT success;
1075 if (ctx==NULL || keys==NULL) {
1076 DEBUG_PRINT_LINE("NULL context or NULL keys array", DEBUG_LEVEL_3);
1077 return 0;
1080 if (keys_nr>DOT11DECRYPT_MAX_KEYS_NR) {
1081 DEBUG_PRINT_LINE("Keys number greater than maximum", DEBUG_LEVEL_3);
1082 return 0;
1085 /* clean key and SA collections before setting new ones */
1086 Dot11DecryptInitContext(ctx);
1088 /* check and insert keys */
1089 for (i=0, success=0; i<(INT)keys_nr; i++) {
1090 if (Dot11DecryptValidateKey(keys+i)==TRUE) {
1091 if (keys[i].KeyType==DOT11DECRYPT_KEY_TYPE_WPA_PWD) {
1092 DEBUG_PRINT_LINE("Set a WPA-PWD key", DEBUG_LEVEL_4);
1093 Dot11DecryptRsnaPwd2Psk(keys[i].UserPwd.Passphrase, keys[i].UserPwd.Ssid, keys[i].UserPwd.SsidLen, keys[i].KeyData.Wpa.Psk);
1094 keys[i].KeyData.Wpa.PskLen = DOT11DECRYPT_WPA_PWD_PSK_LEN;
1096 #ifdef DOT11DECRYPT_DEBUG
1097 else if (keys[i].KeyType==DOT11DECRYPT_KEY_TYPE_WPA_PMK) {
1098 DEBUG_PRINT_LINE("Set a WPA-PMK key", DEBUG_LEVEL_4);
1099 } else if (keys[i].KeyType==DOT11DECRYPT_KEY_TYPE_WEP) {
1100 DEBUG_PRINT_LINE("Set a WEP key", DEBUG_LEVEL_4);
1101 } else {
1102 DEBUG_PRINT_LINE("Set a key", DEBUG_LEVEL_4);
1104 #endif
1105 memcpy(&ctx->keys[success], &keys[i], sizeof(keys[i]));
1106 success++;
1110 ctx->keys_nr=success;
1111 return success;
1114 static void
1115 Dot11DecryptCleanKeys(
1116 PDOT11DECRYPT_CONTEXT ctx)
1118 if (ctx==NULL) {
1119 DEBUG_PRINT_LINE("NULL context", DEBUG_LEVEL_5);
1120 return;
1123 memset(ctx->keys, 0, sizeof(DOT11DECRYPT_KEY_ITEM) * DOT11DECRYPT_MAX_KEYS_NR);
1125 ctx->keys_nr=0;
1127 DEBUG_PRINT_LINE("Keys collection cleaned!", DEBUG_LEVEL_5);
1130 static void
1131 Dot11DecryptRecurseCleanSA(
1132 gpointer first_sa)
1134 DOT11DECRYPT_SEC_ASSOCIATION *sa = (DOT11DECRYPT_SEC_ASSOCIATION *)first_sa;
1135 if (sa != NULL) {
1136 Dot11DecryptRecurseCleanSA((gpointer)sa->next);
1137 g_free(sa);
1141 static void
1142 Dot11DecryptCleanSecAssoc(
1143 PDOT11DECRYPT_CONTEXT ctx)
1145 if (ctx->sa_hash != NULL) {
1146 g_hash_table_destroy(ctx->sa_hash);
1147 ctx->sa_hash = NULL;
1152 * XXX - This won't be reliable if a packet containing SSID "B" shows
1153 * up in the middle of a 4-way handshake for SSID "A".
1154 * We should probably use a small array or hash table to keep multiple
1155 * SSIDs.
1157 INT Dot11DecryptSetLastSSID(
1158 PDOT11DECRYPT_CONTEXT ctx,
1159 CHAR *pkt_ssid,
1160 size_t pkt_ssid_len)
1162 if (!ctx || !pkt_ssid || pkt_ssid_len < 1 || pkt_ssid_len > WPA_SSID_MAX_SIZE)
1163 return DOT11DECRYPT_RET_UNSUCCESS;
1165 memcpy(ctx->pkt_ssid, pkt_ssid, pkt_ssid_len);
1166 ctx->pkt_ssid_len = pkt_ssid_len;
1168 return DOT11DECRYPT_RET_SUCCESS;
1171 static guint
1172 Dot11DecryptSaHash(gconstpointer key)
1174 GBytes *bytes = g_bytes_new_static(key, sizeof(DOT11DECRYPT_SEC_ASSOCIATION_ID));
1175 guint hash = g_bytes_hash(bytes);
1176 g_bytes_unref(bytes);
1177 return hash;
1180 static gboolean
1181 Dot11DecryptIsSaIdEqual(gconstpointer key1, gconstpointer key2)
1183 return memcmp(key1, key2, sizeof(DOT11DECRYPT_SEC_ASSOCIATION_ID)) == 0;
1186 INT Dot11DecryptInitContext(
1187 PDOT11DECRYPT_CONTEXT ctx)
1189 if (ctx==NULL) {
1190 DEBUG_PRINT_LINE("NULL context", DEBUG_LEVEL_5);
1191 return DOT11DECRYPT_RET_UNSUCCESS;
1194 Dot11DecryptCleanKeys(ctx);
1195 Dot11DecryptCleanSecAssoc(ctx);
1197 ctx->pkt_ssid_len = 0;
1198 ctx->sa_hash = g_hash_table_new_full(Dot11DecryptSaHash, Dot11DecryptIsSaIdEqual,
1199 g_free, Dot11DecryptRecurseCleanSA);
1200 if (ctx->sa_hash == NULL) {
1201 return DOT11DECRYPT_RET_UNSUCCESS;
1204 DEBUG_PRINT_LINE("Context initialized!", DEBUG_LEVEL_5);
1205 return DOT11DECRYPT_RET_SUCCESS;
1208 INT Dot11DecryptDestroyContext(
1209 PDOT11DECRYPT_CONTEXT ctx)
1211 if (ctx==NULL) {
1212 DEBUG_PRINT_LINE("NULL context", DEBUG_LEVEL_5);
1213 return DOT11DECRYPT_RET_UNSUCCESS;
1216 Dot11DecryptCleanKeys(ctx);
1217 Dot11DecryptCleanSecAssoc(ctx);
1219 DEBUG_PRINT_LINE("Context destroyed!", DEBUG_LEVEL_5);
1220 return DOT11DECRYPT_RET_SUCCESS;
1223 #ifdef __cplusplus
1225 #endif
1227 /****************************************************************************/
1229 /****************************************************************************/
1230 /* Internal function definitions */
1232 #ifdef __cplusplus
1233 extern "C" {
1234 #endif
1236 static INT
1237 Dot11DecryptRsnaMng(
1238 UCHAR *decrypt_data,
1239 guint mac_header_len,
1240 guint *decrypt_len,
1241 PDOT11DECRYPT_KEY_ITEM key,
1242 DOT11DECRYPT_SEC_ASSOCIATION *sa)
1244 INT ret = 1;
1245 UCHAR *try_data;
1246 guint try_data_len = *decrypt_len;
1248 if (*decrypt_len == 0) {
1249 DEBUG_PRINT_LINE("Invalid decryption length", DEBUG_LEVEL_3);
1250 return DOT11DECRYPT_RET_UNSUCCESS;
1253 /* allocate a temp buffer for the decryption loop */
1254 try_data=(UCHAR *)g_malloc(try_data_len);
1256 /* start of loop added by GCS */
1257 for(/* sa */; sa != NULL ;sa=sa->next) {
1259 if (sa->validKey==FALSE) {
1260 DEBUG_PRINT_LINE("Key not yet valid", DEBUG_LEVEL_3);
1261 continue;
1264 /* copy the encrypted data into a temp buffer */
1265 memcpy(try_data, decrypt_data, *decrypt_len);
1267 if (sa->wpa.key_ver==1) {
1268 /* CCMP -> HMAC-MD5 is the EAPOL-Key MIC, RC4 is the EAPOL-Key encryption algorithm */
1269 DEBUG_PRINT_LINE("TKIP", DEBUG_LEVEL_3);
1270 DEBUG_DUMP("ptk", sa->wpa.ptk, 64);
1271 DEBUG_DUMP("ptk portion used", DOT11DECRYPT_GET_TK_TKIP(sa->wpa.ptk), 16);
1273 if (*decrypt_len < (guint)mac_header_len) {
1274 DEBUG_PRINT_LINE("Invalid decryption length", DEBUG_LEVEL_3);
1275 g_free(try_data);
1276 return DOT11DECRYPT_RET_UNSUCCESS;
1278 if (*decrypt_len < DOT11DECRYPT_TKIP_MICLEN + DOT11DECRYPT_WEP_ICV) {
1279 DEBUG_PRINT_LINE("Invalid decryption length", DEBUG_LEVEL_3);
1280 g_free(try_data);
1281 return DOT11DECRYPT_RET_UNSUCCESS;
1284 ret = Dot11DecryptTkipDecrypt(try_data + mac_header_len, *decrypt_len - mac_header_len,
1285 try_data + DOT11DECRYPT_TA_OFFSET,
1286 DOT11DECRYPT_GET_TK_TKIP(sa->wpa.ptk));
1287 if (ret) {
1288 DEBUG_PRINT_LINE("TKIP failed!", DEBUG_LEVEL_3);
1289 continue;
1292 DEBUG_PRINT_LINE("TKIP DECRYPTED!!!", DEBUG_LEVEL_3);
1293 /* remove MIC and ICV from the end of packet */
1294 *decrypt_len -= DOT11DECRYPT_TKIP_MICLEN + DOT11DECRYPT_WEP_ICV;
1295 break;
1296 } else if (sa->wpa.cipher == 8 || sa->wpa.cipher == 9) {
1297 DEBUG_PRINT_LINE("GCMP", DEBUG_LEVEL_3);
1299 if (*decrypt_len < DOT11DECRYPT_GCMP_TRAILER) {
1300 DEBUG_PRINT_LINE("Invalid decryption length", DEBUG_LEVEL_3);
1301 g_free(try_data);
1302 return DOT11DECRYPT_RET_UNSUCCESS;
1304 ret = Dot11DecryptGcmpDecrypt(try_data, mac_header_len, (INT)*decrypt_len,
1305 DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
1306 Dot11DecryptGetTkLen(sa->wpa.cipher) / 8);
1307 if (ret) {
1308 continue;
1310 DEBUG_PRINT_LINE("GCMP DECRYPTED!!!", DEBUG_LEVEL_3);
1311 /* remove MIC from the end of packet */
1312 *decrypt_len -= DOT11DECRYPT_GCMP_TRAILER;
1313 break;
1314 } else {
1315 /* AES-CCMP -> HMAC-SHA1-128 is the EAPOL-Key MIC, AES wep_key wrap is the EAPOL-Key encryption algorithm */
1316 DEBUG_PRINT_LINE("CCMP", DEBUG_LEVEL_3);
1318 guint trailer = sa->wpa.cipher != 10 ? DOT11DECRYPT_CCMP_TRAILER : DOT11DECRYPT_CCMP_256_TRAILER;
1319 if (*decrypt_len < trailer) {
1320 DEBUG_PRINT_LINE("Invalid decryption length", DEBUG_LEVEL_3);
1321 g_free(try_data);
1322 return DOT11DECRYPT_RET_UNSUCCESS;
1325 ret = Dot11DecryptCcmpDecrypt(try_data, mac_header_len, (INT)*decrypt_len,
1326 DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
1327 Dot11DecryptGetTkLen(sa->wpa.cipher) / 8,
1328 trailer);
1329 if (ret) {
1330 continue;
1332 DEBUG_PRINT_LINE("CCMP DECRYPTED!!!", DEBUG_LEVEL_3);
1333 /* remove MIC from the end of packet */
1334 *decrypt_len -= trailer;
1335 break;
1338 /* end of loop */
1340 /* none of the keys worked */
1341 if(sa == NULL) {
1342 g_free(try_data);
1343 return ret;
1346 if (*decrypt_len > try_data_len || *decrypt_len < 8) {
1347 DEBUG_PRINT_LINE("Invalid decryption length", DEBUG_LEVEL_3);
1348 g_free(try_data);
1349 return DOT11DECRYPT_RET_UNSUCCESS;
1352 /* remove protection bit */
1353 decrypt_data[1]&=0xBF;
1355 /* remove TKIP/CCMP header */
1356 *decrypt_len-=8;
1358 if (*decrypt_len < mac_header_len) {
1359 DEBUG_PRINT_LINE("Invalid decryption length < mac_header_len", DEBUG_LEVEL_3);
1360 g_free(try_data);
1361 return DOT11DECRYPT_RET_UNSUCCESS;
1364 /* copy the decrypted data into the decrypt buffer GCS*/
1365 memcpy(decrypt_data + mac_header_len, try_data + mac_header_len + 8,
1366 *decrypt_len - mac_header_len);
1367 g_free(try_data);
1369 Dot11DecryptCopyKey(sa, key);
1370 return DOT11DECRYPT_RET_SUCCESS;
1373 static INT
1374 Dot11DecryptWepMng(
1375 PDOT11DECRYPT_CONTEXT ctx,
1376 UCHAR *decrypt_data,
1377 guint mac_header_len,
1378 guint *decrypt_len,
1379 PDOT11DECRYPT_KEY_ITEM key,
1380 DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
1382 UCHAR wep_key[DOT11DECRYPT_WEP_KEY_MAXLEN+DOT11DECRYPT_WEP_IVLEN];
1383 size_t keylen;
1384 INT ret_value=1;
1385 INT key_index;
1386 DOT11DECRYPT_KEY_ITEM *tmp_key;
1387 UINT8 useCache=FALSE;
1388 UCHAR *try_data;
1389 DOT11DECRYPT_SEC_ASSOCIATION *sa;
1390 guint try_data_len = *decrypt_len;
1392 try_data = (UCHAR *)g_malloc(try_data_len);
1394 /* get the Security Association structure for the STA and AP */
1396 /* For WEP the sa is used only for caching. When no sa exists all user
1397 * entered WEP keys are checked and on successful packet decryption an
1398 * sa is formed caching the key used for decryption.
1400 sa = Dot11DecryptGetSa(ctx, id);
1401 if (sa != NULL && sa->key != NULL) {
1402 useCache = TRUE;
1405 for (key_index=0; key_index<(INT)ctx->keys_nr; key_index++) {
1406 /* use the cached one, or try all keys */
1407 if (!useCache) {
1408 tmp_key=&ctx->keys[key_index];
1409 } else {
1410 if (sa->key!=NULL && sa->key->KeyType==DOT11DECRYPT_KEY_TYPE_WEP) {
1411 DEBUG_PRINT_LINE("Try cached WEP key...", DEBUG_LEVEL_3);
1412 tmp_key=sa->key;
1413 } else {
1414 DEBUG_PRINT_LINE("Cached key is not valid, try another WEP key...", DEBUG_LEVEL_3);
1415 tmp_key=&ctx->keys[key_index];
1419 /* obviously, try only WEP keys... */
1420 if (tmp_key->KeyType==DOT11DECRYPT_KEY_TYPE_WEP) {
1421 DEBUG_PRINT_LINE("Try WEP key...", DEBUG_LEVEL_3);
1423 memset(wep_key, 0, sizeof(wep_key));
1424 memcpy(try_data, decrypt_data, *decrypt_len);
1426 /* Costruct the WEP seed: copy the IV in first 3 bytes and then the WEP key (refer to 802-11i-2004, 8.2.1.4.3, pag. 36) */
1427 memcpy(wep_key, try_data+mac_header_len, DOT11DECRYPT_WEP_IVLEN);
1428 keylen=tmp_key->KeyData.Wep.WepKeyLen;
1429 memcpy(wep_key+DOT11DECRYPT_WEP_IVLEN, tmp_key->KeyData.Wep.WepKey, keylen);
1431 ret_value=Dot11DecryptWepDecrypt(wep_key,
1432 keylen+DOT11DECRYPT_WEP_IVLEN,
1433 try_data + (mac_header_len+DOT11DECRYPT_WEP_IVLEN+DOT11DECRYPT_WEP_KIDLEN),
1434 *decrypt_len-(mac_header_len+DOT11DECRYPT_WEP_IVLEN+DOT11DECRYPT_WEP_KIDLEN+DOT11DECRYPT_CRC_LEN));
1436 if (ret_value == DOT11DECRYPT_RET_SUCCESS)
1437 memcpy(decrypt_data, try_data, *decrypt_len);
1440 if (!ret_value && tmp_key->KeyType==DOT11DECRYPT_KEY_TYPE_WEP) {
1441 /* the tried key is the correct one, cache it in the Security Association */
1443 /* Form an SA if one does not exist already */
1444 if (sa == NULL) {
1445 sa = Dot11DecryptNewSa(id);
1446 if (sa == NULL) {
1447 DEBUG_PRINT_LINE("Failed to alloc sa for WEP", DEBUG_LEVEL_3);
1448 ret_value = DOT11DECRYPT_RET_UNSUCCESS;
1449 break;
1451 sa = Dot11DecryptAddSa(ctx, id, sa);
1453 sa->key=tmp_key;
1455 if (key!=NULL) {
1456 memcpy(key, sa->key, sizeof(DOT11DECRYPT_KEY_ITEM));
1457 key->KeyType=DOT11DECRYPT_KEY_TYPE_WEP;
1460 break;
1461 } else {
1462 /* the cached key was not valid, try other keys */
1464 if (useCache==TRUE) {
1465 useCache=FALSE;
1466 key_index--;
1471 g_free(try_data);
1472 if (ret_value)
1473 return DOT11DECRYPT_RET_UNSUCCESS;
1475 DEBUG_PRINT_LINE("WEP DECRYPTED!!!", DEBUG_LEVEL_3);
1477 /* remove ICV (4bytes) from the end of packet */
1478 *decrypt_len-=4;
1480 if (*decrypt_len < 4) {
1481 DEBUG_PRINT_LINE("Decryption length too short", DEBUG_LEVEL_3);
1482 return DOT11DECRYPT_RET_UNSUCCESS;
1485 /* remove protection bit */
1486 decrypt_data[1]&=0xBF;
1488 /* remove IC header */
1489 *decrypt_len-=4;
1490 memmove(decrypt_data + mac_header_len,
1491 decrypt_data + mac_header_len + DOT11DECRYPT_WEP_IVLEN + DOT11DECRYPT_WEP_KIDLEN,
1492 *decrypt_len - mac_header_len);
1494 return DOT11DECRYPT_RET_SUCCESS;
1497 /* From IEEE 802.11-2016 Table 9-133—AKM suite selectors */
1498 static gboolean Dot11DecryptIsFtAkm(int akm)
1500 switch (akm) {
1501 case 3:
1502 case 4:
1503 case 9:
1504 case 13:
1505 return TRUE;
1507 return FALSE;
1510 /* Get xxkey portion of MSK */
1511 /* From IEEE 802.11-2016 12.7.1.7.3 PMK-R0 */
1512 static const guint8 *
1513 Dot11DecryptGetXXKeyFromMSK(const guint8 *msk, size_t msk_len,
1514 int akm, size_t *xxkey_len)
1516 if (!xxkey_len) {
1517 return NULL;
1519 switch (akm) {
1520 case 3:
1521 if (msk_len < 64) {
1522 return NULL;
1524 *xxkey_len = 32;
1525 return msk + 32;
1526 case 13:
1527 if (msk_len < 48) {
1528 return NULL;
1530 *xxkey_len = 48;
1531 return msk;
1532 default:
1533 return NULL;
1537 /* From IEEE 802.11-2016 12.7.1.3 Pairwise key hierarchy */
1538 static void
1539 Dot11DecryptDerivePmkFromMsk(const guint8 *msk, guint8 msk_len, int akm,
1540 guint8 *pmk, guint8 *pmk_len)
1542 if (!msk || !pmk || !pmk_len) {
1543 return;
1545 // When using AKM suite selector 00-0F-AC:12, the length of the PMK, PMK_bits,
1546 // shall be 384 bits. With all other AKM suite selectors, the length of the PMK,
1547 // PMK_bits, shall be 256 bits.
1548 if (akm == 12) {
1549 *pmk_len = 384 / 8;
1550 } else {
1551 *pmk_len = 256 / 8;
1553 if (msk_len + *pmk_len < msk_len) {
1554 *pmk_len = 0;
1555 return;
1557 // PMK = L(MSK, 0, PMK_bits).
1558 memcpy(pmk, msk, *pmk_len);
1561 static gboolean
1562 Dot11DecryptIsWpaKeyType(guint8 key_type)
1564 switch (key_type) {
1565 case DOT11DECRYPT_KEY_TYPE_WPA_PWD:
1566 case DOT11DECRYPT_KEY_TYPE_WPA_PSK:
1567 case DOT11DECRYPT_KEY_TYPE_WPA_PMK:
1568 case DOT11DECRYPT_KEY_TYPE_MSK:
1569 return TRUE;
1571 return FALSE;
1574 static gboolean
1575 Dot11DecryptIsPwdWildcardSsid(const PDOT11DECRYPT_CONTEXT ctx,
1576 const DOT11DECRYPT_KEY_ITEM *key_item)
1578 if (!ctx || !key_item || key_item->KeyType != DOT11DECRYPT_KEY_TYPE_WPA_PWD) {
1579 return FALSE;
1581 if (key_item->UserPwd.SsidLen == 0 && ctx->pkt_ssid_len > 0 &&
1582 ctx->pkt_ssid_len <= DOT11DECRYPT_WPA_SSID_MAX_LEN) {
1583 return TRUE;
1585 return FALSE;
1588 /* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */
1589 static INT
1590 Dot11DecryptRsna4WHandshake(
1591 PDOT11DECRYPT_CONTEXT ctx,
1592 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
1593 const guint8 *eapol_raw,
1594 DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
1595 const guint tot_len)
1597 DOT11DECRYPT_KEY_ITEM *tmp_key, *tmp_pkt_key, pkt_key;
1598 DOT11DECRYPT_SEC_ASSOCIATION *sa;
1599 INT key_index;
1600 INT ret = 1;
1601 UCHAR useCache=FALSE;
1602 UCHAR eapol[DOT11DECRYPT_EAPOL_MAX_LEN];
1604 if (eapol_parsed->len > DOT11DECRYPT_EAPOL_MAX_LEN ||
1605 eapol_parsed->key_len > DOT11DECRYPT_EAPOL_MAX_LEN ||
1606 eapol_parsed->key_data_len > DOT11DECRYPT_EAPOL_MAX_LEN) {
1607 DEBUG_PRINT_LINE("Too large EAPOL frame and/or key data", DEBUG_LEVEL_5);
1608 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1611 /* TODO timeouts? */
1613 /* TODO consider key-index */
1615 /* TODO considera Deauthentications */
1617 DEBUG_PRINT_LINE("4-way handshake...", DEBUG_LEVEL_5);
1619 /* manage 4-way handshake packets; this step completes the 802.1X authentication process (IEEE 802.11i-2004, pag. 85) */
1621 /* message 1: Authenticator->Supplicant (Sec=0, Mic=0, Ack=1, Inst=0, Key=1(pairwise), KeyRSC=0, Nonce=ANonce, MIC=0) */
1622 if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_1) {
1623 DEBUG_PRINT_LINE("4-way handshake message 1", DEBUG_LEVEL_3);
1625 /* On reception of Message 1, the Supplicant determines whether the Key Replay Counter field value has been */
1626 /* used before with the current PMKSA. If the Key Replay Counter field value is less than or equal to the current */
1627 /* local value, the Supplicant discards the message. */
1628 /* -> not checked, the Authenticator will be send another Message 1 (hopefully!) */
1630 /* save ANonce (from authenticator) to derive the PTK with the SNonce (from the 2 message) */
1631 if (!eapol_parsed->nonce) {
1632 DEBUG_PRINT_LINE("ANonce missing", DEBUG_LEVEL_5);
1633 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1636 sa = Dot11DecryptGetSa(ctx, id);
1637 if (sa == NULL || sa->handshake >= 2) {
1638 /* Either no SA exists or one exists but we're reauthenticating */
1639 sa = Dot11DecryptNewSa(id);
1640 if (sa == NULL) {
1641 DEBUG_PRINT_LINE("Failed to alloc broadcast sa", DEBUG_LEVEL_3);
1642 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1644 sa = Dot11DecryptAddSa(ctx, id, sa);
1646 memcpy(sa->wpa.nonce, eapol_parsed->nonce, 32);
1648 /* get the Key Descriptor Version (to select algorithm used in decryption -CCMP or TKIP-) */
1649 sa->wpa.key_ver = eapol_parsed->key_version;
1650 sa->handshake=1;
1651 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
1654 /* message 2|4: Supplicant->Authenticator (Sec=0|1, Mic=1, Ack=0, Inst=0, Key=1(pairwise), KeyRSC=0, Nonce=SNonce|0, MIC=MIC(KCK,EAPOL)) */
1655 if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_2) {
1656 DEBUG_PRINT_LINE("4-way handshake message 2", DEBUG_LEVEL_3);
1658 /* On reception of Message 2, the Authenticator checks that the key replay counter corresponds to the */
1659 /* outstanding Message 1. If not, it silently discards the message. */
1660 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, */
1661 /* the Authenticator silently discards Message 2. */
1662 /* -> not checked; the Supplicant will send another message 2 (hopefully!) */
1664 sa = Dot11DecryptGetSa(ctx, id);
1665 if (sa == NULL) {
1666 DEBUG_PRINT_LINE("No SA for BSSID found", DEBUG_LEVEL_3);
1667 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1669 if (!eapol_parsed->nonce) {
1670 DEBUG_PRINT_LINE("SNonce missing", DEBUG_LEVEL_5);
1671 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1673 if (sa->key != NULL) {
1674 useCache = TRUE;
1677 int akm = -1;
1678 int cipher = -1;
1679 int group_cipher = -1;
1680 guint8 ptk[DOT11DECRYPT_WPA_PTK_MAX_LEN];
1681 size_t ptk_len = 0;
1683 /* now you can derive the PTK */
1684 for (key_index=0; key_index<(INT)ctx->keys_nr || useCache; key_index++) {
1685 /* use the cached one, or try all keys */
1686 if (useCache && Dot11DecryptIsWpaKeyType(sa->key->KeyType)) {
1687 DEBUG_PRINT_LINE("Try cached WPA key...", DEBUG_LEVEL_3);
1688 tmp_key = sa->key;
1689 /* Step back loop counter as cached key is used instead */
1690 key_index--;
1691 } else {
1692 DEBUG_PRINT_LINE("Try WPA key...", DEBUG_LEVEL_3);
1693 tmp_key = &ctx->keys[key_index];
1695 useCache = FALSE;
1697 /* obviously, try only WPA keys... */
1698 if (!Dot11DecryptIsWpaKeyType(tmp_key->KeyType)) {
1699 continue;
1701 if (tmp_key->KeyType == DOT11DECRYPT_KEY_TYPE_WPA_PWD &&
1702 Dot11DecryptIsPwdWildcardSsid(ctx, tmp_key))
1704 /* We have a "wildcard" SSID. Use the one from the packet. */
1705 memcpy(&pkt_key, tmp_key, sizeof(pkt_key));
1706 memcpy(&pkt_key.UserPwd.Ssid, ctx->pkt_ssid, ctx->pkt_ssid_len);
1707 pkt_key.UserPwd.SsidLen = ctx->pkt_ssid_len;
1708 Dot11DecryptRsnaPwd2Psk(pkt_key.UserPwd.Passphrase, pkt_key.UserPwd.Ssid,
1709 pkt_key.UserPwd.SsidLen, pkt_key.KeyData.Wpa.Psk);
1710 tmp_pkt_key = &pkt_key;
1711 } else {
1712 tmp_pkt_key = tmp_key;
1714 memcpy(eapol, eapol_raw, tot_len);
1716 /* From IEEE 802.11-2016 12.7.2 EAPOL-Key frames */
1717 if (eapol_parsed->key_version == 0 || eapol_parsed->key_version == 3 ||
1718 eapol_parsed->key_version == DOT11DECRYPT_WPA_KEY_VER_AES_CCMP)
1720 /* PTK derivation is based on Authentication Key Management Type */
1721 akm = eapol_parsed->akm;
1722 cipher = eapol_parsed->cipher;
1723 group_cipher = eapol_parsed->group_cipher;
1724 } else if (eapol_parsed->key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP) {
1725 /* TKIP */
1726 akm = 2;
1727 cipher = 2;
1728 group_cipher = 2;
1729 } else {
1730 DEBUG_PRINT_LINE("EAPOL key_version not supported", DEBUG_LEVEL_3);
1731 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1734 if (tmp_pkt_key->KeyType == DOT11DECRYPT_KEY_TYPE_MSK) {
1735 Dot11DecryptDerivePmkFromMsk(tmp_pkt_key->Msk.Msk, tmp_pkt_key->Msk.Len, akm,
1736 tmp_pkt_key->KeyData.Wpa.Psk,
1737 &tmp_pkt_key->KeyData.Wpa.PskLen);
1740 if (Dot11DecryptIsFtAkm(akm)) {
1741 ret = Dot11DecryptFtDerivePtk(ctx, sa, tmp_pkt_key,
1742 eapol_parsed->mdid,
1743 eapol_parsed->nonce,
1744 eapol_parsed->fte.r0kh_id,
1745 eapol_parsed->fte.r0kh_id_len,
1746 eapol_parsed->fte.r1kh_id,
1747 eapol_parsed->fte.r1kh_id_len,
1748 akm, cipher, ptk, &ptk_len);
1749 } else {
1750 /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */
1751 ret = Dot11DecryptDerivePtk(sa, /* authenticator nonce, bssid, station mac */
1752 tmp_pkt_key->KeyData.Wpa.Psk, /* PSK == PMK */
1753 tmp_pkt_key->KeyData.Wpa.PskLen,
1754 eapol_parsed->nonce, /* supplicant nonce */
1755 eapol_parsed->key_version,
1756 akm, cipher, ptk, &ptk_len);
1758 if (ret) {
1759 /* Unsuccessful PTK derivation */
1760 continue;
1762 DEBUG_DUMP("TK", DOT11DECRYPT_GET_TK(ptk, akm), Dot11DecryptGetTkLen(cipher) / 8);
1764 ret = Dot11DecryptRsnaMicCheck(eapol_parsed,
1765 eapol, /* eapol frame (header also) */
1766 tot_len, /* eapol frame length */
1767 DOT11DECRYPT_GET_KCK(ptk, akm),
1768 eapol_parsed->key_version,
1769 akm);
1770 /* If the MIC is valid, the Authenticator checks that the RSN information element bit-wise matches */
1771 /* that from the (Re)Association Request message. */
1772 /* i) TODO If these are not exactly the same, the Authenticator uses MLME-DEAUTHENTICATE.request */
1773 /* primitive to terminate the association. */
1774 /* ii) If they do match bit-wise, the Authenticator constructs Message 3. */
1776 if (ret == DOT11DECRYPT_RET_SUCCESS) {
1777 /* the key is the correct one, cache it in the Security Association */
1778 sa->key = tmp_key;
1779 break;
1783 if (ret) {
1784 DEBUG_PRINT_LINE("handshake step failed", DEBUG_LEVEL_3);
1785 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1787 sa->wpa.key_ver = eapol_parsed->key_version;
1788 sa->wpa.akm = akm;
1789 sa->wpa.cipher = cipher;
1790 sa->wpa.tmp_group_cipher = group_cipher;
1791 memcpy(sa->wpa.ptk, ptk, ptk_len);
1792 sa->wpa.ptk_len = (INT)ptk_len;
1793 sa->handshake = 2;
1794 sa->validKey = TRUE; /* we can use the key to decode, even if we have not captured the other eapol packets */
1796 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
1799 /* message 3: Authenticator->Supplicant (Sec=1, Mic=1, Ack=1, Inst=0/1, Key=1(pairwise), KeyRSC=???, Nonce=ANonce, MIC=1) */
1800 if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_3) {
1801 DEBUG_PRINT_LINE("4-way handshake message 3", DEBUG_LEVEL_3);
1803 /* On reception of Message 3, the Supplicant silently discards the message if the Key Replay Counter field */
1804 /* value has already been used or if the ANonce value in Message 3 differs from the ANonce value in Message 1. */
1805 /* -> not checked, the Authenticator will send another message 3 (hopefully!) */
1807 /* TODO check page 88 (RNS) */
1809 /* If using WPA2 PSK, message 3 will contain an RSN for the group key (GTK KDE).
1810 In order to properly support decrypting WPA2-PSK packets, we need to parse this to get the group key. */
1811 if (eapol_parsed->key_type == DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR) {
1812 return Dot11DecryptCopyBroadcastKey(ctx, eapol_parsed->gtk, eapol_parsed->gtk_len, id);
1816 /* message 4 */
1817 if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_4) {
1818 /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
1820 /* TODO check MIC and Replay Counter */
1821 /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */
1822 /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */
1823 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */
1824 /* Authenticator silently discards Message 4. */
1826 DEBUG_PRINT_LINE("4-way handshake message 4", DEBUG_LEVEL_3);
1827 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
1829 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1832 /* Refer to IEEE 802.11-2016 Chapeter 13.8 FT authentication sequence */
1833 #if GCRYPT_VERSION_NUMBER >= 0x010600
1834 gint
1835 Dot11DecryptScanFtAssocForKeys(
1836 const PDOT11DECRYPT_CONTEXT ctx,
1837 const PDOT11DECRYPT_ASSOC_PARSED assoc_parsed,
1838 guint8 *decrypted_gtk, size_t *decrypted_len,
1839 DOT11DECRYPT_KEY_ITEM* used_key)
1841 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
1843 DEBUG_PRINT_LINE("(Re)Association packet", DEBUG_LEVEL_3);
1845 if (!ctx || !assoc_parsed) {
1846 DEBUG_PRINT_LINE("Invalid input parameters", DEBUG_LEVEL_3);
1847 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1849 if (!Dot11DecryptIsFtAkm(assoc_parsed->akm)) {
1850 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1852 if (!assoc_parsed->fte.anonce || !assoc_parsed->fte.snonce) {
1853 DEBUG_PRINT_LINE("ANonce or SNonce missing", DEBUG_LEVEL_5);
1854 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1857 switch (assoc_parsed->frame_subtype) {
1858 case DOT11DECRYPT_SUBTYPE_ASSOC_REQ:
1859 case DOT11DECRYPT_SUBTYPE_REASSOC_REQ:
1860 memcpy(id.sta, assoc_parsed->sa, DOT11DECRYPT_MAC_LEN);
1861 break;
1862 case DOT11DECRYPT_SUBTYPE_ASSOC_RESP:
1863 case DOT11DECRYPT_SUBTYPE_REASSOC_RESP:
1864 memcpy(id.sta, assoc_parsed->da, DOT11DECRYPT_MAC_LEN);
1865 break;
1866 default:
1867 DEBUG_PRINT_LINE("Invalid frame subtype", DEBUG_LEVEL_3);
1868 return DOT11DECRYPT_RET_UNSUCCESS;
1870 memcpy(id.bssid, assoc_parsed->bssid, DOT11DECRYPT_MAC_LEN);
1872 DOT11DECRYPT_KEY_ITEM *tmp_key, *tmp_pkt_key, pkt_key;
1873 DOT11DECRYPT_SEC_ASSOCIATION *sa;
1874 size_t key_index;
1875 guint ret = 1;
1876 gboolean useCache = FALSE;
1878 sa = Dot11DecryptNewSa(&id);
1879 if (sa == NULL) {
1880 DEBUG_PRINT_LINE("Failed to alloc sa", DEBUG_LEVEL_3);
1881 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1884 memcpy(sa->wpa.nonce, assoc_parsed->fte.anonce, 32);
1886 if (sa->key != NULL) {
1887 useCache = TRUE;
1890 guint8 ptk[DOT11DECRYPT_WPA_PTK_MAX_LEN];
1891 size_t ptk_len;
1893 /* now you can derive the PTK */
1894 for (key_index = 0; key_index < ctx->keys_nr || useCache; key_index++) {
1895 /* use the cached one, or try all keys */
1896 if (useCache && Dot11DecryptIsWpaKeyType(sa->key->KeyType)) {
1897 DEBUG_PRINT_LINE("Try cached WPA key...", DEBUG_LEVEL_3);
1898 tmp_key = sa->key;
1899 /* Step back loop counter as cached key is used instead */
1900 key_index--;
1901 } else {
1902 DEBUG_PRINT_LINE("Try WPA key...", DEBUG_LEVEL_3);
1903 tmp_key = &ctx->keys[key_index];
1905 useCache = FALSE;
1907 /* Try only WPA keys... */
1908 if (!Dot11DecryptIsWpaKeyType(tmp_key->KeyType)) {
1909 continue;
1911 if (tmp_key->KeyType == DOT11DECRYPT_KEY_TYPE_WPA_PWD &&
1912 Dot11DecryptIsPwdWildcardSsid(ctx, tmp_key))
1914 /* We have a "wildcard" SSID. Use the one from the packet. */
1915 memcpy(&pkt_key, tmp_key, sizeof(pkt_key));
1916 memcpy(&pkt_key.UserPwd.Ssid, ctx->pkt_ssid, ctx->pkt_ssid_len);
1917 pkt_key.UserPwd.SsidLen = ctx->pkt_ssid_len;
1918 Dot11DecryptRsnaPwd2Psk(pkt_key.UserPwd.Passphrase, pkt_key.UserPwd.Ssid,
1919 pkt_key.UserPwd.SsidLen, pkt_key.KeyData.Wpa.Psk);
1920 tmp_pkt_key = &pkt_key;
1921 } else {
1922 tmp_pkt_key = tmp_key;
1925 if (tmp_pkt_key->KeyType == DOT11DECRYPT_KEY_TYPE_MSK) {
1926 Dot11DecryptDerivePmkFromMsk(tmp_pkt_key->Msk.Msk, tmp_pkt_key->Msk.Len,
1927 assoc_parsed->akm,
1928 tmp_pkt_key->KeyData.Wpa.Psk,
1929 &tmp_pkt_key->KeyData.Wpa.PskLen);
1932 ret = Dot11DecryptFtDerivePtk(ctx, sa, tmp_pkt_key,
1933 assoc_parsed->mdid,
1934 assoc_parsed->fte.snonce,
1935 assoc_parsed->fte.r0kh_id,
1936 assoc_parsed->fte.r0kh_id_len,
1937 assoc_parsed->fte.r1kh_id,
1938 assoc_parsed->fte.r1kh_id_len,
1939 assoc_parsed->akm, assoc_parsed->cipher,
1940 ptk, &ptk_len);
1941 if (ret != DOT11DECRYPT_RET_SUCCESS) {
1942 continue;
1944 DEBUG_DUMP("TK", DOT11DECRYPT_GET_TK(ptk, assoc_parsed->akm),
1945 Dot11DecryptGetTkLen(assoc_parsed->cipher) / 8);
1947 ret = Dot11DecryptFtMicCheck(assoc_parsed,
1948 DOT11DECRYPT_GET_KCK(ptk, assoc_parsed->akm),
1949 Dot11DecryptGetKckLen(assoc_parsed->akm) / 8);
1950 if (ret == DOT11DECRYPT_RET_SUCCESS) {
1951 /* the key is the correct one, cache it in the Security Association */
1952 sa->key = tmp_key;
1953 break;
1957 if (ret) {
1958 DEBUG_PRINT_LINE("handshake step failed", DEBUG_LEVEL_3);
1959 g_free(sa);
1960 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1962 sa = Dot11DecryptAddSa(ctx, &id, sa);
1964 sa->wpa.key_ver = 0; /* Determine key type from akms and cipher*/
1965 sa->wpa.akm = assoc_parsed->akm;
1966 sa->wpa.cipher = assoc_parsed->cipher;
1967 sa->wpa.tmp_group_cipher = assoc_parsed->group_cipher;
1968 memcpy(sa->wpa.ptk, ptk, ptk_len);
1969 sa->wpa.ptk_len = (INT)ptk_len;
1970 sa->validKey = TRUE;
1972 if (assoc_parsed->gtk && assoc_parsed->gtk_len - 8 <= DOT11DECRYPT_WPA_PTK_MAX_LEN - 32) {
1973 guint8 decrypted_key[DOT11DECRYPT_WPA_PTK_MAX_LEN - 32];
1974 guint16 decrypted_key_len;
1975 if (AES_unwrap(DOT11DECRYPT_GET_KEK(sa->wpa.ptk, sa->wpa.akm),
1976 Dot11DecryptGetKekLen(sa->wpa.akm) / 8,
1977 assoc_parsed->gtk, assoc_parsed->gtk_len,
1978 decrypted_key, &decrypted_key_len)) {
1979 return DOT11DECRYPT_RET_UNSUCCESS;
1981 if (decrypted_key_len != assoc_parsed->gtk_subelem_key_len) {
1982 DEBUG_PRINT_LINE("Unexpected GTK length", DEBUG_LEVEL_3);
1983 return DOT11DECRYPT_RET_UNSUCCESS;
1985 Dot11DecryptCopyBroadcastKey(ctx, decrypted_key, decrypted_key_len, &id);
1986 *decrypted_len = decrypted_key_len;
1987 memcpy(decrypted_gtk, decrypted_key, decrypted_key_len);
1989 Dot11DecryptCopyKey(sa, used_key);
1990 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
1992 #else
1993 gint
1994 Dot11DecryptScanFtAssocForKeys(
1995 const PDOT11DECRYPT_CONTEXT ctx _U_,
1996 const PDOT11DECRYPT_ASSOC_PARSED assoc_parsed _U_,
1997 guint8 *decrypted_gtk _U_, size_t *decrypted_len _U_,
1998 DOT11DECRYPT_KEY_ITEM* used_item _U_)
2000 DEBUG_PRINT_LINE("Skipped Dot11DecryptScanFtAssocForKeys, libgcrypt >= 1.6", DEBUG_LEVEL_3);
2001 return DOT11DECRYPT_RET_UNSUCCESS;
2003 #endif
2005 /* From IEEE 802.11-2016 Table 12-8 Integrity and key-wrap algorithms */
2006 static int
2007 Dot11DecryptGetIntegrityAlgoFromAkm(int akm, int *algo, gboolean *hmac)
2009 int res = 0;
2010 switch (akm) {
2011 case 1:
2012 case 2:
2013 *algo = GCRY_MD_SHA1;
2014 *hmac = TRUE;
2015 break;
2016 #if GCRYPT_VERSION_NUMBER >= 0x010600
2017 case 3:
2018 case 4:
2019 case 5:
2020 case 6:
2021 case 7:
2022 case 8:
2023 case 9:
2024 case 10:
2025 *algo = GCRY_MAC_CMAC_AES;
2026 *hmac = FALSE;
2027 break;
2028 #endif
2029 case 11:
2030 case 18:
2031 *algo = GCRY_MD_SHA256;
2032 *hmac = TRUE;
2033 break;
2034 case 12:
2035 case 13:
2036 *algo = GCRY_MD_SHA384;
2037 *hmac = TRUE;
2038 break;
2039 default:
2040 /* Unknown / Not supported yet */
2041 res = -1;
2042 break;
2044 return res;
2047 static INT
2048 Dot11DecryptRsnaMicCheck(
2049 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
2050 UCHAR *eapol,
2051 USHORT eapol_len,
2052 UCHAR *KCK,
2053 USHORT key_ver,
2054 int akm)
2056 guint8 *mic = eapol_parsed->mic;
2057 guint16 mic_len = eapol_parsed->mic_len;
2058 guint16 kck_len = Dot11DecryptGetKckLen(akm) / 8;
2059 /* MIC 16 or 24 bytes, though HMAC-SHA256 / SHA384 algos need 32 / 48 bytes buffer */
2060 UCHAR c_mic[48] = { 0 };
2061 int algo = -1;
2062 gboolean hmac = TRUE;
2064 if (!mic || mic_len > DOT11DECRYPT_WPA_MICKEY_MAX_LEN) {
2065 DEBUG_PRINT_LINE("Not a valid mic", DEBUG_LEVEL_3);
2066 return DOT11DECRYPT_RET_UNSUCCESS;
2069 /* set to 0 the MIC in the EAPOL packet (to calculate the MIC) */
2070 memset(eapol + DOT11DECRYPT_WPA_MICKEY_OFFSET + 4, 0, mic_len);
2072 if (key_ver==DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP) {
2073 /* use HMAC-MD5 for the EAPOL-Key MIC */
2074 algo = GCRY_MD_MD5;
2075 hmac = TRUE;
2076 } else if (key_ver==DOT11DECRYPT_WPA_KEY_VER_AES_CCMP) {
2077 /* use HMAC-SHA1-128 for the EAPOL-Key MIC */
2078 algo = GCRY_MD_SHA1;
2079 hmac = TRUE;
2080 } else {
2081 /* Mic check algoritm determined by AKM type */
2082 if (Dot11DecryptGetIntegrityAlgoFromAkm(akm, &algo, &hmac)) {
2083 DEBUG_PRINT_LINE("Unknown Mic check algo", DEBUG_LEVEL_3);
2084 return DOT11DECRYPT_RET_UNSUCCESS;
2087 if (hmac) {
2088 if (ws_hmac_buffer(algo, c_mic, eapol, eapol_len, KCK, kck_len)) {
2089 DEBUG_PRINT_LINE("HMAC_BUFFER", DEBUG_LEVEL_3);
2090 return DOT11DECRYPT_RET_UNSUCCESS;
2092 } else {
2093 if (ws_cmac_buffer(algo, c_mic, eapol, eapol_len, KCK, kck_len)) {
2094 DEBUG_PRINT_LINE("HMAC_BUFFER", DEBUG_LEVEL_3);
2095 return DOT11DECRYPT_RET_UNSUCCESS;
2099 /* compare calculated MIC with the Key MIC and return result (0 means success) */
2100 DEBUG_DUMP("mic", mic, mic_len);
2101 DEBUG_DUMP("c_mic", c_mic, mic_len);
2102 return memcmp(mic, c_mic, mic_len);
2105 /* IEEE 802.11-2016 Chapter 13.8.4 FT authentication sequence: contents of third message
2106 * IEEE 802.11-2016 Chapter 13.8.5 FT authentication sequence: contents of fourth message
2107 * The MIC shall be calculated on the concatenation of the following data, in the order given here:
2108 * —
2109 * — FTO’s MAC address (6 octets)
2110 * — Target AP’s MAC address (6 octets)
2111 * If third message:
2112 * — Transaction sequence number (1 octet), which shall be set to the value 5 if this is a
2113 * Reassociation Request frame and, otherwise, set to the value 3
2114 * If fourth message:
2115 * — Transaction sequence number (1 octet), which shall be set to the value 6 if this is a
2116 * Reassociation Response frame or, otherwise, set to the value 4
2118 * — RSNE
2119 * — MDE
2120 * — FTE, with the MIC field of the FTE set to 0
2121 * — Contents of the RIC-Response (if present)
2123 #if GCRYPT_VERSION_NUMBER >= 0x010600
2124 static gint
2125 Dot11DecryptFtMicCheck(
2126 const PDOT11DECRYPT_ASSOC_PARSED assoc_parsed,
2127 const guint8 *kck,
2128 size_t kck_len)
2130 guint8 *sta;
2131 guint8 seq_num;
2132 guint8 fte_len;
2133 guint16 mic_len;
2134 guint8 zeros[16] = { 0 };
2135 gcry_mac_hd_t handle;
2137 fte_len = assoc_parsed->fte_tag[1] + 2;
2138 if (fte_len < 20) {
2139 DEBUG_PRINT_LINE("FTE too short", DEBUG_LEVEL_3);
2140 return DOT11DECRYPT_RET_UNSUCCESS;
2143 switch (assoc_parsed->frame_subtype) {
2144 case DOT11DECRYPT_SUBTYPE_ASSOC_REQ:
2145 sta = assoc_parsed->sa;
2146 seq_num = 3;
2147 break;
2148 case DOT11DECRYPT_SUBTYPE_ASSOC_RESP:
2149 sta = assoc_parsed->da;
2150 seq_num = 4;
2151 break;
2152 case DOT11DECRYPT_SUBTYPE_REASSOC_REQ:
2153 sta = assoc_parsed->sa;
2154 seq_num = 5;
2155 break;
2156 case DOT11DECRYPT_SUBTYPE_REASSOC_RESP:
2157 sta = assoc_parsed->da;
2158 seq_num = 6;
2159 break;
2160 default:
2161 return DOT11DECRYPT_RET_UNSUCCESS;
2164 if (gcry_mac_open(&handle, GCRY_MAC_CMAC_AES, 0, NULL)) {
2165 DEBUG_PRINT_LINE("gcry_mac_open failed", DEBUG_LEVEL_3);
2166 return DOT11DECRYPT_RET_UNSUCCESS;
2168 if (gcry_mac_setkey(handle, kck, kck_len)) {
2169 DEBUG_PRINT_LINE("gcry_mac_setkey failed", DEBUG_LEVEL_3);
2170 gcry_mac_close(handle);
2171 return DOT11DECRYPT_RET_UNSUCCESS;
2173 gcry_mac_write(handle, sta, DOT11DECRYPT_MAC_LEN);
2174 gcry_mac_write(handle, assoc_parsed->bssid, DOT11DECRYPT_MAC_LEN);
2176 gcry_mac_write(handle, &seq_num, 1);
2178 gcry_mac_write(handle, assoc_parsed->rsne_tag, assoc_parsed->rsne_tag[1] + 2);
2179 gcry_mac_write(handle, assoc_parsed->mde_tag, assoc_parsed->mde_tag[1] + 2);
2181 mic_len = assoc_parsed->fte.mic_len;
2182 gcry_mac_write(handle, assoc_parsed->fte_tag, 4);
2183 gcry_mac_write(handle, zeros, mic_len); /* MIC zeroed */
2184 gcry_mac_write(handle, assoc_parsed->fte_tag + 4 + mic_len, fte_len - 4 - mic_len);
2186 if (assoc_parsed->rde_tag) {
2187 gcry_mac_write(handle, assoc_parsed->rde_tag, assoc_parsed->rde_tag[1] + 2);
2190 if (gcry_mac_verify(handle, assoc_parsed->fte.mic, mic_len) != 0) {
2191 DEBUG_DUMP("MIC", assoc_parsed->fte.mic, mic_len);
2192 DEBUG_PRINT_LINE("MIC verification failed", DEBUG_LEVEL_3);
2193 gcry_mac_close(handle);
2194 return DOT11DECRYPT_RET_UNSUCCESS;
2196 DEBUG_DUMP("MIC", assoc_parsed->fte.mic, mic_len);
2197 gcry_mac_close(handle);
2198 return DOT11DECRYPT_RET_SUCCESS;
2200 #endif
2202 static INT
2203 Dot11DecryptValidateKey(
2204 PDOT11DECRYPT_KEY_ITEM key)
2206 size_t len;
2207 UCHAR ret=TRUE;
2209 if (key==NULL) {
2210 DEBUG_PRINT_LINE("NULL key", DEBUG_LEVEL_5);
2211 return FALSE;
2214 switch (key->KeyType) {
2215 case DOT11DECRYPT_KEY_TYPE_WEP:
2216 /* check key size limits */
2217 len=key->KeyData.Wep.WepKeyLen;
2218 if (len<DOT11DECRYPT_WEP_KEY_MINLEN || len>DOT11DECRYPT_WEP_KEY_MAXLEN) {
2219 DEBUG_PRINT_LINE("WEP key: key length not accepted", DEBUG_LEVEL_5);
2220 ret=FALSE;
2222 break;
2224 case DOT11DECRYPT_KEY_TYPE_WEP_40:
2225 /* set the standard length and use a generic WEP key type */
2226 key->KeyData.Wep.WepKeyLen=DOT11DECRYPT_WEP_40_KEY_LEN;
2227 key->KeyType=DOT11DECRYPT_KEY_TYPE_WEP;
2228 break;
2230 case DOT11DECRYPT_KEY_TYPE_WEP_104:
2231 /* set the standard length and use a generic WEP key type */
2232 key->KeyData.Wep.WepKeyLen=DOT11DECRYPT_WEP_104_KEY_LEN;
2233 key->KeyType=DOT11DECRYPT_KEY_TYPE_WEP;
2234 break;
2236 case DOT11DECRYPT_KEY_TYPE_WPA_PWD:
2237 /* check passphrase and SSID size limits */
2238 len=strlen(key->UserPwd.Passphrase);
2239 if (len<DOT11DECRYPT_WPA_PASSPHRASE_MIN_LEN || len>DOT11DECRYPT_WPA_PASSPHRASE_MAX_LEN) {
2240 DEBUG_PRINT_LINE("WPA-PWD key: passphrase length not accepted", DEBUG_LEVEL_5);
2241 ret=FALSE;
2244 len=key->UserPwd.SsidLen;
2245 if (len>DOT11DECRYPT_WPA_SSID_MAX_LEN) {
2246 DEBUG_PRINT_LINE("WPA-PWD key: ssid length not accepted", DEBUG_LEVEL_5);
2247 ret=FALSE;
2250 break;
2252 case DOT11DECRYPT_KEY_TYPE_WPA_PSK:
2253 break;
2255 case DOT11DECRYPT_KEY_TYPE_TK:
2256 break;
2258 case DOT11DECRYPT_KEY_TYPE_MSK:
2259 break;
2261 default:
2262 ret=FALSE;
2264 return ret;
2267 static INT
2268 Dot11DecryptGetSaAddress(
2269 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame,
2270 DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
2272 #ifdef DOT11DECRYPT_DEBUG
2273 #define MSGBUF_LEN 255
2274 CHAR msgbuf[MSGBUF_LEN];
2275 #endif
2277 if ((DOT11DECRYPT_TYPE(frame->fc[0])==DOT11DECRYPT_TYPE_DATA) &&
2278 (DOT11DECRYPT_DS_BITS(frame->fc[1]) == 0) &&
2279 (memcmp(frame->addr2, frame->addr3, DOT11DECRYPT_MAC_LEN) != 0) &&
2280 (memcmp(frame->addr1, frame->addr3, DOT11DECRYPT_MAC_LEN) != 0)) {
2281 /* DATA frame with fromDS=0 ToDS=0 and neither RA or SA is BSSID
2282 => TDLS traffic. Use highest MAC address for bssid */
2283 if (memcmp(frame->addr1, frame->addr2, DOT11DECRYPT_MAC_LEN) < 0) {
2284 memcpy(id->sta, frame->addr1, DOT11DECRYPT_MAC_LEN);
2285 memcpy(id->bssid, frame->addr2, DOT11DECRYPT_MAC_LEN);
2286 } else {
2287 memcpy(id->sta, frame->addr2, DOT11DECRYPT_MAC_LEN);
2288 memcpy(id->bssid, frame->addr1, DOT11DECRYPT_MAC_LEN);
2290 } else {
2291 const UCHAR *addr;
2293 /* Normal Case: SA between STA and AP */
2294 if ((addr = Dot11DecryptGetBssidAddress(frame)) != NULL) {
2295 memcpy(id->bssid, addr, DOT11DECRYPT_MAC_LEN);
2296 } else {
2297 return DOT11DECRYPT_RET_UNSUCCESS;
2300 if ((addr = Dot11DecryptGetStaAddress(frame)) != NULL) {
2301 memcpy(id->sta, addr, DOT11DECRYPT_MAC_LEN);
2302 } else {
2303 return DOT11DECRYPT_RET_UNSUCCESS;
2307 #ifdef DOT11DECRYPT_DEBUG
2308 g_snprintf(msgbuf, MSGBUF_LEN, "BSSID_MAC: %02X.%02X.%02X.%02X.%02X.%02X\t",
2309 id->bssid[0],id->bssid[1],id->bssid[2],id->bssid[3],id->bssid[4],id->bssid[5]);
2310 DEBUG_PRINT_LINE(msgbuf, DEBUG_LEVEL_3);
2311 g_snprintf(msgbuf, MSGBUF_LEN, "STA_MAC: %02X.%02X.%02X.%02X.%02X.%02X\t",
2312 id->sta[0],id->sta[1],id->sta[2],id->sta[3],id->sta[4],id->sta[5]);
2313 DEBUG_PRINT_LINE(msgbuf, DEBUG_LEVEL_3);
2314 #endif
2316 return DOT11DECRYPT_RET_SUCCESS;
2320 * Dot11DecryptGetBssidAddress() and Dot11DecryptGetBssidAddress() are used for
2321 * key caching. In each case, it's more important to return a value than
2322 * to return a _correct_ value, so we fudge addresses in some cases, e.g.
2323 * the BSSID in bridged connections.
2324 * FromDS ToDS Sta BSSID
2325 * 0 0 addr1/2 addr3
2326 * 0 1 addr2 addr1
2327 * 1 0 addr1 addr2
2328 * 1 1 addr2 addr1
2331 static const UCHAR *
2332 Dot11DecryptGetStaAddress(
2333 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame)
2335 switch(DOT11DECRYPT_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
2336 case 0:
2337 if (memcmp(frame->addr2, frame->addr3, DOT11DECRYPT_MAC_LEN) == 0)
2338 return frame->addr1;
2339 else
2340 return frame->addr2;
2341 case 1:
2342 return frame->addr2;
2343 case 2:
2344 return frame->addr1;
2345 case 3:
2346 if (memcmp(frame->addr1, frame->addr2, DOT11DECRYPT_MAC_LEN) < 0)
2347 return frame->addr1;
2348 else
2349 return frame->addr2;
2351 default:
2352 return NULL;
2356 static const UCHAR *
2357 Dot11DecryptGetBssidAddress(
2358 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame)
2360 switch(DOT11DECRYPT_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
2361 case 0:
2362 return frame->addr3;
2363 case 1:
2364 return frame->addr1;
2365 case 2:
2366 return frame->addr2;
2367 case 3:
2368 if (memcmp(frame->addr1, frame->addr2, DOT11DECRYPT_MAC_LEN) > 0)
2369 return frame->addr1;
2370 else
2371 return frame->addr2;
2373 default:
2374 return NULL;
2378 /* From IEEE 802.11-2016 Table 9-131 Cipher suite selectors and
2379 * Table 12-4 Cipher suite key lengths */
2380 static int Dot11DecryptGetTkLen(int cipher)
2382 switch (cipher) {
2383 case 1: return 40; /* WEP-40 */
2384 case 2: return 256; /* TKIP */
2385 case 3: return -1; /* Reserved */
2386 case 4: return 128; /* CCMP-128 */
2387 case 5: return 104; /* WEP-104 */
2388 case 6: return 128; /* BIP-CMAC-128 */
2389 case 7: return -1; /* Group addressed traffic not allowed */
2390 case 8: return 128; /* GCMP-128 */
2391 case 9: return 256; /* GCMP-256 */
2392 case 10: return 256; /* CCMP-256 */
2393 case 11: return 128; /* BIP-GMAC-128 */
2394 case 12: return 256; /* BIP-GMAC-256 */
2395 case 13: return 256; /* BIP-CMAC-256 */
2396 default:
2397 DEBUG_PRINT_LINE("Unknown cipher", DEBUG_LEVEL_3);
2398 return -1;
2402 /* From IEEE 802.11-2016 Table 12-8 Integrity and key-wrap algorithms */
2403 static int Dot11DecryptGetKckLen(int akm)
2405 switch (akm) {
2406 case 1: return 128;
2407 case 2: return 128;
2408 case 3: return 128;
2409 case 4: return 128;
2410 case 5: return 128;
2411 case 6: return 128;
2412 case 8: return 128;
2413 case 9: return 128;
2414 case 11: return 128;
2415 case 12: return 192;
2416 case 13: return 192;
2417 case 18: return 128;
2418 default:
2419 /* Unknown / Not supported */
2420 DEBUG_PRINT_LINE("Unknown akm", DEBUG_LEVEL_3);
2421 return -1;
2425 /* From IEEE 802.11-2016 Table 12-8 Integrity and key-wrap algorithms */
2426 static int Dot11DecryptGetKekLen(int akm)
2428 switch (akm) {
2429 case 1: return 128;
2430 case 2: return 128;
2431 case 3: return 128;
2432 case 4: return 128;
2433 case 5: return 128;
2434 case 6: return 128;
2435 case 8: return 128;
2436 case 9: return 128;
2437 case 11: return 128;
2438 case 12: return 256;
2439 case 13: return 256;
2440 case 18: return 128;
2441 default:
2442 /* Unknown / Not supported */
2443 DEBUG_PRINT_LINE("Unknown akm", DEBUG_LEVEL_3);
2444 return -1;
2448 /* From IEEE 802.11-2016 9.4.2.25.3 AKM suites and
2449 * Table 12-8 Integrity and key-wrap algorithms */
2450 static int Dot11DecryptGetPtkLen(int akm, int cipher)
2452 int kck_len = Dot11DecryptGetKckLen(akm);
2453 int kek_len = Dot11DecryptGetKekLen(akm);
2454 int tk_len = Dot11DecryptGetTkLen(cipher);
2456 if (kck_len == -1 || kek_len == -1 || tk_len == -1) {
2457 DEBUG_PRINT_LINE("Invalid PTK len", DEBUG_LEVEL_3);
2458 return -1;
2460 return kck_len + kek_len + tk_len;
2463 /* From IEEE 802.11-2016 12.7.1.2 PRF and Table 9-133 AKM suite selectors */
2464 static int
2465 Dot11DecryptGetDeriveFuncFromAkm(int akm)
2467 int func = -1;
2468 switch (akm) {
2469 case 1:
2470 case 2:
2471 func = DOT11DECRYPT_DERIVE_USING_PRF;
2472 break;
2473 case 3:
2474 case 4:
2475 case 5:
2476 case 6:
2477 case 7:
2478 case 8:
2479 case 9:
2480 case 10:
2481 case 11:
2482 case 12:
2483 case 13:
2484 case 18:
2485 func = DOT11DECRYPT_DERIVE_USING_KDF;
2486 break;
2487 default:
2488 /* Unknown / Not supported yet */
2489 break;
2491 return func;
2494 /* From IEEE 802.11-2016 12.7.1.2 PRF and Table 9-133 AKM suite selectors */
2495 static int
2496 Dot11DecryptGetHashAlgoFromAkm(int akm)
2498 int algo = -1;
2499 switch (akm) {
2500 case 1:
2501 case 2:
2502 algo = GCRY_MD_SHA1;
2503 break;
2504 case 3:
2505 case 4:
2506 case 5:
2507 case 6:
2508 case 7:
2509 case 8:
2510 case 9:
2511 case 10:
2512 case 11:
2513 case 18:
2514 algo = GCRY_MD_SHA256;
2515 break;
2516 case 12:
2517 case 13:
2518 algo = GCRY_MD_SHA384;
2519 break;
2520 default:
2521 /* Unknown / Not supported yet */
2522 break;
2524 return algo;
2527 /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */
2528 /** From IEEE 802.11-2016 12.7.1.3 Pairwise key hierarchy:
2529 * PRF-Length(PMK, “Pairwise key expansion”,
2530 * Min(AA, SPA) || Max(AA, SPA) ||
2531 * Min(ANonce, SNonce) || Max(ANonce, SNonce))
2533 static guint8
2534 Dot11DecryptDerivePtk(
2535 const DOT11DECRYPT_SEC_ASSOCIATION *sa,
2536 const UCHAR *pmk,
2537 size_t pmk_len,
2538 const UCHAR snonce[32],
2539 int key_version,
2540 int akm,
2541 int cipher,
2542 guint8 *ptk, size_t *ptk_len)
2544 #ifdef DOT11DECRYPT_DEBUG
2545 #define MSGBUF_LEN 255
2546 CHAR msgbuf[MSGBUF_LEN];
2547 #endif
2548 int algo = -1;
2549 int ptk_len_bits = -1;
2550 int derive_func;
2552 if (!sa || !pmk || !snonce || !ptk || !ptk_len) {
2553 DEBUG_PRINT_LINE("Invalid input for PTK derivation", DEBUG_LEVEL_3);
2554 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2557 if (key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP) {
2558 /* TKIP */
2559 ptk_len_bits = 512;
2560 derive_func = DOT11DECRYPT_DERIVE_USING_PRF;
2561 algo = GCRY_MD_SHA1;
2562 } else {
2563 /* From IEEE 802.11-2016 Table 12-8 Integrity and key-wrap algorithms */
2564 ptk_len_bits = Dot11DecryptGetPtkLen(akm, cipher);
2565 algo = Dot11DecryptGetHashAlgoFromAkm(akm);
2566 derive_func = Dot11DecryptGetDeriveFuncFromAkm(akm);
2568 #ifdef DOT11DECRYPT_DEBUG
2569 g_snprintf(msgbuf, MSGBUF_LEN, "ptk_len_bits: %d, algo: %d, cipher: %d", ptk_len_bits, algo, cipher);
2570 DEBUG_PRINT_LINE(msgbuf, DEBUG_LEVEL_3);
2571 #endif /* DOT11DECRYPT_DEBUG */
2574 if (ptk_len_bits == -1 || algo == -1) {
2575 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2577 *ptk_len = ptk_len_bits / 8;
2579 static const char *const label = "Pairwise key expansion";
2580 guint8 context[DOT11DECRYPT_MAC_LEN * 2 + 32 * 2];
2581 int offset = 0;
2583 /* Min(AA, SPA) || Max(AA, SPA) */
2584 if (memcmp(sa->saId.sta, sa->saId.bssid, DOT11DECRYPT_MAC_LEN) < 0)
2586 memcpy(context + offset, sa->saId.sta, DOT11DECRYPT_MAC_LEN);
2587 offset += DOT11DECRYPT_MAC_LEN;
2588 memcpy(context + offset, sa->saId.bssid, DOT11DECRYPT_MAC_LEN);
2589 offset += DOT11DECRYPT_MAC_LEN;
2591 else
2593 memcpy(context + offset, sa->saId.bssid, DOT11DECRYPT_MAC_LEN);
2594 offset += DOT11DECRYPT_MAC_LEN;
2595 memcpy(context + offset, sa->saId.sta, DOT11DECRYPT_MAC_LEN);
2596 offset += DOT11DECRYPT_MAC_LEN;
2599 /* Min(ANonce, SNonce) || Max(ANonce, SNonce) */
2600 if (memcmp(snonce, sa->wpa.nonce, 32) < 0 )
2602 memcpy(context + offset, snonce, 32);
2603 offset += 32;
2604 memcpy(context + offset, sa->wpa.nonce, 32);
2605 offset += 32;
2607 else
2609 memcpy(context + offset, sa->wpa.nonce, 32);
2610 offset += 32;
2611 memcpy(context + offset, snonce, 32);
2612 offset += 32;
2614 if (derive_func == DOT11DECRYPT_DERIVE_USING_PRF) {
2615 dot11decrypt_prf(pmk, pmk_len, label, context, offset, algo,
2616 ptk, *ptk_len);
2617 } else {
2618 dot11decrypt_kdf(pmk, pmk_len, label, context, offset, algo,
2619 ptk, *ptk_len);
2621 DEBUG_DUMP("PTK", ptk, *ptk_len);
2622 return DOT11DECRYPT_RET_SUCCESS;
2626 * For Fast BSS Transition AKMS derive PTK from sa, selected key and various information in
2627 * eapol key frame.
2628 * From IEEE 802.11-2016 12.7.1.7.1
2630 static guint8
2631 Dot11DecryptFtDerivePtk(
2632 const PDOT11DECRYPT_CONTEXT ctx,
2633 const DOT11DECRYPT_SEC_ASSOCIATION *sa,
2634 const PDOT11DECRYPT_KEY_ITEM key,
2635 const guint8 mdid[2],
2636 const guint8 *snonce,
2637 const guint8 *r0kh_id, size_t r0kh_id_len,
2638 const guint8 *r1kh_id, size_t r1kh_id_len _U_,
2639 int akm, int cipher,
2640 guint8 *ptk, size_t *ptk_len)
2642 int hash_algo = Dot11DecryptGetHashAlgoFromAkm(akm);
2643 guint8 pmk_r0[DOT11DECRYPT_WPA_PMK_MAX_LEN];
2644 guint8 pmk_r1[DOT11DECRYPT_WPA_PMK_MAX_LEN];
2645 guint8 pmk_r0_name[16];
2646 guint8 pmk_r1_name[16];
2647 guint8 ptk_name[16];
2648 size_t pmk_r0_len;
2649 size_t pmk_r1_len;
2650 const guint8 *xxkey = NULL;
2651 size_t xxkey_len;
2652 int ptk_len_bits;
2654 if (!sa || !key || !mdid || !snonce || !r0kh_id || !r1kh_id || !ptk || !ptk_len) {
2655 DEBUG_PRINT_LINE("Invalid input for FT PTK derivation", DEBUG_LEVEL_3);
2656 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2658 ptk_len_bits = Dot11DecryptGetPtkLen(akm, cipher);
2659 if (ptk_len_bits == -1) {
2660 DEBUG_PRINT_LINE("Invalid akm or cipher", DEBUG_LEVEL_3);
2661 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2663 *ptk_len = ptk_len_bits / 8;
2665 if (key->KeyType == DOT11DECRYPT_KEY_TYPE_MSK) {
2666 xxkey = Dot11DecryptGetXXKeyFromMSK(key->Msk.Msk,
2667 key->Msk.Len,
2668 akm,
2669 &xxkey_len);
2671 if (!xxkey && key->KeyData.Wpa.PskLen > 0) {
2672 xxkey = key->KeyData.Wpa.Psk;
2673 xxkey_len = key->KeyData.Wpa.PskLen;
2675 if (!xxkey) {
2676 DEBUG_PRINT_LINE("no xxkey. Skipping", DEBUG_LEVEL_3);
2677 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2679 dot11decrypt_derive_pmk_r0(xxkey, xxkey_len,
2680 ctx->pkt_ssid, ctx->pkt_ssid_len,
2681 mdid,
2682 r0kh_id, r0kh_id_len,
2683 sa->saId.sta, hash_algo,
2684 pmk_r0, &pmk_r0_len, pmk_r0_name);
2685 DEBUG_DUMP("PMK-R0", pmk_r0, (int)pmk_r0_len);
2686 DEBUG_DUMP("PMKR0Name", pmk_r0_name, 16);
2688 dot11decrypt_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name,
2689 r1kh_id, sa->saId.sta, hash_algo,
2690 pmk_r1, &pmk_r1_len, pmk_r1_name);
2691 DEBUG_DUMP("PMK-R1", pmk_r1, (int)pmk_r1_len);
2692 DEBUG_DUMP("PMKR1Name", pmk_r1_name, 16);
2694 dot11decrypt_derive_ft_ptk(pmk_r1, pmk_r1_len, pmk_r1_name,
2695 snonce, sa->wpa.nonce,
2696 sa->saId.bssid, sa->saId.sta, hash_algo,
2697 ptk, *ptk_len, ptk_name);
2698 DEBUG_DUMP("PTK", ptk, (int)*ptk_len);
2699 return DOT11DECRYPT_RET_SUCCESS;
2702 #define MAX_SSID_LENGTH 32 /* maximum SSID length */
2704 static INT
2705 Dot11DecryptRsnaPwd2PskStep(
2706 const guint8 *ppBytes,
2707 const guint ppLength,
2708 const CHAR *ssid,
2709 const size_t ssidLength,
2710 const INT iterations,
2711 const INT count,
2712 UCHAR *output)
2714 UCHAR digest[MAX_SSID_LENGTH+4] = { 0 }; /* SSID plus 4 bytes of count */
2715 INT i, j;
2717 if (ssidLength > MAX_SSID_LENGTH) {
2718 /* This "should not happen" */
2719 return DOT11DECRYPT_RET_UNSUCCESS;
2722 /* U1 = PRF(P, S || INT(i)) */
2723 memcpy(digest, ssid, ssidLength);
2724 digest[ssidLength] = (UCHAR)((count>>24) & 0xff);
2725 digest[ssidLength+1] = (UCHAR)((count>>16) & 0xff);
2726 digest[ssidLength+2] = (UCHAR)((count>>8) & 0xff);
2727 digest[ssidLength+3] = (UCHAR)(count & 0xff);
2728 if (ws_hmac_buffer(GCRY_MD_SHA1, digest, digest, (guint32) ssidLength + 4, ppBytes, ppLength)) {
2729 return DOT11DECRYPT_RET_UNSUCCESS;
2732 /* output = U1 */
2733 memcpy(output, digest, 20);
2734 for (i = 1; i < iterations; i++) {
2735 /* Un = PRF(P, Un-1) */
2736 if (ws_hmac_buffer(GCRY_MD_SHA1, digest, digest, HASH_SHA1_LENGTH, ppBytes, ppLength)) {
2737 return DOT11DECRYPT_RET_UNSUCCESS;
2740 /* output = output xor Un */
2741 for (j = 0; j < 20; j++) {
2742 output[j] ^= digest[j];
2746 return DOT11DECRYPT_RET_SUCCESS;
2749 static INT
2750 Dot11DecryptRsnaPwd2Psk(
2751 const CHAR *passphrase,
2752 const CHAR *ssid,
2753 const size_t ssidLength,
2754 UCHAR *output)
2756 UCHAR m_output[40] = { 0 };
2757 GByteArray *pp_ba = g_byte_array_new();
2759 if (!uri_str_to_bytes(passphrase, pp_ba)) {
2760 g_byte_array_free(pp_ba, TRUE);
2761 return 0;
2764 Dot11DecryptRsnaPwd2PskStep(pp_ba->data, pp_ba->len, ssid, ssidLength, 4096, 1, m_output);
2765 Dot11DecryptRsnaPwd2PskStep(pp_ba->data, pp_ba->len, ssid, ssidLength, 4096, 2, &m_output[20]);
2767 memcpy(output, m_output, DOT11DECRYPT_WPA_PWD_PSK_LEN);
2768 g_byte_array_free(pp_ba, TRUE);
2770 return 0;
2774 * Returns the decryption_key_t struct given a string describing the key.
2775 * Returns NULL if the input_string cannot be parsed.
2777 decryption_key_t*
2778 parse_key_string(gchar* input_string, guint8 key_type)
2780 gchar *key, *tmp_str;
2781 gchar *ssid;
2783 GString *key_string = NULL;
2784 GByteArray *ssid_ba = NULL, *key_ba;
2785 gboolean res;
2787 gchar **tokens;
2788 guint n = 0;
2789 decryption_key_t *dk;
2791 if(input_string == NULL)
2792 return NULL;
2795 * Parse the input_string. WEP and WPA will be just a string
2796 * of hexadecimal characters (if key is wrong, null will be
2797 * returned...).
2798 * WPA-PWD should be in the form
2799 * <key data>[:<ssid>]
2802 switch(key_type)
2804 case DOT11DECRYPT_KEY_TYPE_WEP:
2805 case DOT11DECRYPT_KEY_TYPE_WEP_40:
2806 case DOT11DECRYPT_KEY_TYPE_WEP_104:
2808 key_ba = g_byte_array_new();
2809 res = hex_str_to_bytes(input_string, key_ba, FALSE);
2811 if (res && key_ba->len > 0) {
2812 /* Key is correct! It was probably an 'old style' WEP key */
2813 /* Create the decryption_key_t structure, fill it and return it*/
2814 dk = g_new(decryption_key_t, 1);
2816 dk->type = DOT11DECRYPT_KEY_TYPE_WEP;
2817 /* XXX - The current key handling code in the GUI requires
2818 * no separators and lower case */
2819 tmp_str = bytes_to_str(NULL, key_ba->data, key_ba->len);
2820 dk->key = g_string_new(tmp_str);
2821 g_string_ascii_down(dk->key);
2822 dk->bits = key_ba->len * 8;
2823 dk->ssid = NULL;
2825 wmem_free(NULL, tmp_str);
2826 g_byte_array_free(key_ba, TRUE);
2827 return dk;
2830 /* Key doesn't work */
2831 g_byte_array_free(key_ba, TRUE);
2832 return NULL;
2834 case DOT11DECRYPT_KEY_TYPE_WPA_PWD:
2836 tokens = g_strsplit(input_string,":",0);
2838 /* Tokens is a null termiated array of strings ... */
2839 while(tokens[n] != NULL)
2840 n++;
2842 if(n < 1)
2844 /* Free the array of strings */
2845 g_strfreev(tokens);
2846 return NULL;
2850 * The first token is the key
2852 key = g_strdup(tokens[0]);
2854 ssid = NULL;
2855 /* Maybe there is a second token (an ssid, if everything else is ok) */
2856 if(n >= 2)
2858 ssid = g_strdup(tokens[1]);
2861 /* Create a new string */
2862 key_string = g_string_new(key);
2863 ssid_ba = NULL;
2865 /* Two (or more) tokens mean that the user entered a WPA-PWD key ... */
2866 if( ((key_string->len) > WPA_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WPA_KEY_MIN_CHAR_SIZE))
2868 g_string_free(key_string, TRUE);
2870 g_free(key);
2871 g_free(ssid);
2873 /* Free the array of strings */
2874 g_strfreev(tokens);
2875 return NULL;
2878 if(ssid != NULL) /* more than two tokens found, means that the user specified the ssid */
2880 ssid_ba = g_byte_array_new();
2881 if (! uri_str_to_bytes(ssid, ssid_ba)) {
2882 g_string_free(key_string, TRUE);
2883 g_byte_array_free(ssid_ba, TRUE);
2884 g_free(key);
2885 g_free(ssid);
2886 /* Free the array of strings */
2887 g_strfreev(tokens);
2888 return NULL;
2891 if(ssid_ba->len > WPA_SSID_MAX_CHAR_SIZE)
2893 g_string_free(key_string, TRUE);
2894 g_byte_array_free(ssid_ba, TRUE);
2896 g_free(key);
2897 g_free(ssid);
2899 /* Free the array of strings */
2900 g_strfreev(tokens);
2901 return NULL;
2905 /* Key was correct!!! Create the new decryption_key_t ... */
2906 dk = g_new(decryption_key_t, 1);
2908 dk->type = DOT11DECRYPT_KEY_TYPE_WPA_PWD;
2909 dk->key = g_string_new(key);
2910 dk->bits = 256; /* This is the length of the array pf bytes that will be generated using key+ssid ...*/
2911 dk->ssid = byte_array_dup(ssid_ba); /* NULL if ssid_ba is NULL */
2913 g_string_free(key_string, TRUE);
2914 if (ssid_ba != NULL)
2915 g_byte_array_free(ssid_ba, TRUE);
2917 g_free(key);
2918 g_free(ssid);
2920 /* Free the array of strings */
2921 g_strfreev(tokens);
2922 return dk;
2924 case DOT11DECRYPT_KEY_TYPE_WPA_PSK:
2926 key_ba = g_byte_array_new();
2927 res = hex_str_to_bytes(input_string, key_ba, FALSE);
2929 /* Two tokens means that the user should have entered a WPA-BIN key ... */
2930 if(!res || (key_ba->len != DOT11DECRYPT_WPA_PWD_PSK_LEN &&
2931 key_ba->len != DOT11DECRYPT_WPA_PMK_MAX_LEN))
2933 g_byte_array_free(key_ba, TRUE);
2935 /* No ssid has been created ... */
2936 return NULL;
2939 /* Key was correct!!! Create the new decryption_key_t ... */
2940 dk = g_new(decryption_key_t, 1);
2942 dk->type = DOT11DECRYPT_KEY_TYPE_WPA_PSK;
2943 dk->key = g_string_new(input_string);
2944 dk->bits = (guint) dk->key->len * 4;
2945 dk->ssid = NULL;
2947 g_byte_array_free(key_ba, TRUE);
2948 return dk;
2950 case DOT11DECRYPT_KEY_TYPE_TK:
2952 /* From IEEE 802.11-2016 Table 12-4 Cipher suite key lengths */
2953 static const guint8 allowed_key_lengths[] = {
2954 // TBD 40 / 8, /* WEP-40 */
2955 // TBD 104 / 8, /* WEP-104 */
2956 256 / 8, /* TKIP, GCMP-256, CCMP-256 */
2957 128 / 8, /* CCMP-128, GCMP-128 */
2959 gboolean key_length_ok = FALSE;
2961 key_ba = g_byte_array_new();
2962 res = hex_str_to_bytes(input_string, key_ba, FALSE);
2964 for (size_t i = 0; i < sizeof(allowed_key_lengths); i++) {
2965 if (key_ba->len == allowed_key_lengths[i]) {
2966 key_length_ok = TRUE;
2967 break;
2970 if (!res || !key_length_ok) {
2971 g_byte_array_free(key_ba, TRUE);
2972 return NULL;
2974 dk = g_new(decryption_key_t, 1);
2975 dk->type = DOT11DECRYPT_KEY_TYPE_TK;
2976 dk->key = g_string_new(input_string);
2977 dk->bits = (guint) dk->key->len * 4;
2978 dk->ssid = NULL;
2980 g_byte_array_free(key_ba, TRUE);
2981 return dk;
2983 case DOT11DECRYPT_KEY_TYPE_MSK:
2985 key_ba = g_byte_array_new();
2986 res = hex_str_to_bytes(input_string, key_ba, FALSE);
2988 if (!res || key_ba->len < DOT11DECRYPT_MSK_MIN_LEN ||
2989 key_ba->len > DOT11DECRYPT_MSK_MAX_LEN)
2991 g_byte_array_free(key_ba, TRUE);
2992 return NULL;
2994 dk = g_new(decryption_key_t, 1);
2995 dk->type = DOT11DECRYPT_KEY_TYPE_MSK;
2996 dk->key = g_string_new(input_string);
2997 dk->bits = (guint)dk->key->len * 4;
2998 dk->ssid = NULL;
2999 g_byte_array_free(key_ba, TRUE);
3000 return dk;
3004 /* Type not supported */
3005 return NULL;
3008 void
3009 free_key_string(decryption_key_t *dk)
3011 if (dk->key)
3012 g_string_free(dk->key, TRUE);
3013 if (dk->ssid)
3014 g_byte_array_free(dk->ssid, TRUE);
3015 g_free(dk);
3018 static INT
3019 Dot11DecryptTDLSDeriveKey(
3020 PDOT11DECRYPT_SEC_ASSOCIATION sa,
3021 const guint8 *data,
3022 #if GCRYPT_VERSION_NUMBER >= 0x010600
3023 guint offset_rsne,
3024 #else
3025 guint offset_rsne _U_,
3026 #endif
3027 guint offset_fte,
3028 #if GCRYPT_VERSION_NUMBER >= 0x010600
3029 guint offset_timeout,
3030 #else
3031 guint offset_timeout _U_,
3032 #endif
3033 guint offset_link,
3034 #if GCRYPT_VERSION_NUMBER >= 0x010600
3035 guint8 action)
3036 #else
3037 guint8 action _U_)
3038 #endif
3041 gcry_md_hd_t sha256_handle;
3042 gcry_md_hd_t hmac_handle;
3043 const guint8 *snonce, *anonce, *initiator, *responder, *bssid;
3044 guint8 key_input[32];
3045 #if GCRYPT_VERSION_NUMBER >= 0x010600
3046 guint8 mic[16], seq_num = action + 1;
3047 guint8 zeros[16] = { 0 };
3048 gcry_mac_hd_t cmac_handle;
3049 size_t cmac_len = 16;
3050 size_t cmac_write_len;
3051 #endif
3053 /* Get key input */
3054 anonce = &data[offset_fte + 20];
3055 snonce = &data[offset_fte + 52];
3057 gcry_md_open (&sha256_handle, GCRY_MD_SHA256, 0);
3058 if (memcmp(anonce, snonce, DOT11DECRYPT_WPA_NONCE_LEN) < 0) {
3059 gcry_md_write(sha256_handle, anonce, DOT11DECRYPT_WPA_NONCE_LEN);
3060 gcry_md_write(sha256_handle, snonce, DOT11DECRYPT_WPA_NONCE_LEN);
3061 } else {
3062 gcry_md_write(sha256_handle, snonce, DOT11DECRYPT_WPA_NONCE_LEN);
3063 gcry_md_write(sha256_handle, anonce, DOT11DECRYPT_WPA_NONCE_LEN);
3065 memcpy(key_input, gcry_md_read(sha256_handle, 0), 32);
3066 gcry_md_close(sha256_handle);
3068 /* Derive key */
3069 bssid = &data[offset_link + 2];
3070 initiator = &data[offset_link + 8];
3071 responder = &data[offset_link + 14];
3072 if (gcry_md_open(&hmac_handle, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC)) {
3073 return DOT11DECRYPT_RET_UNSUCCESS;
3075 if (gcry_md_setkey(hmac_handle, key_input, 32)) {
3076 gcry_md_close(hmac_handle);
3077 return DOT11DECRYPT_RET_UNSUCCESS;
3079 gcry_md_putc(hmac_handle, 1);
3080 gcry_md_putc(hmac_handle, 0);
3081 gcry_md_write(hmac_handle, "TDLS PMK", 8);
3082 if (memcmp(initiator, responder, DOT11DECRYPT_MAC_LEN) < 0) {
3083 gcry_md_write(hmac_handle, initiator, DOT11DECRYPT_MAC_LEN);
3084 gcry_md_write(hmac_handle, responder, DOT11DECRYPT_MAC_LEN);
3085 } else {
3086 gcry_md_write(hmac_handle, responder, DOT11DECRYPT_MAC_LEN);
3087 gcry_md_write(hmac_handle, initiator, DOT11DECRYPT_MAC_LEN);
3089 gcry_md_write(hmac_handle, bssid, DOT11DECRYPT_MAC_LEN);
3090 gcry_md_putc(hmac_handle, 0);
3091 gcry_md_putc(hmac_handle, 1);
3092 memcpy(key_input, gcry_md_read(hmac_handle, 0), 32);
3093 gcry_md_close(hmac_handle);
3095 /* Check MIC */
3096 #if GCRYPT_VERSION_NUMBER >= 0x010600
3097 if (gcry_mac_open(&cmac_handle, GCRY_MAC_CMAC_AES, 0, NULL)) {
3098 return DOT11DECRYPT_RET_UNSUCCESS;
3100 if (gcry_mac_setkey(cmac_handle, key_input, 16)) {
3101 gcry_mac_close(cmac_handle);
3102 return DOT11DECRYPT_RET_UNSUCCESS;
3104 gcry_mac_write(cmac_handle, initiator, DOT11DECRYPT_MAC_LEN);
3105 gcry_mac_write(cmac_handle, responder, DOT11DECRYPT_MAC_LEN);
3106 gcry_mac_write(cmac_handle, &seq_num, 1);
3107 gcry_mac_write(cmac_handle, &data[offset_link], data[offset_link + 1] + 2);
3108 gcry_mac_write(cmac_handle, &data[offset_rsne], data[offset_rsne + 1] + 2);
3109 gcry_mac_write(cmac_handle, &data[offset_timeout], data[offset_timeout + 1] + 2);
3110 gcry_mac_write(cmac_handle, &data[offset_fte], 4);
3111 gcry_mac_write(cmac_handle, zeros, 16);
3112 cmac_write_len = data[offset_fte + 1] + 2;
3113 if (cmac_write_len < 20) {
3114 DEBUG_PRINT_LINE("Bad MAC len", DEBUG_LEVEL_3);
3115 gcry_mac_close(cmac_handle);
3116 return DOT11DECRYPT_RET_UNSUCCESS;
3118 gcry_mac_write(cmac_handle, &data[offset_fte + 20], cmac_write_len - 20);
3119 if (gcry_mac_read(cmac_handle, mic, &cmac_len) != GPG_ERR_NO_ERROR) {
3120 DEBUG_PRINT_LINE("MAC read error", DEBUG_LEVEL_3);
3121 gcry_mac_close(cmac_handle);
3122 return DOT11DECRYPT_RET_UNSUCCESS;
3124 if (memcmp(mic, &data[offset_fte + 4], 16)) {
3125 DEBUG_PRINT_LINE("MIC verification failed", DEBUG_LEVEL_3);
3126 gcry_mac_close(cmac_handle);
3127 return DOT11DECRYPT_RET_UNSUCCESS;
3129 gcry_mac_close(cmac_handle);
3130 #else
3131 DEBUG_PRINT_LINE("MIC verification failed, need libgcrypt >= 1.6", DEBUG_LEVEL_3);
3132 return DOT11DECRYPT_RET_UNSUCCESS;
3133 #endif
3134 /* TODO support other akm and ciphers? */
3135 sa->wpa.akm = 2;
3136 sa->wpa.cipher = 4;
3137 sa->wpa.ptk_len = Dot11DecryptGetPtkLen(sa->wpa.akm, sa->wpa.cipher) / 8;
3138 memcpy(DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
3139 key_input + 16, Dot11DecryptGetTkLen(sa->wpa.cipher) / 8);
3140 memcpy(sa->wpa.nonce, snonce, DOT11DECRYPT_WPA_NONCE_LEN);
3141 sa->validKey = TRUE;
3142 sa->wpa.key_ver = DOT11DECRYPT_WPA_KEY_VER_AES_CCMP;
3143 DEBUG_PRINT_LINE("MIC verified", DEBUG_LEVEL_3);
3144 return DOT11DECRYPT_RET_SUCCESS;
3148 #ifdef __cplusplus
3150 #endif
3152 /****************************************************************************/
3155 * Editor modelines
3157 * Local Variables:
3158 * c-basic-offset: 4
3159 * tab-width: 8
3160 * indent-tabs-mode: nil
3161 * End:
3163 * ex: set shiftwidth=4 tabstop=8 expandtab:
3164 * :indentSize=4:tabSize=8:noTabs=true: