4 * Copyright (c) 2006 CACE Technologies, Davis (California)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
23 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 /****************************************************************************/
43 #include <epan/tvbuff.h>
44 #include <epan/crc32.h>
45 #include <epan/strutil.h>
46 #include <epan/emem.h>
47 #include <epan/pint.h>
48 #include <epan/crypt/crypt-rc4.h>
49 #include <epan/crypt/airpdcap_rijndael.h>
51 #include "airpdcap_system.h"
52 #include "airpdcap_int.h"
54 #include "crypt-sha1.h"
55 #include "crypt-md5.h"
57 #include "airpdcap_debug.h"
59 #include "wep-wpadefs.h"
62 /****************************************************************************/
64 /****************************************************************************/
65 /* Constant definitions */
67 #define AIRPDCAP_SHA_DIGEST_LEN 20
69 /* EAPOL definitions */
71 * Length of the EAPOL-Key key confirmation key (KCK) used to calculate
72 * MIC over EAPOL frame and validate an EAPOL packet (128 bits)
74 #define AIRPDCAP_WPA_KCK_LEN 16
76 *Offset of the Key MIC in the EAPOL packet body
78 #define AIRPDCAP_WPA_MICKEY_OFFSET 77
80 * Maximum length of the EAPOL packet (it depends on the maximum MAC
83 #define AIRPDCAP_WPA_MAX_EAPOL_LEN 4095
85 * EAPOL Key Descriptor Version 1, used for all EAPOL-Key frames to and
86 * from a STA when neither the group nor pairwise ciphers are CCMP for
89 * Defined in 802.11i-2004, page 78
91 #define AIRPDCAP_WPA_KEY_VER_NOT_CCMP 1
93 * EAPOL Key Descriptor Version 2, used for all EAPOL-Key frames to and
94 * from a STA when either the pairwise or the group cipher is AES-CCMP
95 * for Key Descriptor 2.
97 * Defined in 802.11i-2004, page 78
99 #define AIRPDCAP_WPA_KEY_VER_AES_CCMP 2
101 /** Define EAPOL Key Descriptor type values: use 254 for WPA and 2 for WPA2 **/
102 #define AIRPDCAP_RSN_WPA_KEY_DESCRIPTOR 254
103 #define AIRPDCAP_RSN_WPA2_KEY_DESCRIPTOR 2
105 /****************************************************************************/
109 /****************************************************************************/
110 /* Macro definitions */
112 extern const UINT32 crc32_table[256];
113 #define CRC(crc, ch) (crc = (crc >> 8) ^ crc32_table[(crc ^ (ch)) & 0xff])
115 #define AIRPDCAP_GET_TK(ptk) (ptk + 32)
117 /****************************************************************************/
119 /****************************************************************************/
120 /* Type definitions */
122 /* Internal function prototype declarations */
129 * It is a step of the PBKDF2 (specifically the PKCS #5 v2.0) defined in
130 * the RFC 2898 to derive a key (used as PMK in WPA)
131 * @param password [IN] pointer to a password (sequence of between 8 and
132 * 63 ASCII encoded characters)
133 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
135 * @param iterations [IN] times to hash the password (4096 for WPA)
136 * @param count [IN] ???
137 * @param output [OUT] pointer to a preallocated buffer of
138 * AIRPDCAP_SHA_DIGEST_LEN characters that will contain a part of the key
140 static INT AirPDcapRsnaPwd2PskStep(
141 const guint8 *ppbytes,
142 const guint passLength,
144 const size_t ssidLength,
145 const INT iterations,
151 * It calculates the passphrase-to-PSK mapping reccomanded for use with
152 * RSNAs. This implementation uses the PBKDF2 method defined in the RFC
154 * @param password [IN] pointer to a password (sequence of between 8 and
155 * 63 ASCII encoded characters)
156 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
158 * @param output [OUT] calculated PSK (to use as PMK in WPA)
160 * Described in 802.11i-2004, page 165
162 static INT AirPDcapRsnaPwd2Psk(
163 const CHAR *passphrase,
165 const size_t ssidLength,
169 static INT AirPDcapRsnaMng(
171 guint mac_header_len,
173 PAIRPDCAP_KEY_ITEM key,
174 AIRPDCAP_SEC_ASSOCIATION *sa,
178 static INT AirPDcapWepMng(
179 PAIRPDCAP_CONTEXT ctx,
181 guint mac_header_len,
183 PAIRPDCAP_KEY_ITEM key,
184 AIRPDCAP_SEC_ASSOCIATION *sa,
188 static INT AirPDcapRsna4WHandshake(
189 PAIRPDCAP_CONTEXT ctx,
191 AIRPDCAP_SEC_ASSOCIATION *sa,
192 PAIRPDCAP_KEY_ITEM key,
196 * It checks whether the specified key is corrected or not.
198 * For a standard WEP key the length will be changed to the standard
199 * length, and the type changed in a generic WEP key.
200 * @param key [IN] pointer to the key to validate
202 * - TRUE: the key contains valid fields and values
203 * - FALSE: the key has some invalid field or value
205 static INT AirPDcapValidateKey(
206 PAIRPDCAP_KEY_ITEM key)
209 static INT AirPDcapRsnaMicCheck(
212 UCHAR KCK[AIRPDCAP_WPA_KCK_LEN],
217 * @param ctx [IN] pointer to the current context
218 * @param id [IN] id of the association (composed by BSSID and MAC of
221 * - index of the Security Association structure if found
222 * - -1, if the specified addresses pair BSSID-STA MAC has not been found
224 static INT AirPDcapGetSa(
225 PAIRPDCAP_CONTEXT ctx,
226 AIRPDCAP_SEC_ASSOCIATION_ID *id)
229 static INT AirPDcapStoreSa(
230 PAIRPDCAP_CONTEXT ctx,
231 AIRPDCAP_SEC_ASSOCIATION_ID *id)
234 static const UCHAR * AirPDcapGetStaAddress(
235 const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
238 static const UCHAR * AirPDcapGetBssidAddress(
239 const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
242 static void AirPDcapRsnaPrfX(
243 AIRPDCAP_SEC_ASSOCIATION *sa,
245 const UCHAR snonce[32],
246 const INT x, /* for TKIP 512, for CCMP 384 */
254 /****************************************************************************/
256 /****************************************************************************/
257 /* Exported function definitions */
263 const guint8 broadcast_mac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
266 /* NOTE : this assumes the WPA RSN IE format. If it were to be a generic RSN IE, then
267 we would need to change the structure since it could be variable length depending on the number
268 of unicast OUI and auth OUI. */
274 guint8 multicastOUI[4];
275 guint16 iUnicastCount; /* this should always be 1 for WPA client */
276 guint8 unicastOUI[4];
277 guint16 iAuthCount; /* this should always be 1 for WPA client */
282 #define EAPKEY_MIC_LEN 16 /* length of the MIC key for EAPoL_Key packet's MIC using MD5 */
287 guint8 key_information[2]; /* Make this an array to avoid alignment issues */
288 guint8 key_length[2]; /* Make this an array to avoid alignment issues */
289 guint8 replay_counter[8];
290 guint8 key_nonce[NONCE_LEN];
292 guint8 key_sequence_counter[8]; /* also called the RSC */
294 guint8 key_mic[EAPKEY_MIC_LEN];
295 guint8 key_data_len[2]; /* Make this an array rather than a U16 to avoid alignment shifting */
296 guint8 ie[sizeof(RSN_IE)]; /* Make this an array to avoid alignment issues */
297 } EAPOL_RSN_KEY, * P_EAPOL_RSN_KEY;
301 /* A note about some limitations with the WPA decryption:
303 Unless someone takes the time to restructure the current method used for maintaining decryption keys, there
304 will be some anomalies observed when using the decryption feature.
306 Currently, there is only one pairwise (unicast) key and one group (broadcast) key saved for each security association
307 (SA). As a result, if a wireless sniffer session captures the traffic of a station (STA) associating with an AP
308 more than once, or captures a STA roaming, then you will not be able to arbitrarilly click on different encrypted
309 packets in the trace and observe their internal decrypted structure. This is because when you click on a packet,
310 Wireshark immediately performs the decryption routine with whatever the last key used was. It does not maintain a
311 cache of all the keys that were used by this STA/AP pairing.
313 However, if you are just looking at the summary lines of a capture, it will appear that everything was decrypted properly.
314 This is because when first performing a capture or initially reading a capture file, Wireshark will first
315 process the packets in order. As it encounters new EAPOL packets, it will update its internal key list with the
316 newfound key. Then it will use that key for decrypting subsequent packets. Each time a new key is found, the old key
317 is overwritten. So, if you then click on a packet that was previously decrypted properly, it might suddenly no longer
318 be decrypted because a later EAPOL key had caused the internal decryption key to be updated.
320 For broadcast packets, there is a clunky work-around. If the AP is using group-key rotation, you simply have to find the appropriate
321 EAPOL group key packet (usually size is 211 bytes and will have a protocol type of EAPOL and Info field of Key). If you click on it
322 and then click on the broadcast packet you are trying to decrypt, the packet will be decrypted properly. By first
323 clicking on the EAPOL packet for the group-key, you will force Wireshark to parse that packet and load the group-key it
324 contains. That group key will then be used for decrypting all subsequent broadcast packets you click on.
326 Ideally, it would be best to maintain an expanding list of SA keys. Perhaps we could associate packet number ranges
327 that they apply to. Then, whenever we need to decrypt a packet, we can determine which key to use based on whether
328 it is broadcast or unicast and within what packet number range it falls.
330 Either that, or store two versions of encrypted packets - the orginal packet and it's successfully
331 decrypted version. Then Wireshark wouldn't have to decrypt packets on the fly if they were already successfully decrypted.
337 AirPDcapDecryptWPABroadcastKey(P_EAPOL_RSN_KEY pEAPKey, guint8 *decryption_key, PAIRPDCAP_SEC_ASSOCIATION sa)
341 guint8 *szEncryptedKey;
343 static AIRPDCAP_KEY_ITEM dummy_key; /* needed in case AirPDcapRsnaMng() wants the key structure */
345 /* 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. */
347 /* Preparation for decrypting the group key - determine group key data length */
348 /* depending on whether it's a TKIP or AES encryption key */
349 key_version = AIRPDCAP_EAP_KEY_DESCR_VER(pEAPKey->key_information[1]);
350 if (key_version == AIRPDCAP_WPA_KEY_VER_NOT_CCMP){
352 memcpy(&key_len, pEAPKey->key_length, 2); /* get the key length as a UINT16 */
353 }else if (key_version == AIRPDCAP_WPA_KEY_VER_AES_CCMP){
355 memcpy(&key_len, pEAPKey->key_data_len, 2); /* get the key length as a UINT16 */
357 key_len = ntohs(key_len); /* Convert to proper endianess */
358 if (key_len > sizeof(RSN_IE)) { /* Don't read past the end of pEAPKey->ie */
362 /* Encrypted key is in the information element field of the EAPOL key packet */
363 szEncryptedKey = g_memdup(pEAPKey->ie, key_len);
365 DEBUG_DUMP("Encrypted Broadcast key:", szEncryptedKey, key_len);
366 DEBUG_DUMP("KeyIV:", pEAPKey->key_iv, 16);
367 DEBUG_DUMP("decryption_key:", decryption_key, 16);
369 /* Build the full decryption key based on the IV and part of the pairwise key */
370 memcpy(new_key, pEAPKey->key_iv, 16);
371 memcpy(new_key+16, decryption_key, 16);
372 DEBUG_DUMP("FullDecrKey:", new_key, 32);
374 if (key_version == AIRPDCAP_WPA_KEY_VER_NOT_CCMP){
377 /* Per 802.11i, Draft 3.0 spec, section 8.5.2, p. 97, line 4-8, */
378 /* group key is decrypted using RC4. Concatenate the IV with the 16 byte EK (PTK+16) to get the decryption key */
380 rc4_state_struct rc4_state;
381 crypt_rc4_init(&rc4_state, new_key, sizeof(new_key));
383 /* Do dummy 256 iterations of the RC4 algorithm (per 802.11i, Draft 3.0, p. 97 line 6) */
384 crypt_rc4(&rc4_state, dummy, 256);
385 crypt_rc4(&rc4_state, szEncryptedKey, key_len);
387 } else if (key_version == AIRPDCAP_WPA_KEY_VER_AES_CCMP){
392 guint8 *decrypted_data;
394 /* This storage is needed for the AES_unwrap function */
395 decrypted_data = (guint8 *) g_malloc(key_len);
397 AES_unwrap(decryption_key, 16, szEncryptedKey, key_len, decrypted_data);
399 /* With WPA2 what we get after Broadcast Key decryption is an actual RSN structure.
400 The key itself is stored as a GTK KDE
401 WPA2 IE (1 byte) id = 0xdd, length (1 byte), GTK OUI (4 bytes), key index (1 byte) and 1 reserved byte. Thus we have to
402 pass pointer to the actual key with 8 bytes offset */
406 while(key_index < key_len && !key_found){
410 rsn_id = decrypted_data[key_index];
413 key_index += decrypted_data[key_index+1]+2;
420 /* Skip over the GTK header info, and don't copy past the end of the encrypted data */
421 memcpy(szEncryptedKey, decrypted_data+key_index+8, key_len-key_index-8);
424 g_free(decrypted_data);
427 /* Decrypted key is now in szEncryptedKey with len of key_len */
428 DEBUG_DUMP("Broadcast key:", szEncryptedKey, key_len);
430 /* Load the proper key material info into the SA */
431 sa->key = &dummy_key; /* we just need key to be not null because it is checked in AirPDcapRsnaMng(). The WPA key materials are actually in the .wpa structure */
433 sa->wpa.key_ver = key_version;
435 /* Since this is a GTK and it's size is only 32 bytes (vs. the 64 byte size of a PTK), we fake it and put it in at a 32-byte offset so the */
436 /* AirPDcapRsnaMng() function will extract the right piece of the GTK for decryption. (The first 16 bytes of the GTK are used for decryption.) */
437 memset(sa->wpa.ptk, 0, sizeof(sa->wpa.ptk));
438 memcpy(sa->wpa.ptk+32, szEncryptedKey, key_len);
439 g_free(szEncryptedKey);
443 /* Return a pointer the the requested SA. If it doesn't exist create it. */
444 PAIRPDCAP_SEC_ASSOCIATION
446 PAIRPDCAP_CONTEXT ctx,
447 AIRPDCAP_SEC_ASSOCIATION_ID *id)
451 /* search for a cached Security Association for supplied BSSID and STA MAC */
452 if ((sa_index=AirPDcapGetSa(ctx, id))==-1) {
453 /* create a new Security Association if it doesn't currently exist */
454 if ((sa_index=AirPDcapStoreSa(ctx, id))==-1) {
458 /* get the Security Association structure */
459 return &ctx->sa[sa_index];
462 #define GROUP_KEY_PAYLOAD_LEN (8+4+sizeof(EAPOL_RSN_KEY))
463 INT AirPDcapScanForGroupKey(
464 PAIRPDCAP_CONTEXT ctx,
466 const guint mac_header_len,
470 const UCHAR *address;
471 AIRPDCAP_SEC_ASSOCIATION_ID id;
473 PAIRPDCAP_SEC_ASSOCIATION sta_sa;
474 PAIRPDCAP_SEC_ASSOCIATION sa;
476 const guint8 dot1x_header[] = {
477 0xAA, /* DSAP=SNAP */
478 0xAA, /* SSAP=SNAP */
479 0x03, /* Control field=Unnumbered frame */
480 0x00, 0x00, 0x00, /* Org. code=encaps. Ethernet */
481 0x88, 0x8E /* Type: 802.1X authentication */
484 P_EAPOL_RSN_KEY pEAPKey;
489 AIRPDCAP_DEBUG_TRACE_START("AirPDcapScanForGroupKey");
491 if (mac_header_len + GROUP_KEY_PAYLOAD_LEN < tot_len) {
492 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "Message too short", AIRPDCAP_DEBUG_LEVEL_3);
493 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
496 /* cache offset in the packet data */
497 offset = mac_header_len;
499 /* check if the packet has an LLC header and the packet is 802.1X authentication (IEEE 802.1X-2004, pg. 24) */
500 if (memcmp(data+offset, dot1x_header, 8) == 0) {
502 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "Authentication: EAPOL packet", AIRPDCAP_DEBUG_LEVEL_3);
504 /* skip LLC header */
508 /* check if the packet is a EAPOL-Key (0x03) (IEEE 802.1X-2004, pg. 25) */
509 if (data[offset+1]!=3) {
510 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "Not EAPOL-Key", AIRPDCAP_DEBUG_LEVEL_3);
511 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
514 /* get and check the body length (IEEE 802.1X-2004, pg. 25) */
515 bodyLength=pntohs(data+offset+2);
516 if ((tot_len-offset-4) < bodyLength) {
517 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "EAPOL body too short", AIRPDCAP_DEBUG_LEVEL_3);
518 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
521 /* skip EAPOL MPDU and go to the first byte of the body */
524 pEAPKey = (P_EAPOL_RSN_KEY) (data+offset);
526 /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */
527 if (/*pEAPKey->type!=0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */
528 pEAPKey->type != AIRPDCAP_RSN_WPA2_KEY_DESCRIPTOR && /* IEEE 802.11 Key Descriptor Type (WPA2) */
529 pEAPKey->type != AIRPDCAP_RSN_WPA_KEY_DESCRIPTOR) /* 254 = RSN_KEY_DESCRIPTOR - WPA, */
531 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "Not valid key descriptor type", AIRPDCAP_DEBUG_LEVEL_3);
532 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
535 /* start with descriptor body */
538 /* Verify the bitfields: Key = 0(groupwise) Mic = 1 Ack = 1 Secure = 1 */
539 if (AIRPDCAP_EAP_KEY(data[offset+1])!=0 ||
540 AIRPDCAP_EAP_ACK(data[offset+1])!=1 ||
541 AIRPDCAP_EAP_MIC(data[offset]) != 1 ||
542 AIRPDCAP_EAP_SEC(data[offset]) != 1){
544 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "Key bitfields not correct", AIRPDCAP_DEBUG_LEVEL_3);
545 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
549 if ( (address=AirPDcapGetBssidAddress((const AIRPDCAP_MAC_FRAME_ADDR4 *)(data))) != NULL) {
550 memcpy(id.bssid, address, AIRPDCAP_MAC_LEN);
552 sprintf(msgbuf, "BSSID: %2X.%2X.%2X.%2X.%2X.%2X\t", id.bssid[0],id.bssid[1],id.bssid[2],id.bssid[3],id.bssid[4],id.bssid[5]);
554 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", msgbuf, AIRPDCAP_DEBUG_LEVEL_3);
556 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "BSSID not found", AIRPDCAP_DEBUG_LEVEL_5);
557 return AIRPDCAP_RET_REQ_DATA;
560 /* force STA address to be the broadcast MAC so we create an SA for the groupkey */
561 memcpy(id.sta, broadcast_mac, AIRPDCAP_MAC_LEN);
563 /* get the Security Association structure for the broadcast MAC and AP */
564 sa = AirPDcapGetSaPtr(ctx, &id);
566 return AIRPDCAP_RET_UNSUCCESS;
569 /* Get the SA for the STA, since we need its pairwise key to decrpyt the group key */
571 /* get STA address */
572 if ( (address=AirPDcapGetStaAddress((const AIRPDCAP_MAC_FRAME_ADDR4 *)(data))) != NULL) {
573 memcpy(id.sta, address, AIRPDCAP_MAC_LEN);
575 sprintf(msgbuf, "ST_MAC: %2X.%2X.%2X.%2X.%2X.%2X\t", id.sta[0],id.sta[1],id.sta[2],id.sta[3],id.sta[4],id.sta[5]);
577 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", msgbuf, AIRPDCAP_DEBUG_LEVEL_3);
579 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "SA not found", AIRPDCAP_DEBUG_LEVEL_5);
580 return AIRPDCAP_RET_REQ_DATA;
583 sta_sa = AirPDcapGetSaPtr(ctx, &id);
585 return AIRPDCAP_RET_UNSUCCESS;
588 /* Extract the group key and install it in the SA */
589 AirPDcapDecryptWPABroadcastKey(pEAPKey, sta_sa->wpa.ptk+16, sa);
592 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapScanForGroupKey", "Skipping: not an EAPOL packet", AIRPDCAP_DEBUG_LEVEL_3);
595 AIRPDCAP_DEBUG_TRACE_END("AirPDcapScanForGroupKey");
600 INT AirPDcapPacketProcess(
601 PAIRPDCAP_CONTEXT ctx,
603 const guint mac_header_len,
607 PAIRPDCAP_KEY_ITEM key,
608 gboolean mngHandshake,
611 const UCHAR *address;
612 AIRPDCAP_SEC_ASSOCIATION_ID id;
613 PAIRPDCAP_SEC_ASSOCIATION sa;
616 const guint8 dot1x_header[] = {
617 0xAA, /* DSAP=SNAP */
618 0xAA, /* SSAP=SNAP */
619 0x03, /* Control field=Unnumbered frame */
620 0x00, 0x00, 0x00, /* Org. code=encaps. Ethernet */
621 0x88, 0x8E /* Type: 802.1X authentication */
628 AIRPDCAP_DEBUG_TRACE_START("AirPDcapPacketProcess");
631 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
632 AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess");
633 return AIRPDCAP_RET_UNSUCCESS;
635 if (data==NULL || tot_len==0) {
636 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL data or length=0", AIRPDCAP_DEBUG_LEVEL_5);
637 AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess");
638 return AIRPDCAP_RET_UNSUCCESS;
641 /* check if the packet is of data type */
642 if (AIRPDCAP_TYPE(data[0])!=AIRPDCAP_TYPE_DATA) {
643 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "not data packet", AIRPDCAP_DEBUG_LEVEL_5);
644 return AIRPDCAP_RET_NO_DATA;
647 /* check correct packet size, to avoid wrong elaboration of encryption algorithms */
648 if (tot_len < (UINT)(mac_header_len+AIRPDCAP_CRYPTED_DATA_MINLEN)) {
649 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "minimum length violated", AIRPDCAP_DEBUG_LEVEL_5);
650 return AIRPDCAP_RET_WRONG_DATA_SIZE;
654 if ( (address=AirPDcapGetBssidAddress((const AIRPDCAP_MAC_FRAME_ADDR4 *)(data))) != NULL) {
655 memcpy(id.bssid, address, AIRPDCAP_MAC_LEN);
657 sprintf(msgbuf, "BSSID: %2X.%2X.%2X.%2X.%2X.%2X\t", id.bssid[0],id.bssid[1],id.bssid[2],id.bssid[3],id.bssid[4],id.bssid[5]);
659 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3);
661 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "BSSID not found", AIRPDCAP_DEBUG_LEVEL_5);
662 return AIRPDCAP_RET_REQ_DATA;
665 /* get STA address */
666 if ( (address=AirPDcapGetStaAddress((const AIRPDCAP_MAC_FRAME_ADDR4 *)(data))) != NULL) {
667 memcpy(id.sta, address, AIRPDCAP_MAC_LEN);
669 sprintf(msgbuf, "ST_MAC: %2X.%2X.%2X.%2X.%2X.%2X\t", id.sta[0],id.sta[1],id.sta[2],id.sta[3],id.sta[4],id.sta[5]);
671 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3);
673 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "SA not found", AIRPDCAP_DEBUG_LEVEL_5);
674 return AIRPDCAP_RET_REQ_DATA;
677 /* get the Security Association structure for the STA and AP */
678 sa = AirPDcapGetSaPtr(ctx, &id);
680 return AIRPDCAP_RET_UNSUCCESS;
683 /* cache offset in the packet data (to scan encryption data) */
684 offset = mac_header_len;
686 /* check if data is encrypted (use the WEP bit in the Frame Control field) */
687 if (AIRPDCAP_WEP(data[1])==0)
690 /* data is sent in cleartext, check if is an authentication message or end the process */
691 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Unencrypted data", AIRPDCAP_DEBUG_LEVEL_3);
693 /* check if the packet as an LLC header and the packet is 802.1X authentication (IEEE 802.1X-2004, pg. 24) */
694 if (memcmp(data+offset, dot1x_header, 8) == 0) {
695 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Authentication: EAPOL packet", AIRPDCAP_DEBUG_LEVEL_3);
697 /* skip LLC header */
700 /* check the version of the EAPOL protocol used (IEEE 802.1X-2004, pg. 24) */
701 /* TODO EAPOL protocol version to check? */
702 /*if (data[offset]!=2) {
703 AIRPDCAP_DEBUG_PRINT_LINE("EAPOL protocol version not recognized", AIRPDCAP_DEBUG_LEVEL_5);
704 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
707 /* check if the packet is a EAPOL-Key (0x03) (IEEE 802.1X-2004, pg. 25) */
708 if (data[offset+1]!=3) {
709 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not EAPOL-Key", AIRPDCAP_DEBUG_LEVEL_5);
710 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
713 /* get and check the body length (IEEE 802.1X-2004, pg. 25) */
714 bodyLength=pntohs(data+offset+2);
715 if ((tot_len-offset-4) < bodyLength) {
716 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "EAPOL body too short", AIRPDCAP_DEBUG_LEVEL_5);
717 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
720 /* skip EAPOL MPDU and go to the first byte of the body */
723 /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */
724 if (/*data[offset]!=0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */
725 data[offset]!=0x2 && /* IEEE 802.11 Key Descriptor Type */
726 data[offset]!=0xFE) /* TODO what's this value??? */
728 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not valid key descriptor type", AIRPDCAP_DEBUG_LEVEL_5);
729 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
732 /* start with descriptor body */
735 /* manage the 4-way handshake to define the key */
736 return AirPDcapRsna4WHandshake(ctx, data, sa, key, offset);
738 /* cleartext message, not authentication */
739 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "No authentication data", AIRPDCAP_DEBUG_LEVEL_5);
740 return AIRPDCAP_RET_NO_DATA_ENCRYPTED;
746 if (decrypt_data==NULL)
747 return AIRPDCAP_RET_UNSUCCESS;
749 /* create new header and data to modify */
750 *decrypt_len = tot_len;
751 memcpy(decrypt_data, data, *decrypt_len);
754 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Encrypted data", AIRPDCAP_DEBUG_LEVEL_3);
756 /* check the Extension IV to distinguish between WEP encryption and WPA encryption */
757 /* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */
758 /* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */
759 /* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */
760 if (AIRPDCAP_EXTIV(data[offset+3])==0) {
761 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "WEP encryption", AIRPDCAP_DEBUG_LEVEL_3);
762 return AirPDcapWepMng(ctx, decrypt_data, mac_header_len, decrypt_len, key, sa, offset);
765 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "TKIP or CCMP encryption", AIRPDCAP_DEBUG_LEVEL_3);
767 /* If index >= 1, then use the group key. This will not work if the AP is using
768 more than one group key simultaneously. I've not seen this in practice, however. Usually an AP
769 will rotate between the two key index values of 1 and 2 whenever it needs to change the group key to be used. */
770 if (AIRPDCAP_KEY_INDEX(data[offset+3])>=1){
772 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "The key index = 1. This is encrypted with a group key.", AIRPDCAP_DEBUG_LEVEL_3);
774 /* force STA address to broadcast MAC so we load the SA for the groupkey */
775 memcpy(id.sta, broadcast_mac, AIRPDCAP_MAC_LEN);
778 sprintf(msgbuf, "ST_MAC: %2X.%2X.%2X.%2X.%2X.%2X\t", id.sta[0],id.sta[1],id.sta[2],id.sta[3],id.sta[4],id.sta[5]);
779 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3);
782 /* search for a cached Security Association for current BSSID and broadcast MAC */
783 sa = AirPDcapGetSaPtr(ctx, &id);
785 return AIRPDCAP_RET_UNSUCCESS;
789 /* Decrypt the packet using the appropriate SA */
790 status = AirPDcapRsnaMng(decrypt_data, mac_header_len, decrypt_len, key, sa, offset);
792 /* If we successfully decrypted a packet, scan it to see if it contains a group key handshake.
793 The group key handshake could be sent at any time the AP wants to change the key (such as when
794 it is using key rotation) so we must scan every packet. */
795 if (status == AIRPDCAP_RET_SUCCESS)
796 AirPDcapScanForGroupKey(ctx, decrypt_data, mac_header_len, *decrypt_len);
802 return AIRPDCAP_RET_UNSUCCESS;
806 PAIRPDCAP_CONTEXT ctx,
807 AIRPDCAP_KEY_ITEM keys[],
808 const size_t keys_nr)
812 AIRPDCAP_DEBUG_TRACE_START("AirPDcapSetKeys");
814 if (ctx==NULL || keys==NULL) {
815 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "NULL context or NULL keys array", AIRPDCAP_DEBUG_LEVEL_3);
816 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
820 if (keys_nr>AIRPDCAP_MAX_KEYS_NR) {
821 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Keys number greater than maximum", AIRPDCAP_DEBUG_LEVEL_3);
822 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
826 /* clean key and SA collections before setting new ones */
827 AirPDcapInitContext(ctx);
829 /* check and insert keys */
830 for (i=0, success=0; i<(INT)keys_nr; i++) {
831 if (AirPDcapValidateKey(keys+i)==TRUE) {
832 if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD) {
833 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PWD key", AIRPDCAP_DEBUG_LEVEL_4);
834 AirPDcapRsnaPwd2Psk(keys[i].UserPwd.Passphrase, keys[i].UserPwd.Ssid, keys[i].UserPwd.SsidLen, keys[i].KeyData.Wpa.Psk);
837 else if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK) {
838 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PMK key", AIRPDCAP_DEBUG_LEVEL_4);
839 } else if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WEP) {
840 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WEP key", AIRPDCAP_DEBUG_LEVEL_4);
842 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a key", AIRPDCAP_DEBUG_LEVEL_4);
845 memcpy(&ctx->keys[success], &keys[i], sizeof(keys[i]));
850 ctx->keys_nr=success;
852 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
858 PAIRPDCAP_CONTEXT ctx)
860 AIRPDCAP_DEBUG_TRACE_START("AirPDcapCleanKeys");
863 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
864 AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys");
868 memset(ctx->keys, 0, sizeof(AIRPDCAP_KEY_ITEM) * AIRPDCAP_MAX_KEYS_NR);
872 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "Keys collection cleaned!", AIRPDCAP_DEBUG_LEVEL_5);
873 AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys");
877 const PAIRPDCAP_CONTEXT ctx,
878 AIRPDCAP_KEY_ITEM keys[],
879 const size_t keys_nr)
883 AIRPDCAP_DEBUG_TRACE_START("AirPDcapGetKeys");
886 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
887 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
889 } else if (keys==NULL) {
890 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL keys array", AIRPDCAP_DEBUG_LEVEL_5);
891 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
892 return (INT)ctx->keys_nr;
894 for (i=0, j=0; i<ctx->keys_nr && i<keys_nr && i<AIRPDCAP_MAX_KEYS_NR; i++) {
895 memcpy(&keys[j], &ctx->keys[i], sizeof(keys[j]));
897 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "Got a key", AIRPDCAP_DEBUG_LEVEL_5);
900 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
906 * XXX - This won't be reliable if a packet containing SSID "B" shows
907 * up in the middle of a 4-way handshake for SSID "A".
908 * We should probably use a small array or hash table to keep multiple
911 INT AirPDcapSetLastSSID(
912 PAIRPDCAP_CONTEXT ctx,
916 if (!ctx || !pkt_ssid || pkt_ssid_len < 1 || pkt_ssid_len > WPA_SSID_MAX_SIZE)
917 return AIRPDCAP_RET_UNSUCCESS;
919 memcpy(ctx->pkt_ssid, pkt_ssid, pkt_ssid_len);
920 ctx->pkt_ssid_len = pkt_ssid_len;
922 return AIRPDCAP_RET_SUCCESS;
925 INT AirPDcapInitContext(
926 PAIRPDCAP_CONTEXT ctx)
928 AIRPDCAP_DEBUG_TRACE_START("AirPDcapInitContext");
931 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
932 AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext");
933 return AIRPDCAP_RET_UNSUCCESS;
936 AirPDcapCleanKeys(ctx);
938 ctx->first_free_index=0;
941 ctx->pkt_ssid_len = 0;
943 memset(ctx->sa, 0, AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR * sizeof(AIRPDCAP_SEC_ASSOCIATION));
945 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "Context initialized!", AIRPDCAP_DEBUG_LEVEL_5);
946 AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext");
947 return AIRPDCAP_RET_SUCCESS;
950 INT AirPDcapDestroyContext(
951 PAIRPDCAP_CONTEXT ctx)
953 AIRPDCAP_DEBUG_TRACE_START("AirPDcapDestroyContext");
956 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
957 AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext");
958 return AIRPDCAP_RET_UNSUCCESS;
961 AirPDcapCleanKeys(ctx);
963 ctx->first_free_index=0;
967 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "Context destroyed!", AIRPDCAP_DEBUG_LEVEL_5);
968 AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext");
969 return AIRPDCAP_RET_SUCCESS;
976 /****************************************************************************/
978 /****************************************************************************/
979 /* Internal function definitions */
988 guint mac_header_len,
990 PAIRPDCAP_KEY_ITEM key,
991 AIRPDCAP_SEC_ASSOCIATION *sa,
997 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "No key associated", AIRPDCAP_DEBUG_LEVEL_3);
998 return AIRPDCAP_RET_REQ_DATA;
1000 if (sa->validKey==FALSE) {
1001 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "Key not yet valid", AIRPDCAP_DEBUG_LEVEL_3);
1002 return AIRPDCAP_RET_UNSUCCESS;
1004 if (sa->wpa.key_ver==1) {
1005 /* CCMP -> HMAC-MD5 is the EAPOL-Key MIC, RC4 is the EAPOL-Key encryption algorithm */
1006 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP", AIRPDCAP_DEBUG_LEVEL_3);
1008 DEBUG_DUMP("ptk", sa->wpa.ptk, 64);
1009 DEBUG_DUMP("ptk portion used", AIRPDCAP_GET_TK(sa->wpa.ptk), 16);
1011 ret_value=AirPDcapTkipDecrypt(decrypt_data+offset, *decrypt_len-offset, decrypt_data+AIRPDCAP_TA_OFFSET, AIRPDCAP_GET_TK(sa->wpa.ptk));
1013 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP failed!", AIRPDCAP_DEBUG_LEVEL_3);
1017 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
1018 /* remove MIC (8bytes) and ICV (4bytes) from the end of packet */
1021 /* AES-CCMP -> HMAC-SHA1-128 is the EAPOL-Key MIC, AES wep_key wrap is the EAPOL-Key encryption algorithm */
1022 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP", AIRPDCAP_DEBUG_LEVEL_3);
1024 ret_value=AirPDcapCcmpDecrypt(decrypt_data, mac_header_len, (INT)*decrypt_len, AIRPDCAP_GET_TK(sa->wpa.ptk));
1028 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
1029 /* remove MIC (8bytes) from the end of packet */
1033 /* remove protection bit */
1034 decrypt_data[1]&=0xBF;
1036 /* remove TKIP/CCMP header */
1037 offset = mac_header_len;
1039 memcpy(decrypt_data+offset, decrypt_data+offset+8, *decrypt_len-offset);
1042 memcpy(key, sa->key, sizeof(AIRPDCAP_KEY_ITEM));
1044 if (sa->wpa.key_ver==AIRPDCAP_WPA_KEY_VER_NOT_CCMP)
1045 key->KeyType=AIRPDCAP_KEY_TYPE_TKIP;
1046 else if (sa->wpa.key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP)
1047 key->KeyType=AIRPDCAP_KEY_TYPE_CCMP;
1050 return AIRPDCAP_RET_SUCCESS;
1055 PAIRPDCAP_CONTEXT ctx,
1056 UCHAR *decrypt_data,
1057 guint mac_header_len,
1059 PAIRPDCAP_KEY_ITEM key,
1060 AIRPDCAP_SEC_ASSOCIATION *sa,
1063 UCHAR wep_key[AIRPDCAP_WEP_KEY_MAXLEN+AIRPDCAP_WEP_IVLEN];
1067 AIRPDCAP_KEY_ITEM *tmp_key;
1068 UINT8 useCache=FALSE;
1069 UCHAR *try_data = ep_alloc(*decrypt_len);
1074 for (key_index=0; key_index<(INT)ctx->keys_nr; key_index++) {
1075 /* use the cached one, or try all keys */
1077 tmp_key=&ctx->keys[key_index];
1079 if (sa->key!=NULL && sa->key->KeyType==AIRPDCAP_KEY_TYPE_WEP) {
1080 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try cached WEP key...", AIRPDCAP_DEBUG_LEVEL_3);
1083 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Cached key is not valid, try another WEP key...", AIRPDCAP_DEBUG_LEVEL_3);
1084 tmp_key=&ctx->keys[key_index];
1088 /* obviously, try only WEP keys... */
1089 if (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP)
1091 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try WEP key...", AIRPDCAP_DEBUG_LEVEL_3);
1093 memset(wep_key, 0, sizeof(wep_key));
1094 memcpy(try_data, decrypt_data, *decrypt_len);
1096 /* Costruct the WEP seed: copy the IV in first 3 bytes and then the WEP key (refer to 802-11i-2004, 8.2.1.4.3, pag. 36) */
1097 memcpy(wep_key, try_data+mac_header_len, AIRPDCAP_WEP_IVLEN);
1098 keylen=tmp_key->KeyData.Wep.WepKeyLen;
1099 memcpy(wep_key+AIRPDCAP_WEP_IVLEN, tmp_key->KeyData.Wep.WepKey, keylen);
1101 ret_value=AirPDcapWepDecrypt(wep_key,
1102 keylen+AIRPDCAP_WEP_IVLEN,
1103 try_data + (mac_header_len+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN),
1104 *decrypt_len-(mac_header_len+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN+AIRPDCAP_CRC_LEN));
1106 if (ret_value == AIRPDCAP_RET_SUCCESS)
1107 memcpy(decrypt_data, try_data, *decrypt_len);
1110 if (!ret_value && tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP) {
1111 /* the tried key is the correct one, cached in the Security Association */
1116 memcpy(key, &sa->key, sizeof(AIRPDCAP_KEY_ITEM));
1117 key->KeyType=AIRPDCAP_KEY_TYPE_WEP;
1122 /* the cached key was not valid, try other keys */
1124 if (useCache==TRUE) {
1134 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "WEP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
1136 /* remove ICV (4bytes) from the end of packet */
1139 /* remove protection bit */
1140 decrypt_data[1]&=0xBF;
1142 /* remove IC header */
1143 offset = mac_header_len;
1145 memcpy(decrypt_data+offset, decrypt_data+offset+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN, *decrypt_len-offset);
1147 return AIRPDCAP_RET_SUCCESS;
1150 /* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */
1152 AirPDcapRsna4WHandshake(
1153 PAIRPDCAP_CONTEXT ctx,
1155 AIRPDCAP_SEC_ASSOCIATION *sa,
1156 PAIRPDCAP_KEY_ITEM key,
1159 AIRPDCAP_KEY_ITEM *tmp_key, pkt_key;
1162 UCHAR useCache=FALSE;
1163 UCHAR eapol[AIRPDCAP_EAPOL_MAX_LEN];
1169 /* a 4-way handshake packet use a Pairwise key type (IEEE 802.11i-2004, pg. 79) */
1170 if (AIRPDCAP_EAP_KEY(data[offset+1])!=1) {
1171 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Group/STAKey message (not used)", AIRPDCAP_DEBUG_LEVEL_5);
1172 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
1175 /* TODO timeouts? reauthentication? */
1177 /* TODO consider key-index */
1179 /* TODO considera Deauthentications */
1181 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake...", AIRPDCAP_DEBUG_LEVEL_5);
1183 /* manage 4-way handshake packets; this step completes the 802.1X authentication process (IEEE 802.11i-2004, pag. 85) */
1185 /* message 1: Authenticator->Supplicant (Sec=0, Mic=0, Ack=1, Inst=0, Key=1(pairwise), KeyRSC=0, Nonce=ANonce, MIC=0) */
1186 if (AIRPDCAP_EAP_INST(data[offset+1])==0 &&
1187 AIRPDCAP_EAP_ACK(data[offset+1])==1 &&
1188 AIRPDCAP_EAP_MIC(data[offset])==0)
1190 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 1", AIRPDCAP_DEBUG_LEVEL_3);
1192 /* On reception of Message 1, the Supplicant determines whether the Key Replay Counter field value has been */
1193 /* used before with the current PMKSA. If the Key Replay Counter field value is less than or equal to the current */
1194 /* local value, the Supplicant discards the message. */
1195 /* -> not checked, the Authenticator will be send another Message 1 (hopefully!) */
1197 /* save ANonce (from authenticator) to derive the PTK with the SNonce (from the 2 message) */
1198 memcpy(sa->wpa.nonce, data+offset+12, 32);
1200 /* get the Key Descriptor Version (to select algorithm used in decryption -CCMP or TKIP-) */
1201 sa->wpa.key_ver=AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1]);
1205 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
1208 /* 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)) */
1209 if (AIRPDCAP_EAP_INST(data[offset+1])==0 &&
1210 AIRPDCAP_EAP_ACK(data[offset+1])==0 &&
1211 AIRPDCAP_EAP_MIC(data[offset])==1)
1213 if (AIRPDCAP_EAP_SEC(data[offset])==0) {
1215 /* PATCH: some implementations set secure bit to 0 also in the 4th message */
1216 /* to recognize which message is this check if wep_key data length is 0 */
1217 /* in the 4th message */
1218 if (data[offset+92]!=0 || data[offset+93]!=0) {
1220 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 2", AIRPDCAP_DEBUG_LEVEL_3);
1222 /* On reception of Message 2, the Authenticator checks that the key replay counter corresponds to the */
1223 /* outstanding Message 1. If not, it silently discards the message. */
1224 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, */
1225 /* the Authenticator silently discards Message 2. */
1226 /* -> not checked; the Supplicant will send another message 2 (hopefully!) */
1228 /* now you can derive the PTK */
1229 for (key_index=0; key_index<(INT)ctx->keys_nr || useCache; key_index++) {
1230 /* use the cached one, or try all keys */
1232 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try WPA key...", AIRPDCAP_DEBUG_LEVEL_3);
1233 tmp_key=&ctx->keys[key_index];
1235 /* there is a cached key in the security association, if it's a WPA key try it... */
1236 if (sa->key!=NULL &&
1237 (sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD ||
1238 sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK ||
1239 sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK)) {
1240 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try cached WPA key...", AIRPDCAP_DEBUG_LEVEL_3);
1243 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Cached key is of a wrong type, try WPA key...", AIRPDCAP_DEBUG_LEVEL_3);
1244 tmp_key=&ctx->keys[key_index];
1248 /* obviously, try only WPA keys... */
1249 if (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD ||
1250 tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK ||
1251 tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK)
1253 if (tmp_key->KeyType == AIRPDCAP_KEY_TYPE_WPA_PWD && tmp_key->UserPwd.SsidLen == 0 && ctx->pkt_ssid_len > 0 && ctx->pkt_ssid_len <= AIRPDCAP_WPA_SSID_MAX_LEN) {
1254 /* We have a "wildcard" SSID. Use the one from the packet. */
1255 memcpy(&pkt_key, tmp_key, sizeof(pkt_key));
1256 memcpy(&pkt_key.UserPwd.Ssid, ctx->pkt_ssid, ctx->pkt_ssid_len);
1257 pkt_key.UserPwd.SsidLen = ctx->pkt_ssid_len;
1258 AirPDcapRsnaPwd2Psk(pkt_key.UserPwd.Passphrase, pkt_key.UserPwd.Ssid,
1259 pkt_key.UserPwd.SsidLen, pkt_key.KeyData.Wpa.Psk);
1263 /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */
1264 AirPDcapRsnaPrfX(sa, /* authenticator nonce, bssid, station mac */
1265 tmp_key->KeyData.Wpa.Pmk, /* PMK */
1266 data+offset+12, /* supplicant nonce */
1270 /* verify the MIC (compare the MIC in the packet included in this message with a MIC calculated with the PTK) */
1271 eapol_len=pntohs(data+offset-3)+4;
1272 memcpy(eapol, &data[offset-5], (eapol_len<AIRPDCAP_EAPOL_MAX_LEN?eapol_len:AIRPDCAP_EAPOL_MAX_LEN));
1273 ret_value=AirPDcapRsnaMicCheck(eapol, /* eapol frame (header also) */
1274 eapol_len, /* eapol frame length */
1275 sa->wpa.ptk, /* Key Confirmation Key */
1276 AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])); /* EAPOL-Key description version */
1278 /* If the MIC is valid, the Authenticator checks that the RSN information element bit-wise matches */
1279 /* that from the (Re)Association Request message. */
1280 /* i) TODO If these are not exactly the same, the Authenticator uses MLME-DEAUTHENTICATE.request */
1281 /* primitive to terminate the association. */
1282 /* ii) If they do match bit-wise, the Authenticator constructs Message 3. */
1286 (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD ||
1287 tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK ||
1288 tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK))
1290 /* the temporary key is the correct one, cached in the Security Association */
1295 memcpy(key, &tmp_key, sizeof(AIRPDCAP_KEY_ITEM));
1296 if (AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])==AIRPDCAP_WPA_KEY_VER_NOT_CCMP)
1297 key->KeyType=AIRPDCAP_KEY_TYPE_TKIP;
1298 else if (AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])==AIRPDCAP_WPA_KEY_VER_AES_CCMP)
1299 key->KeyType=AIRPDCAP_KEY_TYPE_CCMP;
1304 /* the cached key was not valid, try other keys */
1306 if (useCache==TRUE) {
1314 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "handshake step failed", AIRPDCAP_DEBUG_LEVEL_3);
1315 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
1320 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
1324 /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
1326 /* TODO check MIC and Replay Counter */
1327 /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */
1328 /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */
1329 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */
1330 /* Authenticator silently discards Message 4. */
1332 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4 (patched)", AIRPDCAP_DEBUG_LEVEL_3);
1338 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
1345 /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
1347 /* TODO check MIC and Replay Counter */
1348 /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */
1349 /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */
1350 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */
1351 /* Authenticator silently discards Message 4. */
1353 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4", AIRPDCAP_DEBUG_LEVEL_3);
1359 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
1363 /* message 3: Authenticator->Supplicant (Sec=1, Mic=1, Ack=1, Inst=0/1, Key=1(pairwise), KeyRSC=???, Nonce=ANonce, MIC=1) */
1364 if (AIRPDCAP_EAP_ACK(data[offset+1])==1 &&
1365 AIRPDCAP_EAP_MIC(data[offset])==1)
1367 P_EAPOL_RSN_KEY pEAPKey;
1368 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 3", AIRPDCAP_DEBUG_LEVEL_3);
1370 /* On reception of Message 3, the Supplicant silently discards the message if the Key Replay Counter field */
1371 /* value has already been used or if the ANonce value in Message 3 differs from the ANonce value in Message 1. */
1372 /* -> not checked, the Authenticator will send another message 3 (hopefully!) */
1374 /* TODO check page 88 (RNS) */
1376 /* If using WPA2 PSK, message 3 will contain an RSN for the group key (GTK KDE).
1377 In order to properly support decrypting WPA2-PSK packets, we need to parse this to get the group key.*/
1378 pEAPKey = (P_EAPOL_RSN_KEY)(&(data[offset-1]));
1379 if (pEAPKey->type == AIRPDCAP_RSN_WPA2_KEY_DESCRIPTOR){
1380 PAIRPDCAP_SEC_ASSOCIATION broadcast_sa;
1381 AIRPDCAP_SEC_ASSOCIATION_ID id;
1383 /* Get broadcacst SA for the current BSSID */
1384 memcpy(id.sta, broadcast_mac, AIRPDCAP_MAC_LEN);
1385 memcpy(id.bssid, sa->saId.bssid, AIRPDCAP_MAC_LEN);
1386 broadcast_sa = AirPDcapGetSaPtr(ctx, &id);
1388 if (broadcast_sa == NULL){
1389 return AIRPDCAP_RET_UNSUCCESS;
1391 AirPDcapDecryptWPABroadcastKey(pEAPKey, sa->wpa.ptk+16, broadcast_sa);
1394 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
1397 return AIRPDCAP_RET_UNSUCCESS;
1401 AirPDcapRsnaMicCheck(
1404 UCHAR KCK[AIRPDCAP_WPA_KCK_LEN],
1407 UCHAR mic[AIRPDCAP_WPA_MICKEY_LEN];
1408 UCHAR c_mic[20]; /* MIC 16 byte, the HMAC-SHA1 use a buffer of 20 bytes */
1410 /* copy the MIC from the EAPOL packet */
1411 memcpy(mic, eapol+AIRPDCAP_WPA_MICKEY_OFFSET+4, AIRPDCAP_WPA_MICKEY_LEN);
1413 /* set to 0 the MIC in the EAPOL packet (to calculate the MIC) */
1414 memset(eapol+AIRPDCAP_WPA_MICKEY_OFFSET+4, 0, AIRPDCAP_WPA_MICKEY_LEN);
1416 if (key_ver==AIRPDCAP_WPA_KEY_VER_NOT_CCMP) {
1417 /* use HMAC-MD5 for the EAPOL-Key MIC */
1418 md5_hmac(eapol, eapol_len, KCK, AIRPDCAP_WPA_KCK_LEN, c_mic);
1419 } else if (key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP) {
1420 /* use HMAC-SHA1-128 for the EAPOL-Key MIC */
1421 sha1_hmac(KCK, AIRPDCAP_WPA_KCK_LEN, eapol, eapol_len, c_mic);
1423 /* key descriptor version not recognized */
1424 return AIRPDCAP_RET_UNSUCCESS;
1426 /* compare calculated MIC with the Key MIC and return result (0 means success) */
1427 return memcmp(mic, c_mic, AIRPDCAP_WPA_MICKEY_LEN);
1431 AirPDcapValidateKey(
1432 PAIRPDCAP_KEY_ITEM key)
1436 AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey");
1439 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "NULL key", AIRPDCAP_DEBUG_LEVEL_5);
1440 AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey");
1444 switch (key->KeyType) {
1445 case AIRPDCAP_KEY_TYPE_WEP:
1446 /* check key size limits */
1447 len=key->KeyData.Wep.WepKeyLen;
1448 if (len<AIRPDCAP_WEP_KEY_MINLEN || len>AIRPDCAP_WEP_KEY_MAXLEN) {
1449 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WEP key: key length not accepted", AIRPDCAP_DEBUG_LEVEL_5);
1454 case AIRPDCAP_KEY_TYPE_WEP_40:
1455 /* set the standard length and use a generic WEP key type */
1456 key->KeyData.Wep.WepKeyLen=AIRPDCAP_WEP_40_KEY_LEN;
1457 key->KeyType=AIRPDCAP_KEY_TYPE_WEP;
1460 case AIRPDCAP_KEY_TYPE_WEP_104:
1461 /* set the standard length and use a generic WEP key type */
1462 key->KeyData.Wep.WepKeyLen=AIRPDCAP_WEP_104_KEY_LEN;
1463 key->KeyType=AIRPDCAP_KEY_TYPE_WEP;
1466 case AIRPDCAP_KEY_TYPE_WPA_PWD:
1467 /* check passphrase and SSID size limits */
1468 len=strlen(key->UserPwd.Passphrase);
1469 if (len<AIRPDCAP_WPA_PASSPHRASE_MIN_LEN || len>AIRPDCAP_WPA_PASSPHRASE_MAX_LEN) {
1470 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: passphrase length not accepted", AIRPDCAP_DEBUG_LEVEL_5);
1474 len=key->UserPwd.SsidLen;
1475 if (len>AIRPDCAP_WPA_SSID_MAX_LEN) {
1476 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: ssid length not accepted", AIRPDCAP_DEBUG_LEVEL_5);
1482 case AIRPDCAP_KEY_TYPE_WPA_PSK:
1485 case AIRPDCAP_KEY_TYPE_WPA_PMK:
1492 AIRPDCAP_DEBUG_TRACE_END("AirPDcapValidateKey");
1498 PAIRPDCAP_CONTEXT ctx,
1499 AIRPDCAP_SEC_ASSOCIATION_ID *id)
1503 if (ctx->sa_index!=-1) {
1504 /* at least one association was stored */
1505 /* search for the association from sa_index to 0 (most recent added) */
1506 for (sa_index=ctx->sa_index; sa_index>=0; sa_index--) {
1507 if (ctx->sa[sa_index].used) {
1508 if (memcmp(id, &(ctx->sa[sa_index].saId), sizeof(AIRPDCAP_SEC_ASSOCIATION_ID))==0) {
1509 ctx->index=sa_index;
1521 PAIRPDCAP_CONTEXT ctx,
1522 AIRPDCAP_SEC_ASSOCIATION_ID *id)
1526 if (ctx->sa[ctx->first_free_index].used) {
1527 /* last addition was in the middle of the array (and the first_free_index was just incremented by 1) */
1528 /* search for a free space from the first_free_index to AIRPDCAP_STA_INFOS_NR (to avoid free blocks in */
1530 for (last_free=ctx->first_free_index; last_free<AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR; last_free++)
1531 if (!ctx->sa[last_free].used)
1534 if (last_free>=AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR) {
1535 /* there is no empty space available. FAILURE */
1539 /* store first free space index */
1540 ctx->first_free_index=last_free;
1544 ctx->index=ctx->first_free_index;
1546 /* reset the info structure */
1547 memset(ctx->sa+ctx->index, 0, sizeof(AIRPDCAP_SEC_ASSOCIATION));
1549 ctx->sa[ctx->index].used=1;
1551 /* set the info structure */
1552 memcpy(&(ctx->sa[ctx->index].saId), id, sizeof(AIRPDCAP_SEC_ASSOCIATION_ID));
1554 /* increment by 1 the first_free_index (heuristic) */
1555 ctx->first_free_index++;
1557 /* set the sa_index if the added index is greater the the sa_index */
1558 if (ctx->index > ctx->sa_index)
1559 ctx->sa_index=ctx->index;
1565 * AirPDcapGetBssidAddress() and AirPDcapGetBssidAddress() are used for
1566 * key caching. In each case, it's more important to return a value than
1567 * to return a _correct_ value, so we fudge addresses in some cases, e.g.
1568 * the BSSID in bridged connections.
1569 * FromDS ToDS Sta BSSID
1576 static const UCHAR *
1577 AirPDcapGetStaAddress(
1578 const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
1580 switch(AIRPDCAP_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
1584 return frame->addr2;
1586 return frame->addr1;
1592 static const UCHAR *
1593 AirPDcapGetBssidAddress(
1594 const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
1596 switch(AIRPDCAP_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
1598 return frame->addr3;
1601 return frame->addr1;
1603 return frame->addr2;
1609 /* Function used to derive the PTK. Refer to IEEE 802.11I-2004, pag. 74 */
1612 AIRPDCAP_SEC_ASSOCIATION *sa,
1613 const UCHAR pmk[32],
1614 const UCHAR snonce[32],
1615 const INT x, /* for TKIP 512, for CCMP 384 */
1620 INT offset=sizeof("Pairwise key expansion");
1624 memcpy(R, "Pairwise key expansion", offset);
1626 /* Min(AA, SPA) || Max(AA, SPA) */
1627 if (memcmp(sa->saId.sta, sa->saId.bssid, AIRPDCAP_MAC_LEN) < 0)
1629 memcpy(R + offset, sa->saId.sta, AIRPDCAP_MAC_LEN);
1630 memcpy(R + offset+AIRPDCAP_MAC_LEN, sa->saId.bssid, AIRPDCAP_MAC_LEN);
1634 memcpy(R + offset, sa->saId.bssid, AIRPDCAP_MAC_LEN);
1635 memcpy(R + offset+AIRPDCAP_MAC_LEN, sa->saId.sta, AIRPDCAP_MAC_LEN);
1638 offset+=AIRPDCAP_MAC_LEN*2;
1640 /* Min(ANonce,SNonce) || Max(ANonce,SNonce) */
1641 if( memcmp(snonce, sa->wpa.nonce, 32) < 0 )
1643 memcpy(R + offset, snonce, 32);
1644 memcpy(R + offset + 32, sa->wpa.nonce, 32);
1648 memcpy(R + offset, sa->wpa.nonce, 32);
1649 memcpy(R + offset + 32, snonce, 32);
1654 for(i = 0; i < (x+159)/160; i++)
1657 sha1_hmac(pmk, 32, R, 100, ptk + i * 20);
1662 AirPDcapRsnaPwd2PskStep(
1663 const guint8 *ppBytes,
1664 const guint ppLength,
1666 const size_t ssidLength,
1667 const INT iterations,
1671 UCHAR digest[36], digest1[AIRPDCAP_SHA_DIGEST_LEN];
1674 /* U1 = PRF(P, S || INT(i)) */
1675 memcpy(digest, ssid, ssidLength);
1676 digest[ssidLength] = (UCHAR)((count>>24) & 0xff);
1677 digest[ssidLength+1] = (UCHAR)((count>>16) & 0xff);
1678 digest[ssidLength+2] = (UCHAR)((count>>8) & 0xff);
1679 digest[ssidLength+3] = (UCHAR)(count & 0xff);
1680 sha1_hmac(ppBytes, ppLength, digest, ssidLength+4, digest1);
1683 memcpy(output, digest1, AIRPDCAP_SHA_DIGEST_LEN);
1684 for (i = 1; i < iterations; i++) {
1685 /* Un = PRF(P, Un-1) */
1686 sha1_hmac(ppBytes, ppLength, digest1, AIRPDCAP_SHA_DIGEST_LEN, digest);
1688 memcpy(digest1, digest, AIRPDCAP_SHA_DIGEST_LEN);
1689 /* output = output xor Un */
1690 for (j = 0; j < AIRPDCAP_SHA_DIGEST_LEN; j++) {
1691 output[j] ^= digest[j];
1695 return AIRPDCAP_RET_SUCCESS;
1699 AirPDcapRsnaPwd2Psk(
1700 const CHAR *passphrase,
1702 const size_t ssidLength,
1705 UCHAR m_output[AIRPDCAP_WPA_PSK_LEN];
1706 GByteArray *pp_ba = g_byte_array_new();
1708 memset(m_output, 0, AIRPDCAP_WPA_PSK_LEN);
1710 if (!uri_str_to_bytes(passphrase, pp_ba)) {
1711 g_byte_array_free(pp_ba, TRUE);
1715 AirPDcapRsnaPwd2PskStep(pp_ba->data, pp_ba->len, ssid, ssidLength, 4096, 1, m_output);
1716 AirPDcapRsnaPwd2PskStep(pp_ba->data, pp_ba->len, ssid, ssidLength, 4096, 2, &m_output[AIRPDCAP_SHA_DIGEST_LEN]);
1718 memcpy(output, m_output, AIRPDCAP_WPA_PSK_LEN);
1719 g_byte_array_free(pp_ba, TRUE);
1725 * Returns the decryption_key_t struct given a string describing the key.
1726 * Returns NULL if the key_string cannot be parsed.
1729 parse_key_string(gchar* input_string)
1735 GString *key_string = NULL;
1736 GByteArray *ssid_ba = NULL, *key_ba;
1741 decryption_key_t *dk;
1742 gchar *first_nibble = input_string;
1744 if(input_string == NULL)
1748 * Parse the input_string. It should be in the form
1749 * <key type>:<key data>[:<ssid>]
1750 * XXX - For backward compatibility, the a WEP key can be just a string
1751 * of hexadecimal characters (if WEP key is wrong, null will be
1755 /* First, check for a WEP string */
1756 /* XXX - This duplicates code in packet-ieee80211.c */
1757 if (g_ascii_strncasecmp(input_string, STRING_KEY_TYPE_WEP ":", 4) == 0) {
1761 key_ba = g_byte_array_new();
1762 res = hex_str_to_bytes(first_nibble, key_ba, FALSE);
1764 if (res && key_ba->len > 0) {
1765 /* Key is correct! It was probably an 'old style' WEP key */
1766 /* Create the decryption_key_t structure, fill it and return it*/
1767 dk = g_malloc(sizeof(decryption_key_t));
1769 dk->type = AIRPDCAP_KEY_TYPE_WEP;
1770 /* XXX - The current key handling code in the GUI requires
1771 * no separators and lower case */
1772 dk->key = g_string_new(bytes_to_str(key_ba->data, key_ba->len));
1773 g_string_down(dk->key);
1774 dk->bits = key_ba->len * 8;
1777 g_byte_array_free(key_ba, TRUE);
1780 g_byte_array_free(key_ba, TRUE);
1783 tokens = g_strsplit(input_string,":",0);
1785 /* Tokens is a null termiated array of strings ... */
1786 while(tokens[n] != NULL)
1791 /* Free the array of strings */
1796 type = g_strdup(tokens[0]);
1799 * The second token is the key (right now it doesn't matter
1800 * if it is a passphrase[+ssid] or an hexadecimal one)
1802 key = g_strdup(tokens[1]);
1805 /* Maybe there is a third token (an ssid, if everything else is ok) */
1808 ssid = g_strdup(tokens[2]);
1811 if (g_ascii_strcasecmp(type,STRING_KEY_TYPE_WPA_PSK) == 0) /* WPA key */
1813 /* Create a new string */
1814 key_string = g_string_new(key);
1816 key_ba = g_byte_array_new();
1817 res = hex_str_to_bytes(key, key_ba, FALSE);
1819 /* Two tokens means that the user should have entered a WPA-BIN key ... */
1820 if(!res || ((key_string->len) != WPA_PSK_KEY_CHAR_SIZE))
1822 g_string_free(key_string, TRUE);
1823 g_byte_array_free(key_ba, TRUE);
1827 /* No ssid has been created ... */
1828 /* Free the array of strings */
1833 /* Key was correct!!! Create the new decryption_key_t ... */
1834 dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
1836 dk->type = AIRPDCAP_KEY_TYPE_WPA_PMK;
1837 dk->key = g_string_new(key);
1838 dk->bits = dk->key->len * 4;
1841 g_string_free(key_string, TRUE);
1842 g_byte_array_free(key_ba, TRUE);
1846 /* Free the array of strings */
1850 else if(g_ascii_strcasecmp(type,STRING_KEY_TYPE_WPA_PWD) == 0) /* WPA key *//* If the number of tokens is more than three, we accept the string... if the first three tokens are correct... */
1852 /* Create a new string */
1853 key_string = g_string_new(key);
1856 /* Three (or more) tokens mean that the user entered a WPA-PWD key ... */
1857 if( ((key_string->len) > WPA_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WPA_KEY_MIN_CHAR_SIZE))
1859 g_string_free(key_string, TRUE);
1865 /* Free the array of strings */
1870 if(ssid != NULL) /* more than three tokens found, means that the user specified the ssid */
1872 ssid_ba = g_byte_array_new();
1873 if (! uri_str_to_bytes(ssid, ssid_ba)) {
1874 g_string_free(key_string, TRUE);
1875 g_byte_array_free(ssid_ba, TRUE);
1879 /* Free the array of strings */
1884 if(ssid_ba->len > WPA_SSID_MAX_CHAR_SIZE)
1886 g_string_free(key_string, TRUE);
1887 g_byte_array_free(ssid_ba, TRUE);
1893 /* Free the array of strings */
1899 /* Key was correct!!! Create the new decryption_key_t ... */
1900 dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
1902 dk->type = AIRPDCAP_KEY_TYPE_WPA_PWD;
1903 dk->key = g_string_new(key);
1904 dk->bits = 256; /* This is the length of the array pf bytes that will be generated using key+ssid ...*/
1905 dk->ssid = byte_array_dup(ssid_ba); /* NULL if ssid_ba is NULL */
1907 g_string_free(key_string, TRUE);
1908 if (ssid_ba != NULL)
1909 g_byte_array_free(ssid_ba, TRUE);
1916 /* Free the array of strings */
1921 /* Something was wrong ... free everything */
1926 g_free(ssid); /* It is not always present */
1927 if (ssid_ba != NULL)
1928 g_byte_array_free(ssid_ba, TRUE);
1930 /* Free the array of strings */
1937 * Returns a newly allocated string representing the given decryption_key_t
1938 * struct, or NULL if something is wrong...
1941 get_key_string(decryption_key_t* dk)
1943 gchar* output_string = NULL;
1945 if(dk == NULL || dk->key == NULL)
1949 case AIRPDCAP_KEY_TYPE_WEP:
1950 output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WEP,dk->key->str);
1952 case AIRPDCAP_KEY_TYPE_WPA_PWD:
1953 if(dk->ssid == NULL)
1954 output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WPA_PWD,dk->key->str);
1956 output_string = g_strdup_printf("%s:%s:%s",
1957 STRING_KEY_TYPE_WPA_PWD, dk->key->str,
1958 format_uri(dk->ssid, ":"));
1960 case AIRPDCAP_KEY_TYPE_WPA_PMK:
1961 output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WPA_PSK,dk->key->str);
1968 return output_string;
1975 /****************************************************************************/
1983 * set-tabs-mode: nil
1986 * ex: set shiftwidth=4 tabstop=8 expandtab
1987 * :indentSize=4:tabSize=8:noTabs=true: