epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / crypt / dot11decrypt.c
blobfb703bc10ebcdb37083451f8cf91d4f35e9f7c60
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"
13 /* Keep this first after config.h so that WS_LOG_DOMAIN is set correctly. */
14 #include "dot11decrypt_debug.h"
16 #include <stdint.h>
17 #include <glib.h>
19 #include <wsutil/wsgcrypt.h>
20 #include <wsutil/crc32.h>
21 #include <wsutil/pint.h>
23 #include <epan/proto.h> /* for DISSECTOR_ASSERT. */
24 #include <epan/strutil.h>
26 #include "dot11decrypt_util.h"
27 #include "dot11decrypt_system.h"
28 #include "dot11decrypt_int.h"
30 #include "wep-wpadefs.h"
33 /****************************************************************************/
34 static int Dot11DecryptGetKckLen(int akm);
35 static int Dot11DecryptGetTkLen(int cipher);
36 static int Dot11DecryptGetKekLen(int akm);
37 static int Dot11DecryptGetPtkLen(int akm, int cipher);
38 static int Dot11DecryptGetHashAlgoFromAkm(int akm);
40 /****************************************************************************/
41 /* Constant definitions */
43 /* EAPOL definitions */
44 /**
45 * Length of the EAPOL-Key key confirmation key (KCK) used to calculate
46 * MIC over EAPOL frame and validate an EAPOL packet (128 bits)
48 #define DOT11DECRYPT_WPA_KCK_LEN 16
49 /**
50 *Offset of the Key MIC in the EAPOL packet body
52 #define DOT11DECRYPT_WPA_MICKEY_OFFSET 77
53 /**
54 * Maximum length of the EAPOL packet (it depends on the maximum MAC
55 * frame size)
57 #define DOT11DECRYPT_WPA_MAX_EAPOL_LEN 4095
58 /**
59 * EAPOL Key Descriptor Version 1, used for all EAPOL-Key frames to and
60 * from a STA when neither the group nor pairwise ciphers are CCMP for
61 * Key Descriptor 1.
62 * @note
63 * Defined in 802.11i-2004, page 78
65 #define DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP 1
66 /**
67 * EAPOL Key Descriptor Version 2, used for all EAPOL-Key frames to and
68 * from a STA when either the pairwise or the group cipher is AES-CCMP
69 * for Key Descriptor 2.
70 * /note
71 * Defined in 802.11i-2004, page 78
73 #define DOT11DECRYPT_WPA_KEY_VER_AES_CCMP 2
75 /** Define EAPOL Key Descriptor type values: use 254 for WPA and 2 for WPA2 **/
76 #define DOT11DECRYPT_RSN_WPA_KEY_DESCRIPTOR 254
77 #define DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR 2
79 /* PMK to PTK derive functions */
80 #define DOT11DECRYPT_DERIVE_USING_PRF 0
81 #define DOT11DECRYPT_DERIVE_USING_KDF 1
82 /****************************************************************************/
85 /****************************************************************************/
86 /* Macro definitions */
88 extern const uint32_t crc32_table[256];
89 #define CRC(crc, ch) (crc = (crc >> 8) ^ crc32_table[(crc ^ (ch)) & 0xff])
91 #define KCK_OFFSET(akm) (0)
92 #define KEK_OFFSET(akm) ((KCK_OFFSET(akm) + Dot11DecryptGetKckLen(akm) / 8))
93 #define TK_OFFSET(akm) ((KEK_OFFSET(akm) + Dot11DecryptGetKekLen(akm) / 8))
95 #define DOT11DECRYPT_GET_KCK(ptk, akm) (ptk + KCK_OFFSET(akm))
96 #define DOT11DECRYPT_GET_KEK(ptk, akm) (ptk + KEK_OFFSET(akm))
97 #define DOT11DECRYPT_GET_TK_TKIP(ptk) (ptk + 32)
98 #define DOT11DECRYPT_GET_TK(ptk, akm) (ptk + TK_OFFSET(akm))
100 #define DOT11DECRYPT_IEEE80211_OUI(oui) (pntoh24(oui) == 0x000fac)
102 /****************************************************************************/
104 /****************************************************************************/
105 /* Type definitions */
107 /* Internal function prototype declarations */
109 #ifdef __cplusplus
110 extern "C" {
111 #endif
114 * It is a step of the PBKDF2 (specifically the PKCS #5 v2.0) defined in
115 * the RFC 2898 to derive a key (used as PMK in WPA)
116 * @param ppbytes [IN] pointer to a password (sequence of between 8 and
117 * 63 ASCII encoded characters)
118 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
119 * encoded characters
120 * @param iterations [IN] times to hash the password (4096 for WPA)
121 * @param count [IN] ???
122 * @param output [OUT] pointer to a preallocated buffer of
123 * SHA1_DIGEST_LEN characters that will contain a part of the key
125 static int Dot11DecryptRsnaPwd2PskStep(
126 const uint8_t *ppbytes,
127 const unsigned passLength,
128 const char *ssid,
129 const size_t ssidLength,
130 const int iterations,
131 const int count,
132 unsigned char *output)
136 * It calculates the passphrase-to-PSK mapping reccomanded for use with
137 * RSNAs. This implementation uses the PBKDF2 method defined in the RFC
138 * 2898.
139 * @param userPwd [IN] pointer to the struct containing a password
140 * (octet string between 8 and 63 octets) and optional SSID octet
141 * string of up to 32 octets (both are usually ASCII but in fact
142 * opaque and can be any encoding.)
143 * @param output [OUT] calculated PSK (to use as PMK in WPA)
144 * @note
145 * Described in 802.11i-2004, page 165
147 static int Dot11DecryptRsnaPwd2Psk(
148 const struct DOT11DECRYPT_KEY_ITEMDATA_PWD *userPwd,
149 unsigned char *output)
152 static int Dot11DecryptRsnaMng(
153 unsigned char *decrypt_data,
154 unsigned mac_header_len,
155 unsigned *decrypt_len,
156 PDOT11DECRYPT_KEY_ITEM key,
157 DOT11DECRYPT_SEC_ASSOCIATION *sa)
160 static int Dot11DecryptWepMng(
161 PDOT11DECRYPT_CONTEXT ctx,
162 unsigned char *decrypt_data,
163 unsigned mac_header_len,
164 unsigned *decrypt_len,
165 PDOT11DECRYPT_KEY_ITEM key,
166 DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
169 static int Dot11DecryptRsna4WHandshake(
170 PDOT11DECRYPT_CONTEXT ctx,
171 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
172 const uint8_t *eapol_raw,
173 DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
174 const unsigned tot_len);
177 * It checks whether the specified key is corrected or not.
178 * @note
179 * For a standard WEP key the length will be changed to the standard
180 * length, and the type changed in a generic WEP key.
181 * @param key [IN] pointer to the key to validate
182 * @return
183 * - true: the key contains valid fields and values
184 * - false: the key has some invalid field or value
186 static int Dot11DecryptValidateKey(
187 PDOT11DECRYPT_KEY_ITEM key)
190 static int Dot11DecryptRsnaMicCheck(
191 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
192 unsigned char *eapol,
193 unsigned short eapol_len,
194 unsigned char *KCK,
195 unsigned short key_ver,
196 int akm)
199 static int
200 Dot11DecryptFtMicCheck(
201 const PDOT11DECRYPT_ASSOC_PARSED assoc_parsed,
202 const uint8_t *kck,
203 size_t kck_len);
205 static PDOT11DECRYPT_SEC_ASSOCIATION
206 Dot11DecryptGetSa(
207 PDOT11DECRYPT_CONTEXT ctx,
208 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
211 static int Dot11DecryptGetSaAddress(
212 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame,
213 DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
216 static const unsigned char * Dot11DecryptGetStaAddress(
217 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame)
220 static const unsigned char * Dot11DecryptGetBssidAddress(
221 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame)
224 static uint8_t
225 Dot11DecryptDerivePtk(
226 const DOT11DECRYPT_SEC_ASSOCIATION *sa,
227 const unsigned char *pmk,
228 size_t pmk_len,
229 const unsigned char snonce[32],
230 int key_version,
231 int akm,
232 int cipher,
233 uint8_t *ptk, size_t *ptk_len);
235 static uint8_t
236 Dot11DecryptFtDerivePtk(
237 const PDOT11DECRYPT_CONTEXT ctx,
238 const DOT11DECRYPT_SEC_ASSOCIATION *sa,
239 const PDOT11DECRYPT_KEY_ITEM key,
240 const uint8_t mdid[2],
241 const uint8_t *snonce,
242 const uint8_t *r0kh_id, size_t r0kh_id_len,
243 const uint8_t *r1kh_id, size_t r1kh_id_len _U_,
244 int akm, int cipher,
245 uint8_t *ptk, size_t *ptk_len);
248 * @param sa [IN/OUT] pointer to SA that will hold the key
249 * @param data [IN] Frame
250 * @param offset_rsne [IN] RSNE IE offset in the frame
251 * @param offset_fte [IN] Fast BSS Transition IE offset in the frame
252 * @param offset_timeout [IN] Timeout Interval IE offset in the frame
253 * @param offset_link [IN] Link Identifier IE offset in the frame
254 * @param action [IN] Tdls Action code (response or confirm)
256 * @return
257 * DOT11DECRYPT_RET_SUCCESS if Key has been successfully derived (and MIC verified)
258 * DOT11DECRYPT_RET_UNSUCCESS otherwise
260 static int
261 Dot11DecryptTDLSDeriveKey(
262 PDOT11DECRYPT_SEC_ASSOCIATION sa,
263 const uint8_t *data,
264 unsigned offset_rsne,
265 unsigned offset_fte,
266 unsigned offset_timeout,
267 unsigned offset_link,
268 uint8_t action)
270 #ifdef __cplusplus
272 #endif
274 /****************************************************************************/
276 /****************************************************************************/
277 /* Exported function definitions */
279 #ifdef __cplusplus
280 extern "C" {
281 #endif
283 const uint8_t broadcast_mac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
285 #define TKIP_GROUP_KEY_LEN 32
286 #define CCMP_GROUP_KEY_LEN 16
288 #define EAPOL_RSN_KEY_LEN 95
290 /* Minimum possible key data size (at least one GTK KDE with CCMP key) */
291 #define GROUP_KEY_MIN_LEN 8 + CCMP_GROUP_KEY_LEN
292 /* Minimum possible group key msg size (group key msg using CCMP as cipher)*/
293 #define GROUP_KEY_PAYLOAD_LEN_MIN \
294 (EAPOL_RSN_KEY_LEN + GROUP_KEY_MIN_LEN)
296 static void
297 Dot11DecryptCopyKey(PDOT11DECRYPT_SEC_ASSOCIATION sa, PDOT11DECRYPT_KEY_ITEM key)
299 if (key!=NULL) {
300 if (sa->key!=NULL)
301 memcpy(key, sa->key, sizeof(DOT11DECRYPT_KEY_ITEM));
302 else
303 memset(key, 0, sizeof(DOT11DECRYPT_KEY_ITEM));
304 key->KeyData.Wpa.PtkLen = sa->wpa.ptk_len;
305 memcpy(key->KeyData.Wpa.Ptk, sa->wpa.ptk, sa->wpa.ptk_len);
306 key->KeyData.Wpa.Akm = sa->wpa.akm;
307 key->KeyData.Wpa.Cipher = sa->wpa.cipher;
308 if (sa->wpa.key_ver==DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP)
309 key->KeyType=DOT11DECRYPT_KEY_TYPE_TKIP;
310 else if (sa->wpa.key_ver == 0 || sa->wpa.key_ver == 3 ||
311 sa->wpa.key_ver == DOT11DECRYPT_WPA_KEY_VER_AES_CCMP)
313 switch (sa->wpa.cipher) {
314 case 1:
315 key->KeyType = DOT11DECRYPT_KEY_TYPE_WEP_40;
316 break;
317 case 2:
318 key->KeyType = DOT11DECRYPT_KEY_TYPE_TKIP;
319 break;
320 case 4:
321 key->KeyType = DOT11DECRYPT_KEY_TYPE_CCMP;
322 break;
323 case 5:
324 key->KeyType = DOT11DECRYPT_KEY_TYPE_WEP_104;
325 break;
326 case 8:
327 key->KeyType = DOT11DECRYPT_KEY_TYPE_GCMP;
328 break;
329 case 9:
330 key->KeyType = DOT11DECRYPT_KEY_TYPE_GCMP_256;
331 break;
332 case 10:
333 key->KeyType = DOT11DECRYPT_KEY_TYPE_CCMP_256;
334 break;
335 default:
336 key->KeyType = DOT11DECRYPT_KEY_TYPE_UNKNOWN;
337 break;
338 /* NOT SUPPORTED YET
339 case 3: Reserved
340 case 6: BIP-CMAC-128
341 case 7: Group addressed traffic not allowed
342 case 11: BIP-GMAC-128
343 case 12: BIP-GMAC-256
344 case 13: BIP-CMAC-256 */
350 static uint8_t*
351 Dot11DecryptRc4KeyData(const uint8_t *decryption_key, unsigned decryption_key_len,
352 const uint8_t *encrypted_keydata, unsigned encrypted_keydata_len)
354 gcry_cipher_hd_t rc4_handle;
355 uint8_t dummy[256] = { 0 };
356 uint8_t *decrypted_key = NULL;
358 if (gcry_cipher_open (&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
359 return NULL;
361 if (gcry_cipher_setkey(rc4_handle, decryption_key, decryption_key_len)) {
362 gcry_cipher_close(rc4_handle);
363 return NULL;
365 decrypted_key = (uint8_t *)g_memdup2(encrypted_keydata, encrypted_keydata_len);
366 if (!decrypted_key) {
367 gcry_cipher_close(rc4_handle);
368 return NULL;
371 /* Do dummy 256 iterations of the RC4 algorithm (per 802.11i, Draft 3.0, p. 97 line 6) */
372 gcry_cipher_decrypt(rc4_handle, dummy, 256, NULL, 0);
373 gcry_cipher_decrypt(rc4_handle, decrypted_key, encrypted_keydata_len, NULL, 0);
374 gcry_cipher_close(rc4_handle);
375 return decrypted_key;
378 static int
379 AES_unwrap(
380 const uint8_t *kek,
381 uint16_t kek_len,
382 const uint8_t *cipher_text,
383 uint16_t cipher_len,
384 uint8_t *output,
385 uint16_t *output_len)
387 gcry_cipher_hd_t handle;
389 if (kek == NULL || cipher_len < 16 || cipher_text == NULL) {
390 return 1; /* "should not happen" */
392 if (gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_AESWRAP, 0)) {
393 return 1;
395 if (gcry_cipher_setkey(handle, kek, kek_len)) {
396 gcry_cipher_close(handle);
397 return 1;
399 if (gcry_cipher_decrypt(handle, output, cipher_len - 8, cipher_text, cipher_len)) {
400 gcry_cipher_close(handle);
401 return 1;
403 *output_len = cipher_len - 8;
404 gcry_cipher_close(handle);
405 return 0;
409 Dot11DecryptDecryptKeyData(PDOT11DECRYPT_CONTEXT ctx,
410 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
411 const unsigned char bssid[DOT11DECRYPT_MAC_LEN],
412 const unsigned char sta[DOT11DECRYPT_MAC_LEN],
413 unsigned char *decrypted_data, unsigned *decrypted_len,
414 PDOT11DECRYPT_KEY_ITEM key)
416 uint8_t key_version;
417 const uint8_t *key_data;
418 uint16_t key_bytes_len = 0; /* Length of the total key data field */
419 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
420 PDOT11DECRYPT_SEC_ASSOCIATION sa;
422 /* search for a cached Security Association for current BSSID and AP */
423 memcpy(id.bssid, bssid, DOT11DECRYPT_MAC_LEN);
424 memcpy(id.sta, sta, DOT11DECRYPT_MAC_LEN);
425 sa = Dot11DecryptGetSa(ctx, &id);
426 if (sa == NULL || !sa->validKey) {
427 ws_debug("No valid SA for BSSID found");
428 return DOT11DECRYPT_RET_UNSUCCESS;
431 /* Decrypt GTK using KEK portion of PTK */
432 uint8_t *decryption_key = DOT11DECRYPT_GET_KEK(sa->wpa.ptk, sa->wpa.akm);
433 unsigned decryption_key_len = Dot11DecryptGetKekLen(sa->wpa.akm) / 8;
435 /* 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. */
437 /* Preparation for decrypting the group key - determine group key data length */
438 /* depending on whether the pairwise key is TKIP or AES encryption key */
439 key_version = eapol_parsed->key_version;
440 if (key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP){
441 /* TKIP */
442 key_bytes_len = eapol_parsed->key_len;
443 }else if (key_version == DOT11DECRYPT_WPA_KEY_VER_AES_CCMP){
444 /* AES */
445 key_bytes_len = eapol_parsed->key_data_len;
447 /* AES keys must be at least 128 bits = 16 bytes. */
448 if (key_bytes_len < 16) {
449 return DOT11DECRYPT_RET_UNSUCCESS;
451 } else {
452 /* XXX Ideally group cipher suite type from EAPOL message 2 of 4 should be used to */
453 /* determine key size. As we currently have no way to do this lookup check that key */
454 /* is at least 16 bytes (IEEE802.11-2016 Table 12-4 Cipher suite key lengths) */
455 key_bytes_len = eapol_parsed->key_data_len;
457 if (key_bytes_len < 16) {
458 return DOT11DECRYPT_RET_UNSUCCESS;
462 if ((key_bytes_len < GROUP_KEY_MIN_LEN) ||
463 (eapol_parsed->len < EAPOL_RSN_KEY_LEN) ||
464 (key_bytes_len > eapol_parsed->len - EAPOL_RSN_KEY_LEN)) {
465 return DOT11DECRYPT_RET_UNSUCCESS;
468 /* Encrypted key is in the information element field of the EAPOL key packet */
469 key_data = eapol_parsed->key_data;
471 DEBUG_DUMP("Encrypted Broadcast key", key_data, key_bytes_len, LOG_LEVEL_DEBUG);
472 DEBUG_DUMP("KeyIV", eapol_parsed->key_iv, 16, LOG_LEVEL_DEBUG);
473 DEBUG_DUMP("decryption_key", decryption_key, decryption_key_len, LOG_LEVEL_DEBUG);
475 /* As we have no concept of the prior association request at this point, we need to deduce the */
476 /* group key cipher from the length of the key bytes. In WPA this is straightforward as the */
477 /* keybytes just contain the GTK, and the GTK is only in the group handshake, NOT the M3. */
478 /* In WPA2 its a little more tricky as the M3 keybytes contain an RSN_IE, but the group handshake */
479 /* does not. Also there are other (variable length) items in the keybytes which we need to account */
480 /* for to determine the true key length, and thus the group cipher. */
482 if (key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP){
483 /* TKIP key */
484 /* Per 802.11i, Draft 3.0 spec, section 8.5.2, p. 97, line 4-8, */
485 /* group key is decrypted using RC4. Concatenate the IV with the 16 byte EK (PTK+16) to get the decryption key */
486 uint8_t new_key[32];
487 uint8_t *data;
489 /* The WPA group key just contains the GTK bytes so deducing the type is straightforward */
490 /* Note - WPA M3 doesn't contain a group key so we'll only be here for the group handshake */
491 sa->wpa.key_ver = (key_bytes_len >=TKIP_GROUP_KEY_LEN)?DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP:DOT11DECRYPT_WPA_KEY_VER_AES_CCMP;
493 /* Build the full decryption key based on the IV and part of the pairwise key */
494 memcpy(new_key, eapol_parsed->key_iv, 16);
495 memcpy(new_key+16, decryption_key, 16);
496 DEBUG_DUMP("FullDecrKey", new_key, 32, LOG_LEVEL_DEBUG);
497 data = Dot11DecryptRc4KeyData(new_key, 32, key_data, key_bytes_len);
498 if (!data) {
499 return DOT11DECRYPT_RET_UNSUCCESS;
501 memcpy(decrypted_data, data, key_bytes_len);
502 g_free(data);
503 } else {
504 /* Ideally AKM from EAPOL message 2 of 4 should be used to determine Key-wrap algorithm to use */
505 /* Though fortunately IEEE802.11-2016 Table 12-8 state that all AKMs use "NIST AES Key Wrap" */
506 /* algorithm so no AKM lookup is needed. */
508 /* Unwrap the key; the result is key_bytes_len in length */
509 if (AES_unwrap(decryption_key, decryption_key_len, key_data, key_bytes_len,
510 decrypted_data, &key_bytes_len)) {
511 return DOT11DECRYPT_RET_UNSUCCESS;
515 Dot11DecryptCopyKey(sa, key);
516 *decrypted_len = key_bytes_len;
517 return DOT11DECRYPT_RET_SUCCESS;
521 * @param ctx [IN] pointer to the current context
522 * @param id [IN] id of the association (composed by BSSID and MAC of
523 * the station)
524 * @return a pointer of the requested SA. NULL if it doesn't exist.
526 static PDOT11DECRYPT_SEC_ASSOCIATION
527 Dot11DecryptGetSa(
528 PDOT11DECRYPT_CONTEXT ctx,
529 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
531 return (DOT11DECRYPT_SEC_ASSOCIATION *)g_hash_table_lookup(ctx->sa_hash, id);
534 static PDOT11DECRYPT_SEC_ASSOCIATION
535 Dot11DecryptNewSa(const DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
537 PDOT11DECRYPT_SEC_ASSOCIATION sa = g_new0(DOT11DECRYPT_SEC_ASSOCIATION, 1);
538 if (sa != NULL) {
539 sa->saId = *id;
541 return sa;
544 static DOT11DECRYPT_SEC_ASSOCIATION *
545 Dot11DecryptPrependSa(
546 DOT11DECRYPT_SEC_ASSOCIATION *existing_sa,
547 DOT11DECRYPT_SEC_ASSOCIATION *new_sa)
549 DOT11DECRYPT_SEC_ASSOCIATION tmp_sa;
551 /* Add new SA first in list, but copy by value into existing record
552 * so that sa_hash need not be updated with new value */
553 tmp_sa = *existing_sa;
554 *existing_sa = *new_sa;
555 *new_sa = tmp_sa;
556 existing_sa->next = new_sa;
557 return existing_sa;
560 /* Add SA, keep existing (if any). Return pointer to newly inserted (first) SA */
561 static PDOT11DECRYPT_SEC_ASSOCIATION
562 Dot11DecryptAddSa(
563 PDOT11DECRYPT_CONTEXT ctx,
564 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
565 DOT11DECRYPT_SEC_ASSOCIATION *sa)
567 DOT11DECRYPT_SEC_ASSOCIATION *existing_sa = Dot11DecryptGetSa(ctx, id);
568 if (existing_sa != NULL) {
569 sa = Dot11DecryptPrependSa(existing_sa, sa);
570 } else {
571 void *key = g_memdup2(id, sizeof(DOT11DECRYPT_SEC_ASSOCIATION_ID));
572 g_hash_table_insert(ctx->sa_hash, key, sa);
574 return sa;
578 Dot11DecryptGetKCK(const PDOT11DECRYPT_KEY_ITEM key, const uint8_t **kck)
580 if (!key || !kck) {
581 return 0;
583 *kck = DOT11DECRYPT_GET_KCK(key->KeyData.Wpa.Ptk, key->KeyData.Wpa.Akm);
584 return Dot11DecryptGetKckLen(key->KeyData.Wpa.Akm) / 8;
588 Dot11DecryptGetKEK(const PDOT11DECRYPT_KEY_ITEM key, const uint8_t **kek)
590 if (!key || !kek) {
591 return 0;
593 *kek = DOT11DECRYPT_GET_KEK(key->KeyData.Wpa.Ptk, key->KeyData.Wpa.Akm);
594 return Dot11DecryptGetKekLen(key->KeyData.Wpa.Akm) / 8;
598 Dot11DecryptGetTK(const PDOT11DECRYPT_KEY_ITEM key, const uint8_t **tk)
600 int len;
601 if (!key || !tk) {
602 return 0;
604 if (key->KeyType == DOT11DECRYPT_KEY_TYPE_TKIP) {
605 *tk = DOT11DECRYPT_GET_TK_TKIP(key->KeyData.Wpa.Ptk);
606 len = 16;
607 } else {
608 *tk = DOT11DECRYPT_GET_TK(key->KeyData.Wpa.Ptk, key->KeyData.Wpa.Akm);
609 len = Dot11DecryptGetTkLen(key->KeyData.Wpa.Cipher) / 8;
611 return len;
615 Dot11DecryptGetGTK(const PDOT11DECRYPT_KEY_ITEM key, const uint8_t **gtk)
617 int len;
618 if (!key || !gtk) {
619 return 0;
622 /* GTK is stored in PTK at offset 32. See comment in Dot11DecryptCopyBroadcastKey */
623 *gtk = key->KeyData.Wpa.Ptk + 32;
624 if (key->KeyType == DOT11DECRYPT_KEY_TYPE_TKIP) {
625 len = 16;
626 } else {
627 len = Dot11DecryptGetTkLen(key->KeyData.Wpa.Cipher) / 8;
629 return len;
632 int Dot11DecryptScanTdlsForKeys(
633 PDOT11DECRYPT_CONTEXT ctx,
634 const uint8_t *data,
635 const unsigned tot_len)
637 unsigned offset = 0;
638 unsigned tot_len_left = tot_len;
639 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
640 PDOT11DECRYPT_SEC_ASSOCIATION sa;
641 const uint8_t *initiator, *responder;
642 uint8_t action;
643 unsigned status, offset_rsne = 0, offset_fte = 0, offset_link = 0, offset_timeout = 0;
644 ws_debug("Authentication: TDLS Action Frame");
646 /* TDLS payload contains a TDLS Action field (802.11-2016 9.6.13) */
648 /* check if the packet is a TDLS response or confirm */
649 if (tot_len_left < 1) {
650 ws_debug("Not EAPOL-Key");
651 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
653 action = data[offset];
654 if (action != 1 && action != 2) {
655 ws_debug("Not Response nor confirm");
656 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
658 offset++;
659 tot_len_left--;
661 /* Check for SUCCESS (0) or SUCCESS_POWER_SAVE_MODE (85) Status Code */
662 if (tot_len_left < 5) {
663 ws_debug("Not EAPOL-Key");
664 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
666 status=pntoh16(data + offset);
667 if (status != 0 && status != 85) {
668 ws_debug("TDLS setup not successful");
669 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
672 /* skip Token + capabilities */
673 offset += 5;
675 /* search for RSN, Fast BSS Transition, Link Identifier and Timeout Interval IEs */
677 while(offset < (tot_len - 2)) {
678 uint8_t element_id = data[offset];
679 uint8_t length = data[offset + 1];
680 unsigned min_length = length;
681 switch (element_id) {
682 case 48: /* RSN (802.11-2016 9.4.2.35) */
683 offset_rsne = offset;
684 min_length = 1;
685 break;
686 case 55: /* FTE (802.11-2016 9.4.2.48) */
687 offset_fte = offset;
688 /* Plus variable length optional parameter(s) */
689 min_length = 2 + 16 + 32 + 32;
690 break;
691 case 56: /* Timeout Interval (802.11-2016 9.4.2.49) */
692 offset_timeout = offset;
693 min_length = 1 + 4;
694 break;
695 case 101: /* Link Identifier (802.11-2016 9.4.2.62) */
696 offset_link = offset;
697 min_length = 6 + 6 + 6;
698 break;
701 if (length < min_length || tot_len < offset + 2 + length) {
702 ws_debug("Invalid length records in IEs");
703 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
705 offset += 2 + length;
708 if (offset_rsne == 0 || offset_fte == 0 ||
709 offset_timeout == 0 || offset_link == 0)
711 ws_debug("Cannot Find all necessary IEs");
712 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
715 ws_debug("Found RSNE/Fast BSS/Timeout Interval/Link IEs");
717 /* Will create a Security Association between 2 STA. Need to get both MAC address */
718 initiator = &data[offset_link + 8];
719 responder = &data[offset_link + 14];
721 if (memcmp(initiator, responder, DOT11DECRYPT_MAC_LEN) < 0) {
722 memcpy(id.sta, initiator, DOT11DECRYPT_MAC_LEN);
723 memcpy(id.bssid, responder, DOT11DECRYPT_MAC_LEN);
724 } else {
725 memcpy(id.sta, responder, DOT11DECRYPT_MAC_LEN);
726 memcpy(id.bssid, initiator, DOT11DECRYPT_MAC_LEN);
729 /* Check if already derived this key */
730 sa = Dot11DecryptGetSa(ctx, &id);
731 PDOT11DECRYPT_SEC_ASSOCIATION iter_sa;
732 for (iter_sa = sa; iter_sa != NULL; iter_sa = iter_sa->next) {
733 if (iter_sa->validKey &&
734 memcmp(iter_sa->wpa.nonce, data + offset_fte + 52,
735 DOT11DECRYPT_WPA_NONCE_LEN) == 0)
737 /* Already have valid key for this SA, no need to redo key derivation */
738 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
741 /* We are opening a new session with the same two STA (previous sa will be kept if any) */
742 sa = Dot11DecryptNewSa(&id);
743 if (sa == NULL) {
744 ws_warning("Failed to alloc new SA entry");
745 return DOT11DECRYPT_RET_REQ_DATA;
747 if (Dot11DecryptTDLSDeriveKey(sa, data, offset_rsne, offset_fte,
748 offset_timeout, offset_link, action) == DOT11DECRYPT_RET_SUCCESS) {
749 Dot11DecryptAddSa(ctx, &id, sa);
750 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
752 g_free(sa);
753 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
756 static int
757 Dot11DecryptCopyBroadcastKey(
758 PDOT11DECRYPT_CONTEXT ctx,
759 const uint8_t *gtk, size_t gtk_len,
760 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
762 DOT11DECRYPT_SEC_ASSOCIATION_ID broadcast_id;
763 DOT11DECRYPT_SEC_ASSOCIATION *sa;
764 DOT11DECRYPT_SEC_ASSOCIATION *broadcast_sa;
766 if (!gtk || gtk_len == 0) {
767 ws_debug("No broadcast key found");
768 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
770 if (gtk_len > DOT11DECRYPT_WPA_PTK_MAX_LEN - 32) {
771 ws_debug("Broadcast key too large");
772 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
775 sa = Dot11DecryptGetSa(ctx, id);
776 if (sa == NULL) {
777 ws_debug("No SA for BSSID found");
778 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
781 /* Broadcast SA for the current BSSID */
782 memcpy(broadcast_id.bssid, id->bssid, DOT11DECRYPT_MAC_LEN);
783 memcpy(broadcast_id.sta, broadcast_mac, DOT11DECRYPT_MAC_LEN);
785 broadcast_sa = Dot11DecryptNewSa(&broadcast_id);
786 if (broadcast_sa == NULL) {
787 ws_warning("Failed to alloc broadcast sa");
788 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
791 /* Retrieve AKMS / cipher etc from handshake message 2 */
793 broadcast_sa->wpa.key_ver = sa->wpa.key_ver;
794 broadcast_sa->wpa.akm = sa->wpa.akm;
795 broadcast_sa->wpa.cipher = sa->wpa.tmp_group_cipher;
796 broadcast_sa->wpa.ptk_len = sa->wpa.ptk_len;
797 broadcast_sa->validKey = true;
798 DEBUG_DUMP("Broadcast key", gtk, gtk_len, LOG_LEVEL_DEBUG);
800 /* Since this is a GTK and its size is only 32 bytes (vs. the 64 byte size of a PTK),
801 * we fake it and put it in at a 32-byte offset so the Dot11DecryptRsnaMng() function
802 * will extract the right piece of the GTK for decryption. (The first 16 bytes of the
803 * GTK are used for decryption.) */
804 memset(broadcast_sa->wpa.ptk, 0, sizeof(broadcast_sa->wpa.ptk));
805 memcpy(broadcast_sa->wpa.ptk + 32, gtk, gtk_len);
806 Dot11DecryptAddSa(ctx, &broadcast_id, broadcast_sa);
807 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
810 static int
811 Dot11DecryptGroupHandshake(
812 PDOT11DECRYPT_CONTEXT ctx,
813 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
814 const DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
815 const unsigned tot_len)
818 if (GROUP_KEY_PAYLOAD_LEN_MIN > tot_len) {
819 ws_debug("Message too short for Group Key");
820 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
822 if (eapol_parsed->msg_type != DOT11DECRYPT_HS_MSG_TYPE_GHS_1){
823 ws_warning("Not Group handshake message 1");
824 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
826 return Dot11DecryptCopyBroadcastKey(ctx, eapol_parsed->gtk, eapol_parsed->gtk_len, id);
829 int Dot11DecryptScanEapolForKeys(
830 PDOT11DECRYPT_CONTEXT ctx,
831 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
832 const uint8_t *eapol_raw,
833 const unsigned tot_len,
834 const unsigned char bssid[DOT11DECRYPT_MAC_LEN],
835 const unsigned char sta[DOT11DECRYPT_MAC_LEN])
837 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
839 /* Callers provide these guarantees, so let's make them explicit. */
840 DISSECTOR_ASSERT(tot_len <= DOT11DECRYPT_EAPOL_MAX_LEN);
842 ws_debug("Authentication: EAPOL packet");
844 /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */
845 if (/*eapol_parsed->key_type != 0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */
846 eapol_parsed->key_type != DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR && /* IEEE 802.11 Key Descriptor Type (WPA2) */
847 eapol_parsed->key_type != DOT11DECRYPT_RSN_WPA_KEY_DESCRIPTOR) /* 254 = RSN_KEY_DESCRIPTOR - WPA, */
849 ws_debug("Not valid key descriptor type");
850 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
853 /* search for a cached Security Association for current BSSID and AP */
854 memcpy(id.bssid, bssid, DOT11DECRYPT_MAC_LEN);
855 memcpy(id.sta, sta, DOT11DECRYPT_MAC_LEN);
857 switch (eapol_parsed->msg_type) {
858 case DOT11DECRYPT_HS_MSG_TYPE_4WHS_1:
859 case DOT11DECRYPT_HS_MSG_TYPE_4WHS_2:
860 case DOT11DECRYPT_HS_MSG_TYPE_4WHS_3:
861 case DOT11DECRYPT_HS_MSG_TYPE_4WHS_4:
862 return Dot11DecryptRsna4WHandshake(ctx, eapol_parsed, eapol_raw,
863 &id, tot_len);
864 case DOT11DECRYPT_HS_MSG_TYPE_GHS_1:
865 return Dot11DecryptGroupHandshake(ctx, eapol_parsed, &id, tot_len);
866 case DOT11DECRYPT_HS_MSG_TYPE_GHS_2:
867 break;
868 case DOT11DECRYPT_HS_MSG_TYPE_INVALID:
869 default:
870 ws_warning("Invalid message type");
871 break;
873 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
876 static int
877 Dot11DecryptGetNbrOfTkKeys(PDOT11DECRYPT_CONTEXT ctx)
879 int nbr = 0;
880 for (size_t i = 0; i < ctx->keys_nr; i++) {
881 if (ctx->keys[i].KeyType == DOT11DECRYPT_KEY_TYPE_TK) {
882 nbr++;
885 return nbr;
888 static int
889 Dot11DecryptUsingUserTk(
890 PDOT11DECRYPT_CONTEXT ctx,
891 unsigned char *decrypt_data,
892 unsigned mac_header_len,
893 unsigned *decrypt_len,
894 DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
895 DOT11DECRYPT_KEY_ITEM *used_key)
897 int ret = DOT11DECRYPT_RET_REQ_DATA;
898 DOT11DECRYPT_SEC_ASSOCIATION *sa = Dot11DecryptNewSa(id);
899 DOT11DECRYPT_KEY_ITEM *key;
900 if (sa == NULL) {
901 return ret;
904 sa->wpa.akm = 2;
905 sa->validKey = true;
907 /* Try decrypt packet with all user TKs applicable ciphers */
908 for (size_t key_index = 0; key_index < ctx->keys_nr; key_index++) {
909 key = &ctx->keys[key_index];
910 if (key->KeyType != DOT11DECRYPT_KEY_TYPE_TK) {
911 continue;
913 int ciphers_to_try[4] = { 0 };
914 switch (key->Tk.Len) {
915 case DOT11DECRYPT_WEP_40_KEY_LEN:
916 case DOT11DECRYPT_WEP_104_KEY_LEN:
917 /* TBD implement */
918 continue;
919 case 256 / 8:
920 ciphers_to_try[0] = 9; /* GCMP-256 */
921 ciphers_to_try[1] = 10; /* CCMP-256 */
922 break;
923 case 128 / 8:
924 ciphers_to_try[0] = 4; /* CCMP-128 */
925 ciphers_to_try[1] = 8; /* GCMP-128 */
926 ciphers_to_try[2] = 2; /* TKIP */
927 break;
928 default:
929 continue;
932 sa->key = key;
934 for (int i = 0; ciphers_to_try[i] != 0; i++) {
935 sa->wpa.cipher = ciphers_to_try[i];
936 if (sa->wpa.cipher == DOT11DECRYPT_CIPHER_TKIP) {
937 sa->wpa.key_ver = 1;
938 memcpy(DOT11DECRYPT_GET_TK_TKIP(sa->wpa.ptk),
939 key->Tk.Tk, key->Tk.Len);
940 } else {
941 sa->wpa.key_ver = 2;
942 sa->wpa.akm = 2;
943 memcpy(DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
944 key->Tk.Tk, key->Tk.Len);
946 sa->wpa.ptk_len = Dot11DecryptGetPtkLen(sa->wpa.akm, sa->wpa.cipher) / 8;
947 ret = Dot11DecryptRsnaMng(decrypt_data, mac_header_len, decrypt_len, used_key, sa);
948 if (ret == DOT11DECRYPT_RET_SUCCESS) {
949 /* Successfully decrypted using user TK. Add SA formed from user TK so that
950 * subsequent frames can be decrypted much faster using normal code path
951 * without trying each and every user TK entered.
953 Dot11DecryptAddSa(ctx, id, sa);
954 return ret;
958 g_free(sa);
959 return ret;
962 int Dot11DecryptDecryptPacket(
963 PDOT11DECRYPT_CONTEXT ctx,
964 const uint8_t *data,
965 const unsigned mac_header_len,
966 const unsigned tot_len,
967 unsigned char *decrypt_data,
968 unsigned *decrypt_len,
969 PDOT11DECRYPT_KEY_ITEM key)
971 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
972 DISSECTOR_ASSERT(decrypt_data);
973 DISSECTOR_ASSERT(decrypt_len);
975 if (decrypt_len) {
976 *decrypt_len = 0;
978 if (ctx==NULL) {
979 ws_warning("NULL context");
980 return DOT11DECRYPT_RET_REQ_DATA;
982 if (data==NULL || tot_len==0) {
983 ws_debug("NULL data or length=0");
984 return DOT11DECRYPT_RET_REQ_DATA;
987 /* check correct packet size, to avoid wrong elaboration of encryption algorithms */
988 if (tot_len < (unsigned)(mac_header_len+DOT11DECRYPT_CRYPTED_DATA_MINLEN)) {
989 ws_debug("minimum length violated");
990 return DOT11DECRYPT_RET_WRONG_DATA_SIZE;
993 /* Assume that the decrypt_data field is no more than this size. */
994 if (tot_len > DOT11DECRYPT_MAX_CAPLEN) {
995 ws_debug("length too large");
996 return DOT11DECRYPT_RET_UNSUCCESS;
999 /* get STA/BSSID address */
1000 if (Dot11DecryptGetSaAddress((const DOT11DECRYPT_MAC_FRAME_ADDR4 *)(data), &id) != DOT11DECRYPT_RET_SUCCESS) {
1001 ws_noisy("STA/BSSID not found");
1002 return DOT11DECRYPT_RET_REQ_DATA;
1005 /* check if data is encrypted (use the WEP bit in the Frame Control field) */
1006 if (DOT11DECRYPT_WEP(data[1])==0) {
1007 return DOT11DECRYPT_RET_NO_DATA_ENCRYPTED;
1009 PDOT11DECRYPT_SEC_ASSOCIATION sa;
1011 /* create new header and data to modify */
1012 *decrypt_len = tot_len;
1013 memcpy(decrypt_data, data, *decrypt_len);
1015 /* encrypted data */
1016 ws_noisy("Encrypted data");
1018 /* check the Extension IV to distinguish between WEP encryption and WPA encryption */
1019 /* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */
1020 /* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */
1021 /* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */
1022 if (DOT11DECRYPT_EXTIV(data[mac_header_len + 3]) == 0) {
1023 ws_noisy("WEP encryption");
1024 return Dot11DecryptWepMng(ctx, decrypt_data, mac_header_len, decrypt_len, key, &id);
1025 } else {
1026 ws_noisy("TKIP or CCMP encryption");
1028 /* If the destination is a multicast address use the group key. This will not work if the AP is using
1029 more than one group key simultaneously. I've not seen this in practice, however.
1030 Usually an AP will rotate between the two key index values of 1 and 2 whenever
1031 it needs to change the group key to be used. */
1032 if (((const DOT11DECRYPT_MAC_FRAME_ADDR4 *)(data))->addr1[0] & 0x01) {
1033 ws_noisy("Broadcast/Multicast address. This is encrypted with a group key.");
1035 /* force STA address to broadcast MAC so we load the SA for the groupkey */
1036 memcpy(id.sta, broadcast_mac, DOT11DECRYPT_MAC_LEN);
1038 /* search for a cached Security Association for current BSSID and STA/broadcast MAC */
1039 int ret = DOT11DECRYPT_RET_REQ_DATA;
1040 sa = Dot11DecryptGetSa(ctx, &id);
1041 if (sa != NULL) {
1042 /* Decrypt the packet using the appropriate SA */
1043 ret = Dot11DecryptRsnaMng(decrypt_data, mac_header_len, decrypt_len, key, sa);
1045 if (ret != DOT11DECRYPT_RET_SUCCESS && Dot11DecryptGetNbrOfTkKeys(ctx) > 0) {
1046 /* Decryption with known SAs failed. Try decrypt with TK user entries */
1047 ret = Dot11DecryptUsingUserTk(ctx, decrypt_data, mac_header_len, decrypt_len, &id, key);
1049 return ret;
1051 return DOT11DECRYPT_RET_UNSUCCESS;
1054 int Dot11DecryptSetKeys(
1055 PDOT11DECRYPT_CONTEXT ctx,
1056 DOT11DECRYPT_KEY_ITEM keys[],
1057 const size_t keys_nr)
1059 int i;
1060 int success;
1062 if (ctx==NULL || keys==NULL) {
1063 ws_warning("NULL context or NULL keys array");
1064 return 0;
1067 if (keys_nr>DOT11DECRYPT_MAX_KEYS_NR) {
1068 ws_warning("Keys number greater than maximum");
1069 return 0;
1072 /* clean key and SA collections before setting new ones */
1073 Dot11DecryptInitContext(ctx);
1075 /* check and insert keys */
1076 for (i=0, success=0; i<(int)keys_nr; i++) {
1077 if (Dot11DecryptValidateKey(keys+i)==true) {
1078 if (keys[i].KeyType==DOT11DECRYPT_KEY_TYPE_WPA_PWD) {
1079 Dot11DecryptRsnaPwd2Psk(&keys[i].UserPwd, keys[i].KeyData.Wpa.Psk);
1080 keys[i].KeyData.Wpa.PskLen = DOT11DECRYPT_WPA_PWD_PSK_LEN;
1082 memcpy(&ctx->keys[success], &keys[i], sizeof(keys[i]));
1083 success++;
1087 ctx->keys_nr=success;
1088 return success;
1091 static void
1092 Dot11DecryptCleanKeys(
1093 PDOT11DECRYPT_CONTEXT ctx)
1095 if (ctx==NULL) {
1096 ws_warning("NULL context");
1097 return;
1100 memset(ctx->keys, 0, sizeof(DOT11DECRYPT_KEY_ITEM) * DOT11DECRYPT_MAX_KEYS_NR);
1102 ctx->keys_nr=0;
1103 ws_debug("Keys collection cleaned!");
1106 static void
1107 Dot11DecryptCleanSA(
1108 void * first_sa)
1110 DOT11DECRYPT_SEC_ASSOCIATION *cur_sa = (DOT11DECRYPT_SEC_ASSOCIATION *)first_sa;
1111 while (cur_sa) {
1112 DOT11DECRYPT_SEC_ASSOCIATION *next_sa = cur_sa->next;
1113 g_free(cur_sa);
1114 cur_sa = next_sa;
1118 static void
1119 Dot11DecryptCleanSecAssoc(
1120 PDOT11DECRYPT_CONTEXT ctx)
1122 if (ctx->sa_hash != NULL) {
1123 g_hash_table_destroy(ctx->sa_hash);
1124 ctx->sa_hash = NULL;
1129 * XXX - This won't be reliable if a packet containing SSID "B" shows
1130 * up in the middle of a 4-way handshake for SSID "A".
1131 * We should probably use a small array or hash table to keep multiple
1132 * SSIDs.
1134 int Dot11DecryptSetLastSSID(
1135 PDOT11DECRYPT_CONTEXT ctx,
1136 char *pkt_ssid,
1137 size_t pkt_ssid_len)
1139 if (!ctx || !pkt_ssid || pkt_ssid_len < 1 || pkt_ssid_len > WPA_SSID_MAX_SIZE)
1140 return DOT11DECRYPT_RET_UNSUCCESS;
1142 memcpy(ctx->pkt_ssid, pkt_ssid, pkt_ssid_len);
1143 ctx->pkt_ssid_len = pkt_ssid_len;
1145 return DOT11DECRYPT_RET_SUCCESS;
1148 static unsigned
1149 Dot11DecryptSaHash(const void *key)
1151 GBytes *bytes = g_bytes_new_static(key, sizeof(DOT11DECRYPT_SEC_ASSOCIATION_ID));
1152 unsigned hash = g_bytes_hash(bytes);
1153 g_bytes_unref(bytes);
1154 return hash;
1157 static gboolean
1158 Dot11DecryptIsSaIdEqual(const void *key1, const void *key2)
1160 return memcmp(key1, key2, sizeof(DOT11DECRYPT_SEC_ASSOCIATION_ID)) == 0;
1163 int Dot11DecryptInitContext(
1164 PDOT11DECRYPT_CONTEXT ctx)
1166 if (ctx==NULL) {
1167 ws_warning("NULL context");
1168 return DOT11DECRYPT_RET_UNSUCCESS;
1171 Dot11DecryptCleanKeys(ctx);
1172 Dot11DecryptCleanSecAssoc(ctx);
1174 ctx->pkt_ssid_len = 0;
1175 ctx->sa_hash = g_hash_table_new_full(Dot11DecryptSaHash, Dot11DecryptIsSaIdEqual,
1176 g_free, Dot11DecryptCleanSA);
1177 if (ctx->sa_hash == NULL) {
1178 return DOT11DECRYPT_RET_UNSUCCESS;
1181 ws_debug("Context initialized!");
1182 return DOT11DECRYPT_RET_SUCCESS;
1185 int Dot11DecryptDestroyContext(
1186 PDOT11DECRYPT_CONTEXT ctx)
1188 if (ctx==NULL) {
1189 ws_warning("NULL context");
1190 return DOT11DECRYPT_RET_UNSUCCESS;
1193 Dot11DecryptCleanKeys(ctx);
1194 Dot11DecryptCleanSecAssoc(ctx);
1196 ws_debug("Context destroyed!");
1197 return DOT11DECRYPT_RET_SUCCESS;
1200 #ifdef __cplusplus
1202 #endif
1204 /****************************************************************************/
1206 /****************************************************************************/
1207 /* Internal function definitions */
1209 #ifdef __cplusplus
1210 extern "C" {
1211 #endif
1213 static int
1214 Dot11DecryptRsnaMng(
1215 unsigned char *decrypt_data,
1216 unsigned mac_header_len,
1217 unsigned *decrypt_len,
1218 PDOT11DECRYPT_KEY_ITEM key,
1219 DOT11DECRYPT_SEC_ASSOCIATION *sa)
1221 int ret = 1;
1222 unsigned char *try_data;
1223 unsigned try_data_len = *decrypt_len;
1225 if (*decrypt_len == 0) {
1226 ws_debug("Invalid decryption length");
1227 return DOT11DECRYPT_RET_UNSUCCESS;
1230 /* allocate a temp buffer for the decryption loop */
1231 try_data=(unsigned char *)g_malloc(try_data_len);
1233 /* start of loop added by GCS */
1234 for(/* sa */; sa != NULL ;sa=sa->next) {
1236 if (sa->validKey==false) {
1237 ws_noisy("Key not yet valid");
1238 continue;
1241 /* copy the encrypted data into a temp buffer */
1242 memcpy(try_data, decrypt_data, *decrypt_len);
1244 /* Select decryption method based on EAPOL Key Descriptor Version and negotiated AKM
1245 * with selected cipher suite. Refer to IEEE 802.11-2020:
1246 * 12.7.2 EAPOL-Key frames
1247 * 12.2.4 RSNA establishment
1248 * 12.7 Keys and key distribution
1249 * Table 9-149-Cipher suite selectors
1252 if (sa->wpa.key_ver == 1 || sa->wpa.cipher == DOT11DECRYPT_CIPHER_TKIP) {
1253 /* CCMP -> HMAC-MD5 is the EAPOL-Key MIC, RC4 is the EAPOL-Key encryption algorithm */
1254 ws_noisy("TKIP");
1255 DEBUG_DUMP("ptk", sa->wpa.ptk, 64, LOG_LEVEL_NOISY);
1256 DEBUG_DUMP("ptk portion used", DOT11DECRYPT_GET_TK_TKIP(sa->wpa.ptk),
1257 16, LOG_LEVEL_NOISY);
1259 if (*decrypt_len < (unsigned)mac_header_len) {
1260 ws_debug("Invalid decryption length");
1261 g_free(try_data);
1262 return DOT11DECRYPT_RET_UNSUCCESS;
1264 if (*decrypt_len < DOT11DECRYPT_TKIP_MICLEN + DOT11DECRYPT_WEP_ICV) {
1265 ws_debug("Invalid decryption length");
1266 g_free(try_data);
1267 return DOT11DECRYPT_RET_UNSUCCESS;
1270 ret = Dot11DecryptTkipDecrypt(try_data + mac_header_len, *decrypt_len - mac_header_len,
1271 try_data + DOT11DECRYPT_TA_OFFSET,
1272 DOT11DECRYPT_GET_TK_TKIP(sa->wpa.ptk));
1273 if (ret) {
1274 ws_noisy("TKIP failed!");
1275 continue;
1278 ws_noisy("TKIP DECRYPTED!!!");
1279 /* remove MIC and ICV from the end of packet */
1280 *decrypt_len -= DOT11DECRYPT_TKIP_MICLEN + DOT11DECRYPT_WEP_ICV;
1281 break;
1282 } else if (sa->wpa.cipher == DOT11DECRYPT_CIPHER_GCMP ||
1283 sa->wpa.cipher == DOT11DECRYPT_CIPHER_GCMP256)
1285 ws_noisy("GCMP");
1287 if (*decrypt_len < DOT11DECRYPT_GCMP_TRAILER) {
1288 ws_debug("Invalid decryption length");
1289 g_free(try_data);
1290 return DOT11DECRYPT_RET_UNSUCCESS;
1292 ret = Dot11DecryptGcmpDecrypt(try_data, mac_header_len, (int)*decrypt_len,
1293 DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
1294 Dot11DecryptGetTkLen(sa->wpa.cipher) / 8);
1295 if (ret) {
1296 continue;
1298 ws_noisy("GCMP DECRYPTED!!!");
1299 /* remove MIC from the end of packet */
1300 *decrypt_len -= DOT11DECRYPT_GCMP_TRAILER;
1301 break;
1302 } else {
1303 /* AES-CCMP -> HMAC-SHA1-128 is the EAPOL-Key MIC, AES wep_key wrap is the EAPOL-Key encryption algorithm */
1304 ws_noisy("CCMP");
1306 unsigned trailer = sa->wpa.cipher != 10 ? DOT11DECRYPT_CCMP_TRAILER : DOT11DECRYPT_CCMP_256_TRAILER;
1307 if (*decrypt_len < trailer) {
1308 ws_debug("Invalid decryption length");
1309 g_free(try_data);
1310 return DOT11DECRYPT_RET_UNSUCCESS;
1313 ret = Dot11DecryptCcmpDecrypt(try_data, mac_header_len, (int)*decrypt_len,
1314 DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
1315 Dot11DecryptGetTkLen(sa->wpa.cipher) / 8,
1316 trailer);
1317 if (ret) {
1318 continue;
1320 ws_noisy("CCMP DECRYPTED!!!");
1321 /* remove MIC from the end of packet */
1322 *decrypt_len -= trailer;
1323 break;
1326 /* end of loop */
1328 /* none of the keys worked */
1329 if(sa == NULL) {
1330 g_free(try_data);
1331 return ret;
1334 if (*decrypt_len > try_data_len || *decrypt_len < 8) {
1335 ws_debug("Invalid decryption length");
1336 g_free(try_data);
1337 return DOT11DECRYPT_RET_UNSUCCESS;
1340 /* remove protection bit */
1341 decrypt_data[1]&=0xBF;
1343 /* remove TKIP/CCMP header */
1344 *decrypt_len-=8;
1346 if (*decrypt_len < mac_header_len) {
1347 ws_debug("Invalid decryption length < mac_header_len");
1348 g_free(try_data);
1349 return DOT11DECRYPT_RET_UNSUCCESS;
1352 /* copy the decrypted data into the decrypt buffer GCS*/
1353 memcpy(decrypt_data + mac_header_len, try_data + mac_header_len + 8,
1354 *decrypt_len - mac_header_len);
1355 g_free(try_data);
1357 Dot11DecryptCopyKey(sa, key);
1358 return DOT11DECRYPT_RET_SUCCESS;
1361 static int
1362 Dot11DecryptWepMng(
1363 PDOT11DECRYPT_CONTEXT ctx,
1364 unsigned char *decrypt_data,
1365 unsigned mac_header_len,
1366 unsigned *decrypt_len,
1367 PDOT11DECRYPT_KEY_ITEM key,
1368 DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
1370 unsigned char wep_key[DOT11DECRYPT_WEP_KEY_MAXLEN+DOT11DECRYPT_WEP_IVLEN];
1371 size_t keylen;
1372 int ret_value=1;
1373 int key_index;
1374 DOT11DECRYPT_KEY_ITEM *tmp_key;
1375 uint8_t useCache=false;
1376 unsigned char *try_data;
1377 DOT11DECRYPT_SEC_ASSOCIATION *sa;
1378 unsigned try_data_len = *decrypt_len;
1380 try_data = (unsigned char *)g_malloc(try_data_len);
1382 /* get the Security Association structure for the STA and AP */
1384 /* For WEP the sa is used only for caching. When no sa exists all user
1385 * entered WEP keys are checked and on successful packet decryption an
1386 * sa is formed caching the key used for decryption.
1388 sa = Dot11DecryptGetSa(ctx, id);
1389 if (sa != NULL && sa->key != NULL) {
1390 useCache = true;
1393 for (key_index=0; key_index<(int)ctx->keys_nr; key_index++) {
1394 /* use the cached one, or try all keys */
1395 if (!useCache) {
1396 tmp_key=&ctx->keys[key_index];
1397 } else {
1398 if (sa->key!=NULL && sa->key->KeyType==DOT11DECRYPT_KEY_TYPE_WEP) {
1399 ws_noisy("Try cached WEP key...");
1400 tmp_key=sa->key;
1401 } else {
1402 ws_noisy("Cached key is not valid, try another WEP key...");
1403 tmp_key=&ctx->keys[key_index];
1407 /* obviously, try only WEP keys... */
1408 if (tmp_key->KeyType==DOT11DECRYPT_KEY_TYPE_WEP) {
1409 ws_noisy("Try WEP key...");
1411 memset(wep_key, 0, sizeof(wep_key));
1412 memcpy(try_data, decrypt_data, *decrypt_len);
1414 /* Construct 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) */
1415 memcpy(wep_key, try_data+mac_header_len, DOT11DECRYPT_WEP_IVLEN);
1416 keylen=tmp_key->KeyData.Wep.WepKeyLen;
1417 memcpy(wep_key+DOT11DECRYPT_WEP_IVLEN, tmp_key->KeyData.Wep.WepKey, keylen);
1419 ret_value=Dot11DecryptWepDecrypt(wep_key,
1420 keylen+DOT11DECRYPT_WEP_IVLEN,
1421 try_data + (mac_header_len+DOT11DECRYPT_WEP_IVLEN+DOT11DECRYPT_WEP_KIDLEN),
1422 *decrypt_len-(mac_header_len+DOT11DECRYPT_WEP_IVLEN+DOT11DECRYPT_WEP_KIDLEN+DOT11DECRYPT_CRC_LEN));
1424 if (ret_value == DOT11DECRYPT_RET_SUCCESS)
1425 memcpy(decrypt_data, try_data, *decrypt_len);
1428 if (!ret_value && tmp_key->KeyType==DOT11DECRYPT_KEY_TYPE_WEP) {
1429 /* the tried key is the correct one, cache it in the Security Association */
1431 /* Form an SA if one does not exist already */
1432 if (sa == NULL) {
1433 sa = Dot11DecryptNewSa(id);
1434 if (sa == NULL) {
1435 ws_warning("Failed to alloc sa for WEP");
1436 ret_value = DOT11DECRYPT_RET_UNSUCCESS;
1437 break;
1439 sa = Dot11DecryptAddSa(ctx, id, sa);
1441 sa->key=tmp_key;
1443 if (key!=NULL) {
1444 memcpy(key, sa->key, sizeof(DOT11DECRYPT_KEY_ITEM));
1445 key->KeyType=DOT11DECRYPT_KEY_TYPE_WEP;
1448 break;
1449 } else {
1450 /* the cached key was not valid, try other keys */
1452 if (useCache==true) {
1453 useCache=false;
1454 key_index--;
1459 g_free(try_data);
1460 if (ret_value)
1461 return DOT11DECRYPT_RET_UNSUCCESS;
1463 ws_noisy("WEP DECRYPTED!!!");
1465 /* remove ICV (4bytes) from the end of packet */
1466 *decrypt_len-=4;
1468 if (*decrypt_len < 4) {
1469 ws_debug("Decryption length too short");
1470 return DOT11DECRYPT_RET_UNSUCCESS;
1473 /* remove protection bit */
1474 decrypt_data[1]&=0xBF;
1476 /* remove IC header */
1477 *decrypt_len-=4;
1478 memmove(decrypt_data + mac_header_len,
1479 decrypt_data + mac_header_len + DOT11DECRYPT_WEP_IVLEN + DOT11DECRYPT_WEP_KIDLEN,
1480 *decrypt_len - mac_header_len);
1482 return DOT11DECRYPT_RET_SUCCESS;
1485 /* From IEEE 802.11-2016 Table 9-133—AKM suite selectors */
1486 static bool Dot11DecryptIsFtAkm(int akm)
1488 switch (akm) {
1489 case 3:
1490 case 4:
1491 case 9:
1492 case 13:
1493 return true;
1495 return false;
1498 /* Get xxkey portion of MSK */
1499 /* From IEEE 802.11-2016 12.7.1.7.3 PMK-R0 */
1500 static const uint8_t *
1501 Dot11DecryptGetXXKeyFromMSK(const uint8_t *msk, size_t msk_len,
1502 int akm, size_t *xxkey_len)
1504 if (!xxkey_len) {
1505 return NULL;
1507 switch (akm) {
1508 case 3:
1509 if (msk_len < 64) {
1510 return NULL;
1512 *xxkey_len = 32;
1513 return msk + 32;
1514 case 13:
1515 if (msk_len < 48) {
1516 return NULL;
1518 *xxkey_len = 48;
1519 return msk;
1520 default:
1521 return NULL;
1525 /* From IEEE 802.11-2016 12.7.1.3 Pairwise key hierarchy */
1526 static void
1527 Dot11DecryptDerivePmkFromMsk(const uint8_t *msk, uint8_t msk_len, int akm,
1528 uint8_t *pmk, uint8_t *pmk_len)
1530 if (!msk || !pmk || !pmk_len) {
1531 return;
1533 // When using AKM suite selector 00-0F-AC:12, the length of the PMK, PMK_bits,
1534 // shall be 384 bits. With all other AKM suite selectors, the length of the PMK,
1535 // PMK_bits, shall be 256 bits.
1536 if (akm == 12) {
1537 *pmk_len = 384 / 8;
1538 } else {
1539 *pmk_len = 256 / 8;
1541 if ((uint8_t)(msk_len + *pmk_len) < msk_len) {
1542 *pmk_len = 0;
1543 return;
1545 // PMK = L(MSK, 0, PMK_bits).
1546 memcpy(pmk, msk, *pmk_len);
1549 static bool
1550 Dot11DecryptIsWpaKeyType(uint8_t key_type)
1552 switch (key_type) {
1553 case DOT11DECRYPT_KEY_TYPE_WPA_PWD:
1554 case DOT11DECRYPT_KEY_TYPE_WPA_PSK:
1555 case DOT11DECRYPT_KEY_TYPE_WPA_PMK:
1556 case DOT11DECRYPT_KEY_TYPE_MSK:
1557 return true;
1559 return false;
1562 static bool
1563 Dot11DecryptIsPwdWildcardSsid(const PDOT11DECRYPT_CONTEXT ctx,
1564 const DOT11DECRYPT_KEY_ITEM *key_item)
1566 if (!ctx || !key_item || key_item->KeyType != DOT11DECRYPT_KEY_TYPE_WPA_PWD) {
1567 return false;
1569 if (key_item->UserPwd.SsidLen == 0 && ctx->pkt_ssid_len > 0 &&
1570 ctx->pkt_ssid_len <= DOT11DECRYPT_WPA_SSID_MAX_LEN) {
1571 return true;
1573 return false;
1576 /* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */
1577 static int
1578 Dot11DecryptRsna4WHandshake(
1579 PDOT11DECRYPT_CONTEXT ctx,
1580 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
1581 const uint8_t *eapol_raw,
1582 DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
1583 const unsigned tot_len)
1585 DOT11DECRYPT_KEY_ITEM *tmp_key, *tmp_pkt_key, pkt_key;
1586 DOT11DECRYPT_SEC_ASSOCIATION *sa;
1587 int key_index;
1588 int ret = 1;
1589 unsigned char useCache=false;
1590 unsigned char eapol[DOT11DECRYPT_EAPOL_MAX_LEN];
1592 if (eapol_parsed->len > DOT11DECRYPT_EAPOL_MAX_LEN ||
1593 eapol_parsed->key_len > DOT11DECRYPT_EAPOL_MAX_LEN ||
1594 eapol_parsed->key_data_len > DOT11DECRYPT_EAPOL_MAX_LEN) {
1595 ws_debug("Too large EAPOL frame and/or key data");
1596 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1599 /* TODO timeouts? */
1601 /* TODO consider key-index */
1603 /* TODO consider Deauthentications */
1605 ws_debug("4-way handshake...");
1607 /* manage 4-way handshake packets; this step completes the 802.1X authentication process (IEEE 802.11i-2004, pag. 85) */
1609 /* message 1: Authenticator->Supplicant (Sec=0, Mic=0, Ack=1, Inst=0, Key=1(pairwise), KeyRSC=0, Nonce=ANonce, MIC=0) */
1610 if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_1) {
1611 ws_debug("4-way handshake message 1");
1613 /* On reception of Message 1, the Supplicant determines whether the Key Replay Counter field value has been */
1614 /* used before with the current PMKSA. If the Key Replay Counter field value is less than or equal to the current */
1615 /* local value, the Supplicant discards the message. */
1616 /* -> not checked, the Authenticator will be send another Message 1 (hopefully!) */
1618 /* save ANonce (from authenticator) to derive the PTK with the SNonce (from the 2 message) */
1619 if (!eapol_parsed->nonce) {
1620 ws_debug("ANonce missing");
1621 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1624 sa = Dot11DecryptGetSa(ctx, id);
1625 if (sa == NULL || sa->handshake >= 2) {
1626 /* Either no SA exists or one exists but we're reauthenticating */
1627 sa = Dot11DecryptNewSa(id);
1628 if (sa == NULL) {
1629 ws_warning("Failed to alloc broadcast sa");
1630 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1632 sa = Dot11DecryptAddSa(ctx, id, sa);
1634 memcpy(sa->wpa.nonce, eapol_parsed->nonce, 32);
1636 /* get the Key Descriptor Version (to select algorithm used in decryption -CCMP or TKIP-) */
1637 sa->wpa.key_ver = eapol_parsed->key_version;
1638 sa->handshake=1;
1639 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
1642 /* 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)) */
1643 if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_2) {
1644 ws_debug("4-way handshake message 2");
1646 /* On reception of Message 2, the Authenticator checks that the key replay counter corresponds to the */
1647 /* outstanding Message 1. If not, it silently discards the message. */
1648 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, */
1649 /* the Authenticator silently discards Message 2. */
1650 /* -> not checked; the Supplicant will send another message 2 (hopefully!) */
1652 sa = Dot11DecryptGetSa(ctx, id);
1653 if (sa == NULL) {
1654 ws_debug("No SA for BSSID found");
1655 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1657 if (!eapol_parsed->nonce) {
1658 ws_debug("SNonce missing");
1659 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1661 if (sa->key != NULL) {
1662 useCache = true;
1665 int akm = -1;
1666 int cipher = -1;
1667 int group_cipher = -1;
1668 uint8_t ptk[DOT11DECRYPT_WPA_PTK_MAX_LEN];
1669 size_t ptk_len = 0;
1671 /* now you can derive the PTK */
1672 for (key_index=0; key_index<(int)ctx->keys_nr || useCache; key_index++) {
1673 /* use the cached one, or try all keys */
1674 if (useCache && Dot11DecryptIsWpaKeyType(sa->key->KeyType)) {
1675 ws_debug("Try cached WPA key...");
1676 tmp_key = sa->key;
1677 /* Step back loop counter as cached key is used instead */
1678 key_index--;
1679 } else {
1680 ws_debug("Try WPA key...");
1681 tmp_key = &ctx->keys[key_index];
1683 useCache = false;
1685 /* obviously, try only WPA keys... */
1686 if (!Dot11DecryptIsWpaKeyType(tmp_key->KeyType)) {
1687 continue;
1689 if (tmp_key->KeyType == DOT11DECRYPT_KEY_TYPE_WPA_PWD &&
1690 Dot11DecryptIsPwdWildcardSsid(ctx, tmp_key))
1692 /* We have a "wildcard" SSID. Use the one from the packet. */
1693 memcpy(&pkt_key, tmp_key, sizeof(pkt_key));
1694 memcpy(&pkt_key.UserPwd.Ssid, ctx->pkt_ssid, ctx->pkt_ssid_len);
1695 pkt_key.UserPwd.SsidLen = ctx->pkt_ssid_len;
1696 Dot11DecryptRsnaPwd2Psk(&pkt_key.UserPwd, pkt_key.KeyData.Wpa.Psk);
1697 tmp_pkt_key = &pkt_key;
1698 } else {
1699 tmp_pkt_key = tmp_key;
1701 memcpy(eapol, eapol_raw, tot_len);
1703 /* From IEEE 802.11-2016 12.7.2 EAPOL-Key frames */
1704 if (eapol_parsed->key_version == 0 || eapol_parsed->key_version == 3 ||
1705 eapol_parsed->key_version == DOT11DECRYPT_WPA_KEY_VER_AES_CCMP)
1707 /* PTK derivation is based on Authentication Key Management Type */
1708 akm = eapol_parsed->akm;
1709 cipher = eapol_parsed->cipher;
1710 group_cipher = eapol_parsed->group_cipher;
1711 } else if (eapol_parsed->key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP) {
1712 /* TKIP */
1713 akm = 2;
1714 cipher = 2;
1715 group_cipher = 2;
1716 } else {
1717 ws_info("EAPOL key_version not supported");
1718 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1721 if (tmp_pkt_key->KeyType == DOT11DECRYPT_KEY_TYPE_MSK) {
1722 Dot11DecryptDerivePmkFromMsk(tmp_pkt_key->Msk.Msk, tmp_pkt_key->Msk.Len, akm,
1723 tmp_pkt_key->KeyData.Wpa.Psk,
1724 &tmp_pkt_key->KeyData.Wpa.PskLen);
1727 if (Dot11DecryptIsFtAkm(akm)) {
1728 ret = Dot11DecryptFtDerivePtk(ctx, sa, tmp_pkt_key,
1729 eapol_parsed->mdid,
1730 eapol_parsed->nonce,
1731 eapol_parsed->fte.r0kh_id,
1732 eapol_parsed->fte.r0kh_id_len,
1733 eapol_parsed->fte.r1kh_id,
1734 eapol_parsed->fte.r1kh_id_len,
1735 akm, cipher, ptk, &ptk_len);
1736 } else {
1737 /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */
1738 ret = Dot11DecryptDerivePtk(sa, /* authenticator nonce, bssid, station mac */
1739 tmp_pkt_key->KeyData.Wpa.Psk, /* PSK == PMK */
1740 tmp_pkt_key->KeyData.Wpa.PskLen,
1741 eapol_parsed->nonce, /* supplicant nonce */
1742 eapol_parsed->key_version,
1743 akm, cipher, ptk, &ptk_len);
1745 if (ret) {
1746 /* Unsuccessful PTK derivation */
1747 continue;
1749 DEBUG_DUMP("TK", DOT11DECRYPT_GET_TK(ptk, akm), Dot11DecryptGetTkLen(cipher) / 8,
1750 LOG_LEVEL_DEBUG);
1752 ret = Dot11DecryptRsnaMicCheck(eapol_parsed,
1753 eapol, /* eapol frame (header also) */
1754 tot_len, /* eapol frame length */
1755 DOT11DECRYPT_GET_KCK(ptk, akm),
1756 eapol_parsed->key_version,
1757 akm);
1758 /* If the MIC is valid, the Authenticator checks that the RSN information element bit-wise matches */
1759 /* that from the (Re)Association Request message. */
1760 /* i) TODO If these are not exactly the same, the Authenticator uses MLME-DEAUTHENTICATE.request */
1761 /* primitive to terminate the association. */
1762 /* ii) If they do match bit-wise, the Authenticator constructs Message 3. */
1764 if (ret == DOT11DECRYPT_RET_SUCCESS) {
1765 /* the key is the correct one, cache it in the Security Association */
1766 sa->key = tmp_key;
1767 break;
1771 if (ret) {
1772 ws_debug("handshake step failed");
1773 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1775 sa->wpa.key_ver = eapol_parsed->key_version;
1776 sa->wpa.akm = akm;
1777 sa->wpa.cipher = cipher;
1778 sa->wpa.tmp_group_cipher = group_cipher;
1779 memcpy(sa->wpa.ptk, ptk, ptk_len);
1780 sa->wpa.ptk_len = (int)ptk_len;
1781 sa->handshake = 2;
1782 sa->validKey = true; /* we can use the key to decode, even if we have not captured the other eapol packets */
1784 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
1787 /* message 3: Authenticator->Supplicant (Sec=1, Mic=1, Ack=1, Inst=0/1, Key=1(pairwise), KeyRSC=???, Nonce=ANonce, MIC=1) */
1788 if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_3) {
1789 ws_debug("4-way handshake message 3");
1791 /* On reception of Message 3, the Supplicant silently discards the message if the Key Replay Counter field */
1792 /* value has already been used or if the ANonce value in Message 3 differs from the ANonce value in Message 1. */
1793 /* -> not checked, the Authenticator will send another message 3 (hopefully!) */
1795 /* TODO check page 88 (RNS) */
1797 /* If using WPA2 PSK, message 3 will contain an RSN for the group key (GTK KDE).
1798 In order to properly support decrypting WPA2-PSK packets, we need to parse this to get the group key. */
1799 if (eapol_parsed->key_type == DOT11DECRYPT_RSN_WPA2_KEY_DESCRIPTOR) {
1800 return Dot11DecryptCopyBroadcastKey(ctx, eapol_parsed->gtk, eapol_parsed->gtk_len, id);
1804 /* message 4 */
1805 if (eapol_parsed->msg_type == DOT11DECRYPT_HS_MSG_TYPE_4WHS_4) {
1806 /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
1808 /* TODO check MIC and Replay Counter */
1809 /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */
1810 /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */
1811 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */
1812 /* Authenticator silently discards Message 4. */
1814 ws_debug("4-way handshake message 4");
1815 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
1817 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1820 /* Refer to IEEE 802.11-2016 Chapeter 13.8 FT authentication sequence */
1822 Dot11DecryptScanFtAssocForKeys(
1823 const PDOT11DECRYPT_CONTEXT ctx,
1824 const PDOT11DECRYPT_ASSOC_PARSED assoc_parsed,
1825 uint8_t *decrypted_gtk, size_t *decrypted_len,
1826 DOT11DECRYPT_KEY_ITEM* used_key)
1828 DOT11DECRYPT_SEC_ASSOCIATION_ID id;
1830 ws_debug("(Re)Association packet");
1832 if (!ctx || !assoc_parsed) {
1833 ws_warning("Invalid input parameters");
1834 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1836 if (!Dot11DecryptIsFtAkm(assoc_parsed->akm)) {
1837 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1839 if (!assoc_parsed->fte.anonce || !assoc_parsed->fte.snonce) {
1840 ws_debug("ANonce or SNonce missing");
1841 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1844 switch (assoc_parsed->frame_subtype) {
1845 case DOT11DECRYPT_SUBTYPE_ASSOC_REQ:
1846 case DOT11DECRYPT_SUBTYPE_REASSOC_REQ:
1847 memcpy(id.sta, assoc_parsed->sa, DOT11DECRYPT_MAC_LEN);
1848 break;
1849 case DOT11DECRYPT_SUBTYPE_ASSOC_RESP:
1850 case DOT11DECRYPT_SUBTYPE_REASSOC_RESP:
1851 memcpy(id.sta, assoc_parsed->da, DOT11DECRYPT_MAC_LEN);
1852 break;
1853 default:
1854 ws_warning("Invalid frame subtype");
1855 return DOT11DECRYPT_RET_UNSUCCESS;
1857 memcpy(id.bssid, assoc_parsed->bssid, DOT11DECRYPT_MAC_LEN);
1859 DOT11DECRYPT_KEY_ITEM *tmp_key, *tmp_pkt_key, pkt_key;
1860 DOT11DECRYPT_SEC_ASSOCIATION *sa;
1861 size_t key_index;
1862 unsigned ret = 1;
1863 bool useCache = false;
1865 sa = Dot11DecryptNewSa(&id);
1866 if (sa == NULL) {
1867 ws_warning("Failed to alloc sa");
1868 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1871 memcpy(sa->wpa.nonce, assoc_parsed->fte.anonce, 32);
1873 if (sa->key != NULL) {
1874 useCache = true;
1877 uint8_t ptk[DOT11DECRYPT_WPA_PTK_MAX_LEN];
1878 size_t ptk_len;
1880 /* now you can derive the PTK */
1881 for (key_index = 0; key_index < ctx->keys_nr || useCache; key_index++) {
1882 /* use the cached one, or try all keys */
1883 if (useCache && Dot11DecryptIsWpaKeyType(sa->key->KeyType)) {
1884 ws_debug("Try cached WPA key...");
1885 tmp_key = sa->key;
1886 /* Step back loop counter as cached key is used instead */
1887 key_index--;
1888 } else {
1889 ws_debug("Try WPA key...");
1890 tmp_key = &ctx->keys[key_index];
1892 useCache = false;
1894 /* Try only WPA keys... */
1895 if (!Dot11DecryptIsWpaKeyType(tmp_key->KeyType)) {
1896 continue;
1898 if (tmp_key->KeyType == DOT11DECRYPT_KEY_TYPE_WPA_PWD &&
1899 Dot11DecryptIsPwdWildcardSsid(ctx, tmp_key))
1901 /* We have a "wildcard" SSID. Use the one from the packet. */
1902 memcpy(&pkt_key, tmp_key, sizeof(pkt_key));
1903 memcpy(&pkt_key.UserPwd.Ssid, ctx->pkt_ssid, ctx->pkt_ssid_len);
1904 pkt_key.UserPwd.SsidLen = ctx->pkt_ssid_len;
1905 Dot11DecryptRsnaPwd2Psk(&pkt_key.UserPwd, pkt_key.KeyData.Wpa.Psk);
1906 tmp_pkt_key = &pkt_key;
1907 } else {
1908 tmp_pkt_key = tmp_key;
1911 if (tmp_pkt_key->KeyType == DOT11DECRYPT_KEY_TYPE_MSK) {
1912 Dot11DecryptDerivePmkFromMsk(tmp_pkt_key->Msk.Msk, tmp_pkt_key->Msk.Len,
1913 assoc_parsed->akm,
1914 tmp_pkt_key->KeyData.Wpa.Psk,
1915 &tmp_pkt_key->KeyData.Wpa.PskLen);
1918 ret = Dot11DecryptFtDerivePtk(ctx, sa, tmp_pkt_key,
1919 assoc_parsed->mdid,
1920 assoc_parsed->fte.snonce,
1921 assoc_parsed->fte.r0kh_id,
1922 assoc_parsed->fte.r0kh_id_len,
1923 assoc_parsed->fte.r1kh_id,
1924 assoc_parsed->fte.r1kh_id_len,
1925 assoc_parsed->akm, assoc_parsed->cipher,
1926 ptk, &ptk_len);
1927 if (ret != DOT11DECRYPT_RET_SUCCESS) {
1928 continue;
1930 DEBUG_DUMP("TK", DOT11DECRYPT_GET_TK(ptk, assoc_parsed->akm),
1931 Dot11DecryptGetTkLen(assoc_parsed->cipher) / 8,
1932 LOG_LEVEL_DEBUG);
1934 ret = Dot11DecryptFtMicCheck(assoc_parsed,
1935 DOT11DECRYPT_GET_KCK(ptk, assoc_parsed->akm),
1936 Dot11DecryptGetKckLen(assoc_parsed->akm) / 8);
1937 if (ret == DOT11DECRYPT_RET_SUCCESS) {
1938 /* the key is the correct one, cache it in the Security Association */
1939 sa->key = tmp_key;
1940 break;
1944 if (ret) {
1945 ws_debug("handshake step failed");
1946 g_free(sa);
1947 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
1949 sa = Dot11DecryptAddSa(ctx, &id, sa);
1951 sa->wpa.key_ver = 0; /* Determine key type from akms and cipher*/
1952 sa->wpa.akm = assoc_parsed->akm;
1953 sa->wpa.cipher = assoc_parsed->cipher;
1954 sa->wpa.tmp_group_cipher = assoc_parsed->group_cipher;
1955 memcpy(sa->wpa.ptk, ptk, ptk_len);
1956 sa->wpa.ptk_len = (int)ptk_len;
1957 sa->validKey = true;
1959 if (assoc_parsed->gtk && assoc_parsed->gtk_len - 8 <= DOT11DECRYPT_WPA_PTK_MAX_LEN - 32) {
1960 uint8_t decrypted_key[DOT11DECRYPT_WPA_PTK_MAX_LEN - 32];
1961 uint16_t decrypted_key_len;
1962 if (AES_unwrap(DOT11DECRYPT_GET_KEK(sa->wpa.ptk, sa->wpa.akm),
1963 Dot11DecryptGetKekLen(sa->wpa.akm) / 8,
1964 assoc_parsed->gtk, assoc_parsed->gtk_len,
1965 decrypted_key, &decrypted_key_len)) {
1966 return DOT11DECRYPT_RET_UNSUCCESS;
1968 if (decrypted_key_len != assoc_parsed->gtk_subelem_key_len) {
1969 ws_debug("Unexpected GTK length");
1970 return DOT11DECRYPT_RET_UNSUCCESS;
1972 Dot11DecryptCopyBroadcastKey(ctx, decrypted_key, decrypted_key_len, &id);
1973 *decrypted_len = decrypted_key_len;
1974 memcpy(decrypted_gtk, decrypted_key, decrypted_key_len);
1976 Dot11DecryptCopyKey(sa, used_key);
1977 return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
1980 /* From IEEE 802.11-2016 Table 12-8 Integrity and key-wrap algorithms */
1981 static int
1982 Dot11DecryptGetIntegrityAlgoFromAkm(int akm, int *algo, bool *hmac)
1984 int res = 0;
1985 switch (akm) {
1986 case 1:
1987 case 2:
1988 *algo = GCRY_MD_SHA1;
1989 *hmac = true;
1990 break;
1991 case 3:
1992 case 4:
1993 case 5:
1994 case 6:
1995 case 7:
1996 case 8:
1997 case 9:
1998 case 10:
1999 *algo = GCRY_MAC_CMAC_AES;
2000 *hmac = false;
2001 break;
2002 case 11:
2003 case 18:
2004 *algo = GCRY_MD_SHA256;
2005 *hmac = true;
2006 break;
2007 case 12:
2008 case 13:
2009 *algo = GCRY_MD_SHA384;
2010 *hmac = true;
2011 break;
2012 default:
2013 /* Unknown / Not supported yet */
2014 res = -1;
2015 break;
2017 return res;
2020 static int
2021 Dot11DecryptRsnaMicCheck(
2022 PDOT11DECRYPT_EAPOL_PARSED eapol_parsed,
2023 unsigned char *eapol,
2024 unsigned short eapol_len,
2025 unsigned char *KCK,
2026 unsigned short key_ver,
2027 int akm)
2029 uint8_t *mic = eapol_parsed->mic;
2030 uint16_t mic_len = eapol_parsed->mic_len;
2031 uint16_t kck_len = Dot11DecryptGetKckLen(akm) / 8;
2032 /* MIC 16 or 24 bytes, though HMAC-SHA256 / SHA384 algos need 32 / 48 bytes buffer */
2033 unsigned char c_mic[48] = { 0 };
2034 int algo = -1;
2035 bool hmac = true;
2037 if (!mic || mic_len > DOT11DECRYPT_WPA_MICKEY_MAX_LEN) {
2038 ws_debug("Not a valid mic");
2039 return DOT11DECRYPT_RET_UNSUCCESS;
2042 /* set to 0 the MIC in the EAPOL packet (to calculate the MIC) */
2043 memset(eapol + DOT11DECRYPT_WPA_MICKEY_OFFSET + 4, 0, mic_len);
2045 if (key_ver==DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP) {
2046 /* use HMAC-MD5 for the EAPOL-Key MIC */
2047 algo = GCRY_MD_MD5;
2048 hmac = true;
2049 } else if (key_ver==DOT11DECRYPT_WPA_KEY_VER_AES_CCMP) {
2050 /* use HMAC-SHA1-128 for the EAPOL-Key MIC */
2051 algo = GCRY_MD_SHA1;
2052 hmac = true;
2053 } else {
2054 /* Mic check algorithm determined by AKM type */
2055 if (Dot11DecryptGetIntegrityAlgoFromAkm(akm, &algo, &hmac)) {
2056 ws_warning("Unknown Mic check algo");
2057 return DOT11DECRYPT_RET_UNSUCCESS;
2060 if (hmac) {
2061 if (ws_hmac_buffer(algo, c_mic, eapol, eapol_len, KCK, kck_len)) {
2062 ws_debug("HMAC_BUFFER");
2063 return DOT11DECRYPT_RET_UNSUCCESS;
2065 } else {
2066 if (ws_cmac_buffer(algo, c_mic, eapol, eapol_len, KCK, kck_len)) {
2067 ws_debug("HMAC_BUFFER");
2068 return DOT11DECRYPT_RET_UNSUCCESS;
2072 /* compare calculated MIC with the Key MIC and return result (0 means success) */
2073 DEBUG_DUMP("mic", mic, mic_len, LOG_LEVEL_DEBUG);
2074 DEBUG_DUMP("c_mic", c_mic, mic_len, LOG_LEVEL_DEBUG);
2075 return memcmp(mic, c_mic, mic_len);
2078 /* IEEE 802.11-2016 Chapter 13.8.4 FT authentication sequence: contents of third message
2079 * IEEE 802.11-2016 Chapter 13.8.5 FT authentication sequence: contents of fourth message
2080 * The MIC shall be calculated on the concatenation of the following data, in the order given here:
2081 * —
2082 * — FTO’s MAC address (6 octets)
2083 * — Target AP’s MAC address (6 octets)
2084 * If third message:
2085 * — Transaction sequence number (1 octet), which shall be set to the value 5 if this is a
2086 * Reassociation Request frame and, otherwise, set to the value 3
2087 * If fourth message:
2088 * — Transaction sequence number (1 octet), which shall be set to the value 6 if this is a
2089 * Reassociation Response frame or, otherwise, set to the value 4
2091 * — RSNE
2092 * — MDE
2093 * — FTE, with the MIC field of the FTE set to 0
2094 * — Contents of the RIC-Response (if present)
2096 static int
2097 Dot11DecryptFtMicCheck(
2098 const PDOT11DECRYPT_ASSOC_PARSED assoc_parsed,
2099 const uint8_t *kck,
2100 size_t kck_len)
2102 uint8_t *sta;
2103 uint8_t seq_num;
2104 uint8_t fte_len;
2105 uint16_t mic_len;
2106 uint8_t zeros[16] = { 0 };
2107 gcry_mac_hd_t handle;
2109 fte_len = assoc_parsed->fte_tag[1] + 2;
2110 if (fte_len < 20) {
2111 ws_debug("FTE too short");
2112 return DOT11DECRYPT_RET_UNSUCCESS;
2115 switch (assoc_parsed->frame_subtype) {
2116 case DOT11DECRYPT_SUBTYPE_ASSOC_REQ:
2117 sta = assoc_parsed->sa;
2118 seq_num = 3;
2119 break;
2120 case DOT11DECRYPT_SUBTYPE_ASSOC_RESP:
2121 sta = assoc_parsed->da;
2122 seq_num = 4;
2123 break;
2124 case DOT11DECRYPT_SUBTYPE_REASSOC_REQ:
2125 sta = assoc_parsed->sa;
2126 seq_num = 5;
2127 break;
2128 case DOT11DECRYPT_SUBTYPE_REASSOC_RESP:
2129 sta = assoc_parsed->da;
2130 seq_num = 6;
2131 break;
2132 default:
2133 return DOT11DECRYPT_RET_UNSUCCESS;
2136 if (gcry_mac_open(&handle, GCRY_MAC_CMAC_AES, 0, NULL)) {
2137 ws_warning("gcry_mac_open failed");
2138 return DOT11DECRYPT_RET_UNSUCCESS;
2140 if (gcry_mac_setkey(handle, kck, kck_len)) {
2141 ws_warning("gcry_mac_setkey failed");
2142 gcry_mac_close(handle);
2143 return DOT11DECRYPT_RET_UNSUCCESS;
2145 gcry_mac_write(handle, sta, DOT11DECRYPT_MAC_LEN);
2146 gcry_mac_write(handle, assoc_parsed->bssid, DOT11DECRYPT_MAC_LEN);
2148 gcry_mac_write(handle, &seq_num, 1);
2150 gcry_mac_write(handle, assoc_parsed->rsne_tag, assoc_parsed->rsne_tag[1] + 2);
2151 gcry_mac_write(handle, assoc_parsed->mde_tag, assoc_parsed->mde_tag[1] + 2);
2153 mic_len = assoc_parsed->fte.mic_len;
2154 gcry_mac_write(handle, assoc_parsed->fte_tag, 4);
2155 gcry_mac_write(handle, zeros, mic_len); /* MIC zeroed */
2156 gcry_mac_write(handle, assoc_parsed->fte_tag + 4 + mic_len, fte_len - 4 - mic_len);
2158 if (assoc_parsed->rde_tag) {
2159 gcry_mac_write(handle, assoc_parsed->rde_tag, assoc_parsed->rde_tag[1] + 2);
2162 if (gcry_mac_verify(handle, assoc_parsed->fte.mic, mic_len) != 0) {
2163 DEBUG_DUMP("MIC", assoc_parsed->fte.mic, mic_len, LOG_LEVEL_DEBUG);
2164 ws_debug("MIC verification failed");
2165 gcry_mac_close(handle);
2166 return DOT11DECRYPT_RET_UNSUCCESS;
2168 DEBUG_DUMP("MIC", assoc_parsed->fte.mic, mic_len, LOG_LEVEL_DEBUG);
2169 gcry_mac_close(handle);
2170 return DOT11DECRYPT_RET_SUCCESS;
2173 static int
2174 Dot11DecryptValidateKey(
2175 PDOT11DECRYPT_KEY_ITEM key)
2177 size_t len;
2178 unsigned char ret=true;
2180 if (key==NULL) {
2181 ws_warning("NULL key");
2182 return false;
2185 switch (key->KeyType) {
2186 case DOT11DECRYPT_KEY_TYPE_WEP:
2187 /* check key size limits */
2188 len=key->KeyData.Wep.WepKeyLen;
2189 if (len<DOT11DECRYPT_WEP_KEY_MINLEN || len>DOT11DECRYPT_WEP_KEY_MAXLEN) {
2190 ws_info("WEP key: key length not accepted");
2191 ret=false;
2193 break;
2195 case DOT11DECRYPT_KEY_TYPE_WEP_40:
2196 /* set the standard length and use a generic WEP key type */
2197 key->KeyData.Wep.WepKeyLen=DOT11DECRYPT_WEP_40_KEY_LEN;
2198 key->KeyType=DOT11DECRYPT_KEY_TYPE_WEP;
2199 break;
2201 case DOT11DECRYPT_KEY_TYPE_WEP_104:
2202 /* set the standard length and use a generic WEP key type */
2203 key->KeyData.Wep.WepKeyLen=DOT11DECRYPT_WEP_104_KEY_LEN;
2204 key->KeyType=DOT11DECRYPT_KEY_TYPE_WEP;
2205 break;
2207 case DOT11DECRYPT_KEY_TYPE_WPA_PWD:
2208 /* check passphrase and SSID size limits */
2209 len=strlen(key->UserPwd.Passphrase);
2210 if (len<DOT11DECRYPT_WPA_PASSPHRASE_MIN_LEN || len>DOT11DECRYPT_WPA_PASSPHRASE_MAX_LEN) {
2211 ws_info("WPA-PWD key: passphrase length not accepted");
2212 ret=false;
2215 len=key->UserPwd.SsidLen;
2216 if (len>DOT11DECRYPT_WPA_SSID_MAX_LEN) {
2217 ws_info("WPA-PWD key: ssid length not accepted");
2218 ret=false;
2221 break;
2223 case DOT11DECRYPT_KEY_TYPE_WPA_PSK:
2224 break;
2226 case DOT11DECRYPT_KEY_TYPE_TK:
2227 break;
2229 case DOT11DECRYPT_KEY_TYPE_MSK:
2230 break;
2232 default:
2233 ret=false;
2235 return ret;
2238 static int
2239 Dot11DecryptGetSaAddress(
2240 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame,
2241 DOT11DECRYPT_SEC_ASSOCIATION_ID *id)
2243 if ((DOT11DECRYPT_TYPE(frame->fc[0])==DOT11DECRYPT_TYPE_DATA) &&
2244 (DOT11DECRYPT_DS_BITS(frame->fc[1]) == 0) &&
2245 (memcmp(frame->addr2, frame->addr3, DOT11DECRYPT_MAC_LEN) != 0) &&
2246 (memcmp(frame->addr1, frame->addr3, DOT11DECRYPT_MAC_LEN) != 0)) {
2247 /* DATA frame with fromDS=0 ToDS=0 and neither RA or SA is BSSID
2248 => TDLS traffic. Use highest MAC address for bssid */
2249 if (memcmp(frame->addr1, frame->addr2, DOT11DECRYPT_MAC_LEN) < 0) {
2250 memcpy(id->sta, frame->addr1, DOT11DECRYPT_MAC_LEN);
2251 memcpy(id->bssid, frame->addr2, DOT11DECRYPT_MAC_LEN);
2252 } else {
2253 memcpy(id->sta, frame->addr2, DOT11DECRYPT_MAC_LEN);
2254 memcpy(id->bssid, frame->addr1, DOT11DECRYPT_MAC_LEN);
2256 } else {
2257 const unsigned char *addr;
2259 /* Normal Case: SA between STA and AP */
2260 if ((addr = Dot11DecryptGetBssidAddress(frame)) != NULL) {
2261 memcpy(id->bssid, addr, DOT11DECRYPT_MAC_LEN);
2262 } else {
2263 return DOT11DECRYPT_RET_UNSUCCESS;
2266 if ((addr = Dot11DecryptGetStaAddress(frame)) != NULL) {
2267 memcpy(id->sta, addr, DOT11DECRYPT_MAC_LEN);
2268 } else {
2269 return DOT11DECRYPT_RET_UNSUCCESS;
2272 ws_noisy("BSSID_MAC: %02X.%02X.%02X.%02X.%02X.%02X\t",
2273 id->bssid[0],id->bssid[1],id->bssid[2],id->bssid[3],id->bssid[4],id->bssid[5]);
2274 ws_noisy("STA_MAC: %02X.%02X.%02X.%02X.%02X.%02X\t",
2275 id->sta[0],id->sta[1],id->sta[2],id->sta[3],id->sta[4],id->sta[5]);
2277 return DOT11DECRYPT_RET_SUCCESS;
2281 * Dot11DecryptGetBssidAddress() and Dot11DecryptGetBssidAddress() are used for
2282 * key caching. In each case, it's more important to return a value than
2283 * to return a _correct_ value, so we fudge addresses in some cases, e.g.
2284 * the BSSID in bridged connections.
2285 * FromDS ToDS Sta BSSID
2286 * 0 0 addr1/2 addr3
2287 * 0 1 addr2 addr1
2288 * 1 0 addr1 addr2
2289 * 1 1 addr2 addr1
2292 static const unsigned char *
2293 Dot11DecryptGetStaAddress(
2294 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame)
2296 switch(DOT11DECRYPT_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
2297 case 0:
2298 if (memcmp(frame->addr2, frame->addr3, DOT11DECRYPT_MAC_LEN) == 0)
2299 return frame->addr1;
2300 else
2301 return frame->addr2;
2302 case 1:
2303 return frame->addr2;
2304 case 2:
2305 return frame->addr1;
2306 case 3:
2307 if (memcmp(frame->addr1, frame->addr2, DOT11DECRYPT_MAC_LEN) < 0)
2308 return frame->addr1;
2309 else
2310 return frame->addr2;
2312 default:
2313 return NULL;
2317 static const unsigned char *
2318 Dot11DecryptGetBssidAddress(
2319 const DOT11DECRYPT_MAC_FRAME_ADDR4 *frame)
2321 switch(DOT11DECRYPT_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
2322 case 0:
2323 return frame->addr3;
2324 case 1:
2325 return frame->addr1;
2326 case 2:
2327 return frame->addr2;
2328 case 3:
2329 if (memcmp(frame->addr1, frame->addr2, DOT11DECRYPT_MAC_LEN) > 0)
2330 return frame->addr1;
2331 else
2332 return frame->addr2;
2334 default:
2335 return NULL;
2339 /* From IEEE 802.11-2016 Table 9-131 Cipher suite selectors and
2340 * Table 12-4 Cipher suite key lengths */
2341 static int Dot11DecryptGetTkLen(int cipher)
2343 switch (cipher) {
2344 case 1: return 40; /* WEP-40 */
2345 case 2: return 256; /* TKIP */
2346 case 3: return -1; /* Reserved */
2347 case 4: return 128; /* CCMP-128 */
2348 case 5: return 104; /* WEP-104 */
2349 case 6: return 128; /* BIP-CMAC-128 */
2350 case 7: return -1; /* Group addressed traffic not allowed */
2351 case 8: return 128; /* GCMP-128 */
2352 case 9: return 256; /* GCMP-256 */
2353 case 10: return 256; /* CCMP-256 */
2354 case 11: return 128; /* BIP-GMAC-128 */
2355 case 12: return 256; /* BIP-GMAC-256 */
2356 case 13: return 256; /* BIP-CMAC-256 */
2357 default:
2358 ws_warning("Unknown cipher");
2359 return -1;
2363 /* From IEEE 802.11-2016 Table 12-8 Integrity and key-wrap algorithms */
2364 static int Dot11DecryptGetKckLen(int akm)
2366 switch (akm) {
2367 case 1: return 128;
2368 case 2: return 128;
2369 case 3: return 128;
2370 case 4: return 128;
2371 case 5: return 128;
2372 case 6: return 128;
2373 case 8: return 128;
2374 case 9: return 128;
2375 case 11: return 128;
2376 case 12: return 192;
2377 case 13: return 192;
2378 case 18: return 128;
2379 default:
2380 /* Unknown / Not supported */
2381 ws_warning("Unknown akm");
2382 return -1;
2386 /* From IEEE 802.11-2016 Table 12-8 Integrity and key-wrap algorithms */
2387 static int Dot11DecryptGetKekLen(int akm)
2389 switch (akm) {
2390 case 1: return 128;
2391 case 2: return 128;
2392 case 3: return 128;
2393 case 4: return 128;
2394 case 5: return 128;
2395 case 6: return 128;
2396 case 8: return 128;
2397 case 9: return 128;
2398 case 11: return 128;
2399 case 12: return 256;
2400 case 13: return 256;
2401 case 18: return 128;
2402 default:
2403 /* Unknown / Not supported */
2404 ws_warning("Unknown akm");
2405 return -1;
2409 /* From IEEE 802.11-2016 9.4.2.25.3 AKM suites and
2410 * Table 12-8 Integrity and key-wrap algorithms */
2411 static int Dot11DecryptGetPtkLen(int akm, int cipher)
2413 int kck_len = Dot11DecryptGetKckLen(akm);
2414 int kek_len = Dot11DecryptGetKekLen(akm);
2415 int tk_len = Dot11DecryptGetTkLen(cipher);
2417 if (kck_len == -1 || kek_len == -1 || tk_len == -1) {
2418 ws_warning("Invalid PTK len");
2419 return -1;
2421 return kck_len + kek_len + tk_len;
2424 /* From IEEE 802.11-2016 12.7.1.2 PRF and Table 9-133 AKM suite selectors */
2425 static int
2426 Dot11DecryptGetDeriveFuncFromAkm(int akm)
2428 int func = -1;
2429 switch (akm) {
2430 case 1:
2431 case 2:
2432 func = DOT11DECRYPT_DERIVE_USING_PRF;
2433 break;
2434 case 3:
2435 case 4:
2436 case 5:
2437 case 6:
2438 case 7:
2439 case 8:
2440 case 9:
2441 case 10:
2442 case 11:
2443 case 12:
2444 case 13:
2445 case 18:
2446 func = DOT11DECRYPT_DERIVE_USING_KDF;
2447 break;
2448 default:
2449 /* Unknown / Not supported yet */
2450 break;
2452 return func;
2455 /* From IEEE 802.11-2016 12.7.1.2 PRF and Table 9-133 AKM suite selectors */
2456 static int
2457 Dot11DecryptGetHashAlgoFromAkm(int akm)
2459 int algo = -1;
2460 switch (akm) {
2461 case 1:
2462 case 2:
2463 algo = GCRY_MD_SHA1;
2464 break;
2465 case 3:
2466 case 4:
2467 case 5:
2468 case 6:
2469 case 7:
2470 case 8:
2471 case 9:
2472 case 10:
2473 case 11:
2474 case 18:
2475 algo = GCRY_MD_SHA256;
2476 break;
2477 case 12:
2478 case 13:
2479 algo = GCRY_MD_SHA384;
2480 break;
2481 default:
2482 /* Unknown / Not supported yet */
2483 break;
2485 return algo;
2488 /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */
2489 /** From IEEE 802.11-2016 12.7.1.3 Pairwise key hierarchy:
2490 * PRF-Length(PMK, "Pairwise key expansion",
2491 * Min(AA, SPA) || Max(AA, SPA) ||
2492 * Min(ANonce, SNonce) || Max(ANonce, SNonce))
2494 static uint8_t
2495 Dot11DecryptDerivePtk(
2496 const DOT11DECRYPT_SEC_ASSOCIATION *sa,
2497 const unsigned char *pmk,
2498 size_t pmk_len,
2499 const unsigned char snonce[32],
2500 int key_version,
2501 int akm,
2502 int cipher,
2503 uint8_t *ptk, size_t *ptk_len)
2505 int algo = -1;
2506 int ptk_len_bits = -1;
2507 int derive_func;
2509 if (!sa || !pmk || !snonce || !ptk || !ptk_len) {
2510 ws_warning("Invalid input for PTK derivation");
2511 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2514 if (key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP) {
2515 /* TKIP */
2516 ptk_len_bits = 512;
2517 derive_func = DOT11DECRYPT_DERIVE_USING_PRF;
2518 algo = GCRY_MD_SHA1;
2519 } else {
2520 /* From IEEE 802.11-2016 Table 12-8 Integrity and key-wrap algorithms */
2521 ptk_len_bits = Dot11DecryptGetPtkLen(akm, cipher);
2522 algo = Dot11DecryptGetHashAlgoFromAkm(akm);
2523 derive_func = Dot11DecryptGetDeriveFuncFromAkm(akm);
2524 ws_debug("ptk_len_bits: %d, algo: %d, cipher: %d", ptk_len_bits, algo, cipher);
2527 if (ptk_len_bits == -1 || algo == -1) {
2528 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2530 *ptk_len = ptk_len_bits / 8;
2532 static const char *const label = "Pairwise key expansion";
2533 uint8_t context[DOT11DECRYPT_MAC_LEN * 2 + 32 * 2];
2534 int offset = 0;
2536 /* Min(AA, SPA) || Max(AA, SPA) */
2537 if (memcmp(sa->saId.sta, sa->saId.bssid, DOT11DECRYPT_MAC_LEN) < 0)
2539 memcpy(context + offset, sa->saId.sta, DOT11DECRYPT_MAC_LEN);
2540 offset += DOT11DECRYPT_MAC_LEN;
2541 memcpy(context + offset, sa->saId.bssid, DOT11DECRYPT_MAC_LEN);
2542 offset += DOT11DECRYPT_MAC_LEN;
2544 else
2546 memcpy(context + offset, sa->saId.bssid, DOT11DECRYPT_MAC_LEN);
2547 offset += DOT11DECRYPT_MAC_LEN;
2548 memcpy(context + offset, sa->saId.sta, DOT11DECRYPT_MAC_LEN);
2549 offset += DOT11DECRYPT_MAC_LEN;
2552 /* Min(ANonce, SNonce) || Max(ANonce, SNonce) */
2553 if (memcmp(snonce, sa->wpa.nonce, 32) < 0 )
2555 memcpy(context + offset, snonce, 32);
2556 offset += 32;
2557 memcpy(context + offset, sa->wpa.nonce, 32);
2558 offset += 32;
2560 else
2562 memcpy(context + offset, sa->wpa.nonce, 32);
2563 offset += 32;
2564 memcpy(context + offset, snonce, 32);
2565 offset += 32;
2567 if (derive_func == DOT11DECRYPT_DERIVE_USING_PRF) {
2568 dot11decrypt_prf(pmk, pmk_len, label, context, offset, algo,
2569 ptk, *ptk_len);
2570 } else {
2571 dot11decrypt_kdf(pmk, pmk_len, label, context, offset, algo,
2572 ptk, *ptk_len);
2574 DEBUG_DUMP("PTK", ptk, *ptk_len, LOG_LEVEL_DEBUG);
2575 return DOT11DECRYPT_RET_SUCCESS;
2579 * For Fast BSS Transition AKMS derive PTK from sa, selected key and various information in
2580 * eapol key frame.
2581 * From IEEE 802.11-2016 12.7.1.7.1
2583 static uint8_t
2584 Dot11DecryptFtDerivePtk(
2585 const PDOT11DECRYPT_CONTEXT ctx,
2586 const DOT11DECRYPT_SEC_ASSOCIATION *sa,
2587 const PDOT11DECRYPT_KEY_ITEM key,
2588 const uint8_t mdid[2],
2589 const uint8_t *snonce,
2590 const uint8_t *r0kh_id, size_t r0kh_id_len,
2591 const uint8_t *r1kh_id, size_t r1kh_id_len _U_,
2592 int akm, int cipher,
2593 uint8_t *ptk, size_t *ptk_len)
2595 int hash_algo = Dot11DecryptGetHashAlgoFromAkm(akm);
2596 uint8_t pmk_r0[DOT11DECRYPT_WPA_PMK_MAX_LEN];
2597 uint8_t pmk_r1[DOT11DECRYPT_WPA_PMK_MAX_LEN];
2598 uint8_t pmk_r0_name[16] = {0};
2599 uint8_t pmk_r1_name[16] = {0};
2600 uint8_t ptk_name[16];
2601 size_t pmk_r0_len = 0;
2602 size_t pmk_r1_len = 0;
2603 const uint8_t *xxkey = NULL;
2604 size_t xxkey_len;
2605 int ptk_len_bits;
2607 if (!sa || !key || !mdid || !snonce || !r0kh_id || !r1kh_id || !ptk || !ptk_len) {
2608 ws_warning("Invalid input for FT PTK derivation");
2609 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2611 ptk_len_bits = Dot11DecryptGetPtkLen(akm, cipher);
2612 if (ptk_len_bits == -1) {
2613 ws_warning("Invalid akm or cipher");
2614 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2616 *ptk_len = ptk_len_bits / 8;
2618 if (key->KeyType == DOT11DECRYPT_KEY_TYPE_MSK) {
2619 xxkey = Dot11DecryptGetXXKeyFromMSK(key->Msk.Msk,
2620 key->Msk.Len,
2621 akm,
2622 &xxkey_len);
2624 if (!xxkey && key->KeyData.Wpa.PskLen > 0) {
2625 xxkey = key->KeyData.Wpa.Psk;
2626 xxkey_len = key->KeyData.Wpa.PskLen;
2628 if (!xxkey) {
2629 ws_debug("no xxkey. Skipping");
2630 return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
2632 if (!dot11decrypt_derive_pmk_r0(xxkey, xxkey_len,
2633 ctx->pkt_ssid, ctx->pkt_ssid_len,
2634 mdid,
2635 r0kh_id, r0kh_id_len,
2636 sa->saId.sta, hash_algo,
2637 pmk_r0, &pmk_r0_len, pmk_r0_name)) {
2638 /* This can fail for bad size or a bad SHA256 sum. */
2639 return DOT11DECRYPT_RET_UNSUCCESS;
2641 DEBUG_DUMP("PMK-R0", pmk_r0, pmk_r0_len, LOG_LEVEL_DEBUG);
2642 DEBUG_DUMP("PMKR0Name", pmk_r0_name, 16, LOG_LEVEL_DEBUG);
2644 if (!dot11decrypt_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name,
2645 r1kh_id, sa->saId.sta, hash_algo,
2646 pmk_r1, &pmk_r1_len, pmk_r1_name)) {
2647 return DOT11DECRYPT_RET_UNSUCCESS;
2649 DEBUG_DUMP("PMK-R1", pmk_r1, pmk_r1_len, LOG_LEVEL_DEBUG);
2650 DEBUG_DUMP("PMKR1Name", pmk_r1_name, 16, LOG_LEVEL_DEBUG);
2652 if (!dot11decrypt_derive_ft_ptk(pmk_r1, pmk_r1_len, pmk_r1_name,
2653 snonce, sa->wpa.nonce,
2654 sa->saId.bssid, sa->saId.sta, hash_algo,
2655 ptk, *ptk_len, ptk_name)) {
2656 return DOT11DECRYPT_RET_UNSUCCESS;
2658 DEBUG_DUMP("PTK", ptk, *ptk_len, LOG_LEVEL_DEBUG);
2659 return DOT11DECRYPT_RET_SUCCESS;
2662 #define MAX_SSID_LENGTH 32 /* maximum SSID length */
2664 static int
2665 Dot11DecryptRsnaPwd2PskStep(
2666 const uint8_t *ppBytes,
2667 const unsigned ppLength,
2668 const char *ssid,
2669 const size_t ssidLength,
2670 const int iterations,
2671 const int count,
2672 unsigned char *output)
2674 unsigned char digest[MAX_SSID_LENGTH+4] = { 0 }; /* SSID plus 4 bytes of count */
2675 int i, j;
2677 if (ssidLength > MAX_SSID_LENGTH) {
2678 /* This "should not happen" */
2679 return DOT11DECRYPT_RET_UNSUCCESS;
2682 /* U1 = PRF(P, S || int(i)) */
2683 memcpy(digest, ssid, ssidLength);
2684 digest[ssidLength] = (unsigned char)((count>>24) & 0xff);
2685 digest[ssidLength+1] = (unsigned char)((count>>16) & 0xff);
2686 digest[ssidLength+2] = (unsigned char)((count>>8) & 0xff);
2687 digest[ssidLength+3] = (unsigned char)(count & 0xff);
2688 if (ws_hmac_buffer(GCRY_MD_SHA1, digest, digest, (uint32_t) ssidLength + 4, ppBytes, ppLength)) {
2689 return DOT11DECRYPT_RET_UNSUCCESS;
2692 /* output = U1 */
2693 memcpy(output, digest, 20);
2694 for (i = 1; i < iterations; i++) {
2695 /* Un = PRF(P, Un-1) */
2696 if (ws_hmac_buffer(GCRY_MD_SHA1, digest, digest, HASH_SHA1_LENGTH, ppBytes, ppLength)) {
2697 return DOT11DECRYPT_RET_UNSUCCESS;
2700 /* output = output xor Un */
2701 for (j = 0; j < 20; j++) {
2702 output[j] ^= digest[j];
2706 return DOT11DECRYPT_RET_SUCCESS;
2709 static int
2710 Dot11DecryptRsnaPwd2Psk(
2711 const struct DOT11DECRYPT_KEY_ITEMDATA_PWD *userPwd,
2712 unsigned char *output)
2714 unsigned char m_output[40] = { 0 };
2715 GByteArray *pp_ba = g_byte_array_new();
2717 g_byte_array_append(pp_ba, userPwd->Passphrase, (unsigned)userPwd->PassphraseLen);
2719 Dot11DecryptRsnaPwd2PskStep(pp_ba->data, pp_ba->len, userPwd->Ssid, userPwd->SsidLen, 4096, 1, m_output);
2720 Dot11DecryptRsnaPwd2PskStep(pp_ba->data, pp_ba->len, userPwd->Ssid, userPwd->SsidLen, 4096, 2, &m_output[20]);
2722 memcpy(output, m_output, DOT11DECRYPT_WPA_PWD_PSK_LEN);
2723 g_byte_array_free(pp_ba, true);
2725 return 0;
2729 * Returns the decryption_key_t struct given a string describing the key.
2730 * Returns NULL if the input_string cannot be parsed.
2731 * XXX: Should return an error string explaining why parsing failed
2733 decryption_key_t*
2734 parse_key_string(char* input_string, uint8_t key_type, char** error)
2736 GByteArray *ssid_ba = NULL, *key_ba;
2738 char **tokens;
2739 unsigned n = 0;
2740 decryption_key_t *dk;
2742 if(input_string == NULL || (strcmp(input_string, "") == 0)) {
2743 if (error) {
2744 *error = g_strdup("Key cannot be empty");
2746 return NULL;
2750 * Parse the input_string. WEP and WPA will be just a string
2751 * of hexadecimal characters (if key is wrong, null will be
2752 * returned...).
2753 * WPA-PWD should be in the form
2754 * <key data>[:<ssid>]
2755 * With WPA-PWD, we percent-decode the key data and ssid.
2756 * The percent itself ("%25") and the colon ("%3a") must be
2757 * percent-encoded, the latter so we can distinguish between the
2758 * separator and a colon in the key or ssid. Percent-encoding
2759 * for anything else is optional. (NUL is not allowed, either
2760 * percent-encoded or not.)
2763 switch(key_type)
2765 case DOT11DECRYPT_KEY_TYPE_WEP:
2766 case DOT11DECRYPT_KEY_TYPE_WEP_40:
2767 case DOT11DECRYPT_KEY_TYPE_WEP_104:
2769 key_ba = g_byte_array_new();
2771 if (!hex_str_to_bytes(input_string, key_ba, false)) {
2772 if (error) {
2773 *error = g_strdup("WEP key must be a hexadecimal string");
2775 g_byte_array_free(key_ba, true);
2776 return NULL;
2779 if (key_ba->len > 0 && key_ba->len <= DOT11DECRYPT_WEP_KEY_MAXLEN) {
2780 /* Key is correct! It was probably an 'old style' WEP key */
2781 /* Create the decryption_key_t structure, fill it and return it*/
2782 dk = g_new(decryption_key_t, 1);
2784 dk->type = DOT11DECRYPT_KEY_TYPE_WEP;
2785 dk->key = key_ba;
2786 dk->bits = key_ba->len * 8;
2787 dk->ssid = NULL;
2789 return dk;
2792 if (error) {
2793 *error = ws_strdup_printf("WEP key entered is %u bytes, and must be no more than %u", key_ba->len, DOT11DECRYPT_WEP_KEY_MAXLEN);
2795 /* Key doesn't work */
2796 g_byte_array_free(key_ba, true);
2797 return NULL;
2799 case DOT11DECRYPT_KEY_TYPE_WPA_PWD:
2801 tokens = g_strsplit(input_string,":", 3);
2802 n = g_strv_length(tokens);
2804 if (n < 1 || n > 2)
2806 /* Require either one or two tokens; more, and the user
2807 * may have meant a colon in the passphrase or SSID name
2809 /* Free the array of strings */
2810 /* XXX: Return why parsing failed (":" must be escaped) */
2811 if (error) {
2812 *error = g_strdup("Only one ':' is allowed, as a separator between passphrase and SSID; others must be percent-encoded as \"%%3a\"");
2814 g_strfreev(tokens);
2815 return NULL;
2819 * The first token is the key
2821 key_ba = g_byte_array_new();
2822 if (! uri_str_to_bytes(tokens[0], key_ba)) {
2823 /* Failed parsing as percent-encoded */
2824 if (error) {
2825 *error = g_strdup("WPA passphrase is treated as percent-encoded; use \"%%25\" for a literal \"%%\"");
2827 g_byte_array_free(key_ba, true);
2828 g_strfreev(tokens);
2829 return NULL;
2832 /* key length (after percent-decoding) should be between 8 and 63
2833 * octets (63 to distinguish from a PSK as 64 hex characters.)
2834 * XXX: 802.11-2016 Annex J assumes that each character in the
2835 * pass-phrase is ASCII printable ("has an encoding in the range
2836 * 32 to 126"), though this (and the entire algorithm for that
2837 * matter) is only considered a suggestion.
2838 * It is possible to apply PBKDF2 to any octet string, e.g. UTF-8.
2839 * (wpa_passphrase from wpa_supplicant will do so, for example.)
2841 if( ((key_ba->len) > WPA_KEY_MAX_CHAR_SIZE) || ((key_ba->len) < WPA_KEY_MIN_CHAR_SIZE))
2843 if (error) {
2844 *error = ws_strdup_printf("WPA passphrase entered is %u characters after percent-decoding and must be between %u and %u", key_ba->len, WPA_KEY_MIN_CHAR_SIZE, WPA_KEY_MAX_CHAR_SIZE);
2846 g_byte_array_free(key_ba, true);
2848 /* Free the array of strings */
2849 g_strfreev(tokens);
2850 return NULL;
2853 ssid_ba = NULL;
2854 if (n >= 2) /* more than two tokens found, means that the user specified the ssid */
2856 ssid_ba = g_byte_array_new();
2857 if (! uri_str_to_bytes(tokens[1], ssid_ba)) {
2858 if (error) {
2859 *error = g_strdup("WPA SSID is treated as percent-encoded; use \"%%25\" for a literal \"%%\".");
2861 g_byte_array_free(key_ba, true);
2862 g_byte_array_free(ssid_ba, true);
2863 /* Free the array of strings */
2864 g_strfreev(tokens);
2865 return NULL;
2868 if(ssid_ba->len > WPA_SSID_MAX_CHAR_SIZE)
2870 if (error) {
2871 *error = ws_strdup_printf("WPA SSID entered is %u characters after percent-decoding and must be no more than %u", ssid_ba->len, WPA_SSID_MAX_CHAR_SIZE);
2873 g_byte_array_free(key_ba, true);
2874 g_byte_array_free(ssid_ba, true);
2876 /* Free the array of strings */
2877 g_strfreev(tokens);
2878 return NULL;
2882 /* Key was correct!!! Create the new decryption_key_t ... */
2883 dk = g_new(decryption_key_t, 1);
2885 dk->type = DOT11DECRYPT_KEY_TYPE_WPA_PWD;
2886 dk->key = key_ba;
2887 dk->bits = 256; /* This is the length of the array pf bytes that will be generated using key+ssid ...*/
2888 dk->ssid = ssid_ba; /* NULL if ssid_ba is NULL */
2890 /* Free the array of strings */
2891 g_strfreev(tokens);
2892 return dk;
2894 case DOT11DECRYPT_KEY_TYPE_WPA_PSK:
2896 key_ba = g_byte_array_new();
2897 if (!hex_str_to_bytes(input_string, key_ba, false)) {
2898 if (error) {
2899 *error = g_strdup("WPA PSK/PMK must be a hexadecimal string");
2901 g_byte_array_free(key_ba, true);
2902 return NULL;
2905 /* Two tokens means that the user should have entered a WPA-BIN key ... */
2906 if((key_ba->len != DOT11DECRYPT_WPA_PWD_PSK_LEN &&
2907 key_ba->len != DOT11DECRYPT_WPA_PMK_MAX_LEN))
2909 if (error) {
2910 *error = ws_strdup_printf("WPA Pre-Master Key/Pairwise Master Key entered is %u bytes and must be %u or %u", key_ba->len, DOT11DECRYPT_WPA_PWD_PSK_LEN, DOT11DECRYPT_WPA_PMK_MAX_LEN);
2912 g_byte_array_free(key_ba, true);
2913 return NULL;
2916 /* Key was correct!!! Create the new decryption_key_t ... */
2917 dk = g_new(decryption_key_t, 1);
2919 dk->type = DOT11DECRYPT_KEY_TYPE_WPA_PSK;
2920 dk->key = key_ba;
2921 dk->bits = (unsigned) dk->key->len * 8;
2922 dk->ssid = NULL;
2924 return dk;
2926 case DOT11DECRYPT_KEY_TYPE_TK:
2928 /* From IEEE 802.11-2016 Table 12-4 Cipher suite key lengths */
2929 static const uint8_t allowed_key_lengths[] = {
2930 // TBD 40 / 8, /* WEP-40 */
2931 // TBD 104 / 8, /* WEP-104 */
2932 128 / 8, /* CCMP-128, GCMP-128 */
2933 256 / 8, /* TKIP, GCMP-256, CCMP-256 */
2935 bool key_length_ok = false;
2937 key_ba = g_byte_array_new();
2938 if (!hex_str_to_bytes(input_string, key_ba, false)) {
2939 if (error) {
2940 *error = g_strdup("Temporal Key must be a hexadecimal string");
2942 g_byte_array_free(key_ba, true);
2943 return NULL;
2946 for (size_t i = 0; i < sizeof(allowed_key_lengths); i++) {
2947 if (key_ba->len == allowed_key_lengths[i]) {
2948 key_length_ok = true;
2949 break;
2952 if (!key_length_ok) {
2953 if (error) {
2954 GString *err_string = g_string_new("Temporal Keys entered is ");
2955 g_string_append_printf(err_string, "%u bytes and must be ", key_ba->len);
2956 size_t i = 0;
2957 for (; i + 1 < sizeof(allowed_key_lengths); i++) {
2958 g_string_append_printf(err_string, "%u, ", allowed_key_lengths[i]);
2960 g_string_append_printf(err_string, "or %u bytes.", allowed_key_lengths[i]);
2961 *error = g_string_free(err_string, FALSE);
2963 g_byte_array_free(key_ba, true);
2964 return NULL;
2966 dk = g_new(decryption_key_t, 1);
2967 dk->type = DOT11DECRYPT_KEY_TYPE_TK;
2968 dk->key = key_ba;
2969 dk->bits = (unsigned) dk->key->len * 8;
2970 dk->ssid = NULL;
2972 return dk;
2974 case DOT11DECRYPT_KEY_TYPE_MSK:
2976 key_ba = g_byte_array_new();
2977 if (!hex_str_to_bytes(input_string, key_ba, false)) {
2978 if (error) {
2979 *error = g_strdup("Master Session Key must be a hexadecimal string");
2981 g_byte_array_free(key_ba, true);
2982 return NULL;
2985 if (key_ba->len < DOT11DECRYPT_MSK_MIN_LEN ||
2986 key_ba->len > DOT11DECRYPT_MSK_MAX_LEN)
2988 if (error) {
2989 *error = ws_strdup_printf("Master Session Key entered is %u bytes and must be between %u and %u", key_ba->len, DOT11DECRYPT_MSK_MIN_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 = key_ba;
2997 dk->bits = (unsigned)dk->key->len * 8;
2998 dk->ssid = NULL;
2999 return dk;
3003 /* Type not supported */
3004 if (error) {
3005 *error = g_strdup("Unknown key type not supported");
3007 return NULL;
3010 void
3011 free_key_string(decryption_key_t *dk)
3013 if (dk->key)
3014 g_byte_array_free(dk->key, true);
3015 if (dk->ssid)
3016 g_byte_array_free(dk->ssid, true);
3017 g_free(dk);
3020 static int
3021 Dot11DecryptTDLSDeriveKey(
3022 PDOT11DECRYPT_SEC_ASSOCIATION sa,
3023 const uint8_t *data,
3024 unsigned offset_rsne,
3025 unsigned offset_fte,
3026 unsigned offset_timeout,
3027 unsigned offset_link,
3028 uint8_t action)
3031 gcry_md_hd_t sha256_handle;
3032 gcry_md_hd_t hmac_handle;
3033 const uint8_t *snonce, *anonce, *initiator, *responder, *bssid;
3034 uint8_t key_input[32];
3035 uint8_t mic[16], seq_num = action + 1;
3036 uint8_t zeros[16] = { 0 };
3037 gcry_mac_hd_t cmac_handle;
3038 size_t cmac_len = 16;
3039 size_t cmac_write_len;
3041 /* Get key input */
3042 anonce = &data[offset_fte + 20];
3043 snonce = &data[offset_fte + 52];
3045 if (gcry_md_open (&sha256_handle, GCRY_MD_SHA256, 0)) {
3046 return DOT11DECRYPT_RET_UNSUCCESS;
3048 if (memcmp(anonce, snonce, DOT11DECRYPT_WPA_NONCE_LEN) < 0) {
3049 gcry_md_write(sha256_handle, anonce, DOT11DECRYPT_WPA_NONCE_LEN);
3050 gcry_md_write(sha256_handle, snonce, DOT11DECRYPT_WPA_NONCE_LEN);
3051 } else {
3052 gcry_md_write(sha256_handle, snonce, DOT11DECRYPT_WPA_NONCE_LEN);
3053 gcry_md_write(sha256_handle, anonce, DOT11DECRYPT_WPA_NONCE_LEN);
3055 memcpy(key_input, gcry_md_read(sha256_handle, 0), 32);
3056 gcry_md_close(sha256_handle);
3058 /* Derive key */
3059 bssid = &data[offset_link + 2];
3060 initiator = &data[offset_link + 8];
3061 responder = &data[offset_link + 14];
3062 if (gcry_md_open(&hmac_handle, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC)) {
3063 return DOT11DECRYPT_RET_UNSUCCESS;
3065 if (gcry_md_setkey(hmac_handle, key_input, 32)) {
3066 gcry_md_close(hmac_handle);
3067 return DOT11DECRYPT_RET_UNSUCCESS;
3069 gcry_md_putc(hmac_handle, 1);
3070 gcry_md_putc(hmac_handle, 0);
3071 gcry_md_write(hmac_handle, "TDLS PMK", 8);
3072 if (memcmp(initiator, responder, DOT11DECRYPT_MAC_LEN) < 0) {
3073 gcry_md_write(hmac_handle, initiator, DOT11DECRYPT_MAC_LEN);
3074 gcry_md_write(hmac_handle, responder, DOT11DECRYPT_MAC_LEN);
3075 } else {
3076 gcry_md_write(hmac_handle, responder, DOT11DECRYPT_MAC_LEN);
3077 gcry_md_write(hmac_handle, initiator, DOT11DECRYPT_MAC_LEN);
3079 gcry_md_write(hmac_handle, bssid, DOT11DECRYPT_MAC_LEN);
3080 gcry_md_putc(hmac_handle, 0);
3081 gcry_md_putc(hmac_handle, 1);
3082 memcpy(key_input, gcry_md_read(hmac_handle, 0), 32);
3083 gcry_md_close(hmac_handle);
3085 /* Check MIC */
3086 if (gcry_mac_open(&cmac_handle, GCRY_MAC_CMAC_AES, 0, NULL)) {
3087 return DOT11DECRYPT_RET_UNSUCCESS;
3089 if (gcry_mac_setkey(cmac_handle, key_input, 16)) {
3090 gcry_mac_close(cmac_handle);
3091 return DOT11DECRYPT_RET_UNSUCCESS;
3093 gcry_mac_write(cmac_handle, initiator, DOT11DECRYPT_MAC_LEN);
3094 gcry_mac_write(cmac_handle, responder, DOT11DECRYPT_MAC_LEN);
3095 gcry_mac_write(cmac_handle, &seq_num, 1);
3096 gcry_mac_write(cmac_handle, &data[offset_link], data[offset_link + 1] + 2);
3097 gcry_mac_write(cmac_handle, &data[offset_rsne], data[offset_rsne + 1] + 2);
3098 gcry_mac_write(cmac_handle, &data[offset_timeout], data[offset_timeout + 1] + 2);
3099 gcry_mac_write(cmac_handle, &data[offset_fte], 4);
3100 gcry_mac_write(cmac_handle, zeros, 16);
3101 cmac_write_len = data[offset_fte + 1] + 2;
3102 if (cmac_write_len < 20) {
3103 ws_warning("Bad MAC len");
3104 gcry_mac_close(cmac_handle);
3105 return DOT11DECRYPT_RET_UNSUCCESS;
3107 gcry_mac_write(cmac_handle, &data[offset_fte + 20], cmac_write_len - 20);
3108 if (gcry_mac_read(cmac_handle, mic, &cmac_len) != GPG_ERR_NO_ERROR) {
3109 ws_warning("MAC read error");
3110 gcry_mac_close(cmac_handle);
3111 return DOT11DECRYPT_RET_UNSUCCESS;
3113 if (memcmp(mic, &data[offset_fte + 4], 16)) {
3114 ws_debug("MIC verification failed");
3115 gcry_mac_close(cmac_handle);
3116 return DOT11DECRYPT_RET_UNSUCCESS;
3118 gcry_mac_close(cmac_handle);
3119 /* TODO support other akm and ciphers? */
3120 sa->wpa.akm = 2;
3121 sa->wpa.cipher = 4;
3122 sa->wpa.ptk_len = Dot11DecryptGetPtkLen(sa->wpa.akm, sa->wpa.cipher) / 8;
3123 memcpy(DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
3124 key_input + 16, Dot11DecryptGetTkLen(sa->wpa.cipher) / 8);
3125 memcpy(sa->wpa.nonce, snonce, DOT11DECRYPT_WPA_NONCE_LEN);
3126 sa->validKey = true;
3127 sa->wpa.key_ver = DOT11DECRYPT_WPA_KEY_VER_AES_CCMP;
3128 ws_debug("MIC verified");
3129 return DOT11DECRYPT_RET_SUCCESS;
3133 #ifdef __cplusplus
3135 #endif
3137 /****************************************************************************/
3140 * Editor modelines
3142 * Local Variables:
3143 * c-basic-offset: 4
3144 * tab-width: 8
3145 * indent-tabs-mode: nil
3146 * End:
3148 * ex: set shiftwidth=4 tabstop=8 expandtab:
3149 * :indentSize=4:tabSize=8:noTabs=true: