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 <wsutil/crc32.h>
44 #include <wsutil/rc4.h>
45 #include <wsutil/sha1.h>
46 #include <wsutil/md5.h>
47 #include <wsutil/pint.h>
49 #include <epan/tvbuff.h>
50 #include <epan/to_str.h>
51 #include <epan/strutil.h>
52 #include <epan/emem.h>
53 #include <epan/crypt/airpdcap_rijndael.h>
55 #include "airpdcap_system.h"
56 #include "airpdcap_int.h"
58 #include "airpdcap_debug.h"
60 #include "wep-wpadefs.h"
63 /****************************************************************************/
65 /****************************************************************************/
66 /* Constant definitions */
68 #define AIRPDCAP_SHA_DIGEST_LEN 20
70 /* EAPOL definitions */
72 * Length of the EAPOL-Key key confirmation key (KCK) used to calculate
73 * MIC over EAPOL frame and validate an EAPOL packet (128 bits)
75 #define AIRPDCAP_WPA_KCK_LEN 16
77 *Offset of the Key MIC in the EAPOL packet body
79 #define AIRPDCAP_WPA_MICKEY_OFFSET 77
81 * Maximum length of the EAPOL packet (it depends on the maximum MAC
84 #define AIRPDCAP_WPA_MAX_EAPOL_LEN 4095
86 * EAPOL Key Descriptor Version 1, used for all EAPOL-Key frames to and
87 * from a STA when neither the group nor pairwise ciphers are CCMP for
90 * Defined in 802.11i-2004, page 78
92 #define AIRPDCAP_WPA_KEY_VER_NOT_CCMP 1
94 * EAPOL Key Descriptor Version 2, used for all EAPOL-Key frames to and
95 * from a STA when either the pairwise or the group cipher is AES-CCMP
96 * for Key Descriptor 2.
98 * Defined in 802.11i-2004, page 78
100 #define AIRPDCAP_WPA_KEY_VER_AES_CCMP 2
102 /** Define EAPOL Key Descriptor type values: use 254 for WPA and 2 for WPA2 **/
103 #define AIRPDCAP_RSN_WPA_KEY_DESCRIPTOR 254
104 #define AIRPDCAP_RSN_WPA2_KEY_DESCRIPTOR 2
106 /****************************************************************************/
110 /****************************************************************************/
111 /* Macro definitions */
113 extern const UINT32 crc32_table
[256];
114 #define CRC(crc, ch) (crc = (crc >> 8) ^ crc32_table[(crc ^ (ch)) & 0xff])
116 #define AIRPDCAP_GET_TK(ptk) (ptk + 32)
118 /****************************************************************************/
120 /****************************************************************************/
121 /* Type definitions */
123 /* Internal function prototype declarations */
130 * It is a step of the PBKDF2 (specifically the PKCS #5 v2.0) defined in
131 * the RFC 2898 to derive a key (used as PMK in WPA)
132 * @param ppbytes [IN] pointer to a password (sequence of between 8 and
133 * 63 ASCII encoded characters)
134 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
136 * @param iterations [IN] times to hash the password (4096 for WPA)
137 * @param count [IN] ???
138 * @param output [OUT] pointer to a preallocated buffer of
139 * AIRPDCAP_SHA_DIGEST_LEN characters that will contain a part of the key
141 static INT
AirPDcapRsnaPwd2PskStep(
142 const guint8
*ppbytes
,
143 const guint passLength
,
145 const size_t ssidLength
,
146 const INT iterations
,
152 * It calculates the passphrase-to-PSK mapping reccomanded for use with
153 * RSNAs. This implementation uses the PBKDF2 method defined in the RFC
155 * @param passphrase [IN] pointer to a password (sequence of between 8 and
156 * 63 ASCII encoded characters)
157 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
159 * @param output [OUT] calculated PSK (to use as PMK in WPA)
161 * Described in 802.11i-2004, page 165
163 static INT
AirPDcapRsnaPwd2Psk(
164 const CHAR
*passphrase
,
166 const size_t ssidLength
,
170 static INT
AirPDcapRsnaMng(
172 guint mac_header_len
,
174 PAIRPDCAP_KEY_ITEM key
,
175 AIRPDCAP_SEC_ASSOCIATION
*sa
,
179 static INT
AirPDcapWepMng(
180 PAIRPDCAP_CONTEXT ctx
,
182 guint mac_header_len
,
184 PAIRPDCAP_KEY_ITEM key
,
185 AIRPDCAP_SEC_ASSOCIATION
*sa
,
189 static INT
AirPDcapRsna4WHandshake(
190 PAIRPDCAP_CONTEXT ctx
,
192 AIRPDCAP_SEC_ASSOCIATION
*sa
,
193 PAIRPDCAP_KEY_ITEM key
,
197 * It checks whether the specified key is corrected or not.
199 * For a standard WEP key the length will be changed to the standard
200 * length, and the type changed in a generic WEP key.
201 * @param key [IN] pointer to the key to validate
203 * - TRUE: the key contains valid fields and values
204 * - FALSE: the key has some invalid field or value
206 static INT
AirPDcapValidateKey(
207 PAIRPDCAP_KEY_ITEM key
)
210 static INT
AirPDcapRsnaMicCheck(
213 UCHAR KCK
[AIRPDCAP_WPA_KCK_LEN
],
218 * @param ctx [IN] pointer to the current context
219 * @param id [IN] id of the association (composed by BSSID and MAC of
222 * - index of the Security Association structure if found
223 * - -1, if the specified addresses pair BSSID-STA MAC has not been found
225 static INT
AirPDcapGetSa(
226 PAIRPDCAP_CONTEXT ctx
,
227 AIRPDCAP_SEC_ASSOCIATION_ID
*id
)
230 static INT
AirPDcapStoreSa(
231 PAIRPDCAP_CONTEXT ctx
,
232 AIRPDCAP_SEC_ASSOCIATION_ID
*id
)
235 static const UCHAR
* AirPDcapGetStaAddress(
236 const AIRPDCAP_MAC_FRAME_ADDR4
*frame
)
239 static const UCHAR
* AirPDcapGetBssidAddress(
240 const AIRPDCAP_MAC_FRAME_ADDR4
*frame
)
243 static void AirPDcapRsnaPrfX(
244 AIRPDCAP_SEC_ASSOCIATION
*sa
,
246 const UCHAR snonce
[32],
247 const INT x
, /* for TKIP 512, for CCMP 384 */
255 /****************************************************************************/
257 /****************************************************************************/
258 /* Exported function definitions */
264 const guint8 broadcast_mac
[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
267 /* NOTE : this assumes the WPA RSN IE format. If it were to be a generic RSN IE, then
268 we would need to change the structure since it could be variable length depending on the number
269 of unicast OUI and auth OUI. */
275 guint8 multicastOUI
[4];
276 guint16 iUnicastCount
; /* this should always be 1 for WPA client */
277 guint8 unicastOUI
[4];
278 guint16 iAuthCount
; /* this should always be 1 for WPA client */
283 #define EAPKEY_MIC_LEN 16 /* length of the MIC key for EAPoL_Key packet's MIC using MD5 */
288 guint8 key_information
[2]; /* Make this an array to avoid alignment issues */
289 guint8 key_length
[2]; /* Make this an array to avoid alignment issues */
290 guint8 replay_counter
[8];
291 guint8 key_nonce
[NONCE_LEN
];
293 guint8 key_sequence_counter
[8]; /* also called the RSC */
295 guint8 key_mic
[EAPKEY_MIC_LEN
];
296 guint8 key_data_len
[2]; /* Make this an array rather than a U16 to avoid alignment shifting */
297 guint8 ie
[sizeof(RSN_IE
)]; /* Make this an array to avoid alignment issues */
298 } EAPOL_RSN_KEY
, * P_EAPOL_RSN_KEY
;
302 /* A note about some limitations with the WPA decryption:
304 Unless someone takes the time to restructure the current method used for maintaining decryption keys, there
305 will be some anomalies observed when using the decryption feature.
307 Currently, there is only one pairwise (unicast) key and one group (broadcast) key saved for each security association
308 (SA). As a result, if a wireless sniffer session captures the traffic of a station (STA) associating with an AP
309 more than once, or captures a STA roaming, then you will not be able to arbitrarilly click on different encrypted
310 packets in the trace and observe their internal decrypted structure. This is because when you click on a packet,
311 Wireshark immediately performs the decryption routine with whatever the last key used was. It does not maintain a
312 cache of all the keys that were used by this STA/AP pairing.
314 However, if you are just looking at the summary lines of a capture, it will appear that everything was decrypted properly.
315 This is because when first performing a capture or initially reading a capture file, Wireshark will first
316 process the packets in order. As it encounters new EAPOL packets, it will update its internal key list with the
317 newfound key. Then it will use that key for decrypting subsequent packets. Each time a new key is found, the old key
318 is overwritten. So, if you then click on a packet that was previously decrypted properly, it might suddenly no longer
319 be decrypted because a later EAPOL key had caused the internal decryption key to be updated.
321 For broadcast packets, there is a clunky work-around. If the AP is using group-key rotation, you simply have to find the appropriate
322 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
323 and then click on the broadcast packet you are trying to decrypt, the packet will be decrypted properly. By first
324 clicking on the EAPOL packet for the group-key, you will force Wireshark to parse that packet and load the group-key it
325 contains. That group key will then be used for decrypting all subsequent broadcast packets you click on.
327 Ideally, it would be best to maintain an expanding list of SA keys. Perhaps we could associate packet number ranges
328 that they apply to. Then, whenever we need to decrypt a packet, we can determine which key to use based on whether
329 it is broadcast or unicast and within what packet number range it falls.
331 Either that, or store two versions of encrypted packets - the orginal packet and its successfully
332 decrypted version. Then Wireshark wouldn't have to decrypt packets on the fly if they were already successfully decrypted.
338 AirPDcapDecryptWPABroadcastKey(const EAPOL_RSN_KEY
*pEAPKey
, guint8
*decryption_key
, PAIRPDCAP_SEC_ASSOCIATION sa
)
342 guint8
*szEncryptedKey
;
344 static AIRPDCAP_KEY_ITEM dummy_key
; /* needed in case AirPDcapRsnaMng() wants the key structure */
346 /* 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. */
348 /* Preparation for decrypting the group key - determine group key data length */
349 /* depending on whether it's a TKIP or AES encryption key */
350 key_version
= AIRPDCAP_EAP_KEY_DESCR_VER(pEAPKey
->key_information
[1]);
351 if (key_version
== AIRPDCAP_WPA_KEY_VER_NOT_CCMP
){
353 key_len
= pntohs(pEAPKey
->key_length
);
354 }else if (key_version
== AIRPDCAP_WPA_KEY_VER_AES_CCMP
){
356 key_len
= pntohs(pEAPKey
->key_data_len
);
358 if (key_len
> sizeof(RSN_IE
) || key_len
== 0) { /* 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
= (guint8
*)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 its 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 static 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 static INT
AirPDcapScanForGroupKey(
464 PAIRPDCAP_CONTEXT ctx
,
466 const guint mac_header_len
,
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 const 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
= (const 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 ( (addr
=AirPDcapGetBssidAddress((const AIRPDCAP_MAC_FRAME_ADDR4
*)(data
))) != NULL
) {
550 memcpy(id
.bssid
, addr
, 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 ( (addr
=AirPDcapGetStaAddress((const AIRPDCAP_MAC_FRAME_ADDR4
*)(data
))) != NULL
) {
573 memcpy(id
.sta
, addr
, 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
,
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 */
624 const guint8 bt_dot1x_header
[] = {
625 0xAA, /* DSAP=SNAP */
626 0xAA, /* SSAP=SNAP */
627 0x03, /* Control field=Unnumbered frame */
628 0x00, 0x19, 0x58, /* Org. code=Bluetooth SIG */
629 0x00, 0x03 /* Type: Bluetooth Security */
636 AIRPDCAP_DEBUG_TRACE_START("AirPDcapPacketProcess");
639 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL context", AIRPDCAP_DEBUG_LEVEL_5
);
640 AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess");
641 return AIRPDCAP_RET_UNSUCCESS
;
643 if (data
==NULL
|| tot_len
==0) {
644 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL data or length=0", AIRPDCAP_DEBUG_LEVEL_5
);
645 AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess");
646 return AIRPDCAP_RET_UNSUCCESS
;
649 /* check if the packet is of data type */
650 if (AIRPDCAP_TYPE(data
[0])!=AIRPDCAP_TYPE_DATA
) {
651 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "not data packet", AIRPDCAP_DEBUG_LEVEL_5
);
652 return AIRPDCAP_RET_NO_DATA
;
655 /* check correct packet size, to avoid wrong elaboration of encryption algorithms */
656 if (tot_len
< (UINT
)(mac_header_len
+AIRPDCAP_CRYPTED_DATA_MINLEN
)) {
657 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "minimum length violated", AIRPDCAP_DEBUG_LEVEL_5
);
658 return AIRPDCAP_RET_WRONG_DATA_SIZE
;
662 if ( (addr
=AirPDcapGetBssidAddress((const AIRPDCAP_MAC_FRAME_ADDR4
*)(data
))) != NULL
) {
663 memcpy(id
.bssid
, addr
, AIRPDCAP_MAC_LEN
);
665 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]);
667 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf
, AIRPDCAP_DEBUG_LEVEL_3
);
669 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "BSSID not found", AIRPDCAP_DEBUG_LEVEL_5
);
670 return AIRPDCAP_RET_REQ_DATA
;
673 /* get STA address */
674 if ( (addr
=AirPDcapGetStaAddress((const AIRPDCAP_MAC_FRAME_ADDR4
*)(data
))) != NULL
) {
675 memcpy(id
.sta
, addr
, AIRPDCAP_MAC_LEN
);
677 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]);
679 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf
, AIRPDCAP_DEBUG_LEVEL_3
);
681 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "SA not found", AIRPDCAP_DEBUG_LEVEL_5
);
682 return AIRPDCAP_RET_REQ_DATA
;
685 /* get the Security Association structure for the STA and AP */
686 sa
= AirPDcapGetSaPtr(ctx
, &id
);
688 return AIRPDCAP_RET_UNSUCCESS
;
691 /* cache offset in the packet data (to scan encryption data) */
692 offset
= mac_header_len
;
694 /* check if data is encrypted (use the WEP bit in the Frame Control field) */
695 if (AIRPDCAP_WEP(data
[1])==0)
698 /* data is sent in cleartext, check if is an authentication message or end the process */
699 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Unencrypted data", AIRPDCAP_DEBUG_LEVEL_3
);
701 /* check if the packet as an LLC header and the packet is 802.1X authentication (IEEE 802.1X-2004, pg. 24) */
702 if (memcmp(data
+offset
, dot1x_header
, 8) == 0 || memcmp(data
+offset
, bt_dot1x_header
, 8) == 0) {
703 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Authentication: EAPOL packet", AIRPDCAP_DEBUG_LEVEL_3
);
705 /* skip LLC header */
708 /* check the version of the EAPOL protocol used (IEEE 802.1X-2004, pg. 24) */
709 /* TODO EAPOL protocol version to check? */
711 if (data
[offset
]!=2) {
712 AIRPDCAP_DEBUG_PRINT_LINE("EAPOL protocol version not recognized", AIRPDCAP_DEBUG_LEVEL_5
);
713 return AIRPDCAP_RET_NO_VALID_HANDSHAKE
;
717 /* check if the packet is a EAPOL-Key (0x03) (IEEE 802.1X-2004, pg. 25) */
718 if (data
[offset
+1]!=3) {
719 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not EAPOL-Key", AIRPDCAP_DEBUG_LEVEL_5
);
720 return AIRPDCAP_RET_NO_VALID_HANDSHAKE
;
723 /* get and check the body length (IEEE 802.1X-2004, pg. 25) */
724 bodyLength
=pntohs(data
+offset
+2);
725 if ((tot_len
-offset
-4) < bodyLength
) {
726 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "EAPOL body too short", AIRPDCAP_DEBUG_LEVEL_5
);
727 return AIRPDCAP_RET_NO_VALID_HANDSHAKE
;
730 /* skip EAPOL MPDU and go to the first byte of the body */
733 /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */
734 if (/*data[offset]!=0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */
735 data
[offset
]!=0x2 && /* IEEE 802.11 Key Descriptor Type */
736 data
[offset
]!=0xFE) /* TODO what's this value??? */
738 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not valid key descriptor type", AIRPDCAP_DEBUG_LEVEL_5
);
739 return AIRPDCAP_RET_NO_VALID_HANDSHAKE
;
742 /* start with descriptor body */
745 /* manage the 4-way handshake to define the key */
746 return AirPDcapRsna4WHandshake(ctx
, data
, sa
, key
, offset
);
748 /* cleartext message, not authentication */
749 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "No authentication data", AIRPDCAP_DEBUG_LEVEL_5
);
750 return AIRPDCAP_RET_NO_DATA_ENCRYPTED
;
756 if (decrypt_data
==NULL
)
757 return AIRPDCAP_RET_UNSUCCESS
;
759 /* create new header and data to modify */
760 *decrypt_len
= tot_len
;
761 memcpy(decrypt_data
, data
, *decrypt_len
);
764 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Encrypted data", AIRPDCAP_DEBUG_LEVEL_3
);
766 /* check the Extension IV to distinguish between WEP encryption and WPA encryption */
767 /* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */
768 /* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */
769 /* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */
770 if (AIRPDCAP_EXTIV(data
[offset
+3])==0) {
771 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "WEP encryption", AIRPDCAP_DEBUG_LEVEL_3
);
772 return AirPDcapWepMng(ctx
, decrypt_data
, mac_header_len
, decrypt_len
, key
, sa
, offset
);
775 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "TKIP or CCMP encryption", AIRPDCAP_DEBUG_LEVEL_3
);
777 /* If index >= 1, then use the group key. This will not work if the AP is using
778 more than one group key simultaneously. I've not seen this in practice, however.
779 Usually an AP will rotate between the two key index values of 1 and 2 whenever
780 it needs to change the group key to be used. */
781 if (AIRPDCAP_KEY_INDEX(data
[offset
+3])>=1){
783 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "The key index = 1. This is encrypted with a group key.", AIRPDCAP_DEBUG_LEVEL_3
);
785 /* force STA address to broadcast MAC so we load the SA for the groupkey */
786 memcpy(id
.sta
, broadcast_mac
, AIRPDCAP_MAC_LEN
);
789 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]);
790 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf
, AIRPDCAP_DEBUG_LEVEL_3
);
793 /* search for a cached Security Association for current BSSID and broadcast MAC */
794 sa
= AirPDcapGetSaPtr(ctx
, &id
);
796 return AIRPDCAP_RET_UNSUCCESS
;
800 /* Decrypt the packet using the appropriate SA */
801 status
= AirPDcapRsnaMng(decrypt_data
, mac_header_len
, decrypt_len
, key
, sa
, offset
);
803 /* If we successfully decrypted a packet, scan it to see if it contains a group key handshake.
804 The group key handshake could be sent at any time the AP wants to change the key (such as when
805 it is using key rotation) so we must scan every packet. */
806 if (status
== AIRPDCAP_RET_SUCCESS
)
807 AirPDcapScanForGroupKey(ctx
, decrypt_data
, mac_header_len
, *decrypt_len
);
813 return AIRPDCAP_RET_UNSUCCESS
;
817 PAIRPDCAP_CONTEXT ctx
,
818 AIRPDCAP_KEY_ITEM keys
[],
819 const size_t keys_nr
)
823 AIRPDCAP_DEBUG_TRACE_START("AirPDcapSetKeys");
825 if (ctx
==NULL
|| keys
==NULL
) {
826 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "NULL context or NULL keys array", AIRPDCAP_DEBUG_LEVEL_3
);
827 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
831 if (keys_nr
>AIRPDCAP_MAX_KEYS_NR
) {
832 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Keys number greater than maximum", AIRPDCAP_DEBUG_LEVEL_3
);
833 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
837 /* clean key and SA collections before setting new ones */
838 AirPDcapInitContext(ctx
);
840 /* check and insert keys */
841 for (i
=0, success
=0; i
<(INT
)keys_nr
; i
++) {
842 if (AirPDcapValidateKey(keys
+i
)==TRUE
) {
843 if (keys
[i
].KeyType
==AIRPDCAP_KEY_TYPE_WPA_PWD
) {
844 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PWD key", AIRPDCAP_DEBUG_LEVEL_4
);
845 AirPDcapRsnaPwd2Psk(keys
[i
].UserPwd
.Passphrase
, keys
[i
].UserPwd
.Ssid
, keys
[i
].UserPwd
.SsidLen
, keys
[i
].KeyData
.Wpa
.Psk
);
848 else if (keys
[i
].KeyType
==AIRPDCAP_KEY_TYPE_WPA_PMK
) {
849 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PMK key", AIRPDCAP_DEBUG_LEVEL_4
);
850 } else if (keys
[i
].KeyType
==AIRPDCAP_KEY_TYPE_WEP
) {
851 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WEP key", AIRPDCAP_DEBUG_LEVEL_4
);
853 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a key", AIRPDCAP_DEBUG_LEVEL_4
);
856 memcpy(&ctx
->keys
[success
], &keys
[i
], sizeof(keys
[i
]));
861 ctx
->keys_nr
=success
;
863 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
869 PAIRPDCAP_CONTEXT ctx
)
871 AIRPDCAP_DEBUG_TRACE_START("AirPDcapCleanKeys");
874 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5
);
875 AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys");
879 memset(ctx
->keys
, 0, sizeof(AIRPDCAP_KEY_ITEM
) * AIRPDCAP_MAX_KEYS_NR
);
883 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapCleanKeys", "Keys collection cleaned!", AIRPDCAP_DEBUG_LEVEL_5
);
884 AIRPDCAP_DEBUG_TRACE_END("AirPDcapCleanKeys");
888 const PAIRPDCAP_CONTEXT ctx
,
889 AIRPDCAP_KEY_ITEM keys
[],
890 const size_t keys_nr
)
894 AIRPDCAP_DEBUG_TRACE_START("AirPDcapGetKeys");
897 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5
);
898 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
900 } else if (keys
==NULL
) {
901 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL keys array", AIRPDCAP_DEBUG_LEVEL_5
);
902 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
903 return (INT
)ctx
->keys_nr
;
905 for (i
=0, j
=0; i
<ctx
->keys_nr
&& i
<keys_nr
&& i
<AIRPDCAP_MAX_KEYS_NR
; i
++) {
906 memcpy(&keys
[j
], &ctx
->keys
[i
], sizeof(keys
[j
]));
908 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "Got a key", AIRPDCAP_DEBUG_LEVEL_5
);
911 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
917 * XXX - This won't be reliable if a packet containing SSID "B" shows
918 * up in the middle of a 4-way handshake for SSID "A".
919 * We should probably use a small array or hash table to keep multiple
922 INT
AirPDcapSetLastSSID(
923 PAIRPDCAP_CONTEXT ctx
,
927 if (!ctx
|| !pkt_ssid
|| pkt_ssid_len
< 1 || pkt_ssid_len
> WPA_SSID_MAX_SIZE
)
928 return AIRPDCAP_RET_UNSUCCESS
;
930 memcpy(ctx
->pkt_ssid
, pkt_ssid
, pkt_ssid_len
);
931 ctx
->pkt_ssid_len
= pkt_ssid_len
;
933 return AIRPDCAP_RET_SUCCESS
;
936 INT
AirPDcapInitContext(
937 PAIRPDCAP_CONTEXT ctx
)
939 AIRPDCAP_DEBUG_TRACE_START("AirPDcapInitContext");
942 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5
);
943 AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext");
944 return AIRPDCAP_RET_UNSUCCESS
;
947 AirPDcapCleanKeys(ctx
);
949 ctx
->first_free_index
=0;
952 ctx
->pkt_ssid_len
= 0;
954 memset(ctx
->sa
, 0, AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR
* sizeof(AIRPDCAP_SEC_ASSOCIATION
));
956 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "Context initialized!", AIRPDCAP_DEBUG_LEVEL_5
);
957 AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext");
958 return AIRPDCAP_RET_SUCCESS
;
961 INT
AirPDcapDestroyContext(
962 PAIRPDCAP_CONTEXT ctx
)
964 AIRPDCAP_DEBUG_TRACE_START("AirPDcapDestroyContext");
967 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5
);
968 AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext");
969 return AIRPDCAP_RET_UNSUCCESS
;
972 AirPDcapCleanKeys(ctx
);
974 ctx
->first_free_index
=0;
978 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "Context destroyed!", AIRPDCAP_DEBUG_LEVEL_5
);
979 AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext");
980 return AIRPDCAP_RET_SUCCESS
;
987 /****************************************************************************/
989 /****************************************************************************/
990 /* Internal function definitions */
999 guint mac_header_len
,
1001 PAIRPDCAP_KEY_ITEM key
,
1002 AIRPDCAP_SEC_ASSOCIATION
*sa
,
1007 guint try_data_len
= *decrypt_len
;
1009 if (sa
->key
==NULL
) {
1010 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "No key associated", AIRPDCAP_DEBUG_LEVEL_3
);
1011 return AIRPDCAP_RET_REQ_DATA
;
1013 if (sa
->validKey
==FALSE
) {
1014 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "Key not yet valid", AIRPDCAP_DEBUG_LEVEL_3
);
1015 return AIRPDCAP_RET_UNSUCCESS
;
1018 /* allocate a temp buffer for the decryption loop */
1019 try_data
=(UCHAR
*)ep_alloc(try_data_len
);
1021 /* start of loop added by GCS */
1022 for(/* sa */; sa
!= NULL
;sa
=sa
->next
) {
1024 if (*decrypt_len
> try_data_len
) {
1025 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "Invalid decryption length", AIRPDCAP_DEBUG_LEVEL_3
);
1026 return AIRPDCAP_RET_UNSUCCESS
;
1029 /* copy the encrypted data into a temp buffer */
1030 memcpy(try_data
, decrypt_data
, *decrypt_len
);
1032 if (sa
->wpa
.key_ver
==1) {
1033 /* CCMP -> HMAC-MD5 is the EAPOL-Key MIC, RC4 is the EAPOL-Key encryption algorithm */
1034 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP", AIRPDCAP_DEBUG_LEVEL_3
);
1035 DEBUG_DUMP("ptk", sa
->wpa
.ptk
, 64);
1036 DEBUG_DUMP("ptk portion used", AIRPDCAP_GET_TK(sa
->wpa
.ptk
), 16);
1038 ret_value
=AirPDcapTkipDecrypt(try_data
+offset
, *decrypt_len
-offset
, try_data
+AIRPDCAP_TA_OFFSET
, AIRPDCAP_GET_TK(sa
->wpa
.ptk
));
1040 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP failed!", AIRPDCAP_DEBUG_LEVEL_3
);
1044 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3
);
1045 /* remove MIC (8bytes) and ICV (4bytes) from the end of packet */
1049 /* AES-CCMP -> HMAC-SHA1-128 is the EAPOL-Key MIC, AES wep_key wrap is the EAPOL-Key encryption algorithm */
1050 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP", AIRPDCAP_DEBUG_LEVEL_3
);
1052 ret_value
=AirPDcapCcmpDecrypt(try_data
, mac_header_len
, (INT
)*decrypt_len
, AIRPDCAP_GET_TK(sa
->wpa
.ptk
));
1056 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3
);
1057 /* remove MIC (8bytes) from the end of packet */
1064 /* none of the keys worked */
1068 if (*decrypt_len
> try_data_len
|| *decrypt_len
< 8) {
1069 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "Invalid decryption length", AIRPDCAP_DEBUG_LEVEL_3
);
1070 return AIRPDCAP_RET_UNSUCCESS
;
1073 /* copy the decrypted data into the decrypt buffer GCS*/
1074 memcpy(decrypt_data
, try_data
, *decrypt_len
);
1076 /* remove protection bit */
1077 decrypt_data
[1]&=0xBF;
1079 /* remove TKIP/CCMP header */
1080 offset
= mac_header_len
;
1082 memmove(decrypt_data
+offset
, decrypt_data
+offset
+8, *decrypt_len
-offset
);
1085 memcpy(key
, sa
->key
, sizeof(AIRPDCAP_KEY_ITEM
));
1087 if (sa
->wpa
.key_ver
==AIRPDCAP_WPA_KEY_VER_NOT_CCMP
)
1088 key
->KeyType
=AIRPDCAP_KEY_TYPE_TKIP
;
1089 else if (sa
->wpa
.key_ver
==AIRPDCAP_WPA_KEY_VER_AES_CCMP
)
1090 key
->KeyType
=AIRPDCAP_KEY_TYPE_CCMP
;
1093 return AIRPDCAP_RET_SUCCESS
;
1098 PAIRPDCAP_CONTEXT ctx
,
1099 UCHAR
*decrypt_data
,
1100 guint mac_header_len
,
1102 PAIRPDCAP_KEY_ITEM key
,
1103 AIRPDCAP_SEC_ASSOCIATION
*sa
,
1106 UCHAR wep_key
[AIRPDCAP_WEP_KEY_MAXLEN
+AIRPDCAP_WEP_IVLEN
];
1110 AIRPDCAP_KEY_ITEM
*tmp_key
;
1111 UINT8 useCache
=FALSE
;
1113 guint try_data_len
= *decrypt_len
;
1115 try_data
= (UCHAR
*)ep_alloc(try_data_len
);
1120 for (key_index
=0; key_index
<(INT
)ctx
->keys_nr
; key_index
++) {
1121 /* use the cached one, or try all keys */
1123 tmp_key
=&ctx
->keys
[key_index
];
1125 if (sa
->key
!=NULL
&& sa
->key
->KeyType
==AIRPDCAP_KEY_TYPE_WEP
) {
1126 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try cached WEP key...", AIRPDCAP_DEBUG_LEVEL_3
);
1129 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Cached key is not valid, try another WEP key...", AIRPDCAP_DEBUG_LEVEL_3
);
1130 tmp_key
=&ctx
->keys
[key_index
];
1134 /* obviously, try only WEP keys... */
1135 if (tmp_key
->KeyType
==AIRPDCAP_KEY_TYPE_WEP
)
1137 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try WEP key...", AIRPDCAP_DEBUG_LEVEL_3
);
1139 memset(wep_key
, 0, sizeof(wep_key
));
1140 memcpy(try_data
, decrypt_data
, *decrypt_len
);
1142 /* 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) */
1143 memcpy(wep_key
, try_data
+mac_header_len
, AIRPDCAP_WEP_IVLEN
);
1144 keylen
=tmp_key
->KeyData
.Wep
.WepKeyLen
;
1145 memcpy(wep_key
+AIRPDCAP_WEP_IVLEN
, tmp_key
->KeyData
.Wep
.WepKey
, keylen
);
1147 ret_value
=AirPDcapWepDecrypt(wep_key
,
1148 keylen
+AIRPDCAP_WEP_IVLEN
,
1149 try_data
+ (mac_header_len
+AIRPDCAP_WEP_IVLEN
+AIRPDCAP_WEP_KIDLEN
),
1150 *decrypt_len
-(mac_header_len
+AIRPDCAP_WEP_IVLEN
+AIRPDCAP_WEP_KIDLEN
+AIRPDCAP_CRC_LEN
));
1152 if (ret_value
== AIRPDCAP_RET_SUCCESS
)
1153 memcpy(decrypt_data
, try_data
, *decrypt_len
);
1156 if (!ret_value
&& tmp_key
->KeyType
==AIRPDCAP_KEY_TYPE_WEP
) {
1157 /* the tried key is the correct one, cached in the Security Association */
1162 memcpy(key
, &sa
->key
, sizeof(AIRPDCAP_KEY_ITEM
));
1163 key
->KeyType
=AIRPDCAP_KEY_TYPE_WEP
;
1168 /* the cached key was not valid, try other keys */
1170 if (useCache
==TRUE
) {
1180 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "WEP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3
);
1182 /* remove ICV (4bytes) from the end of packet */
1185 if (*decrypt_len
< 4) {
1186 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Decryption length too short", AIRPDCAP_DEBUG_LEVEL_3
);
1187 return AIRPDCAP_RET_UNSUCCESS
;
1190 /* remove protection bit */
1191 decrypt_data
[1]&=0xBF;
1193 /* remove IC header */
1194 offset
= mac_header_len
;
1196 memcpy(decrypt_data
+offset
, decrypt_data
+offset
+AIRPDCAP_WEP_IVLEN
+AIRPDCAP_WEP_KIDLEN
, *decrypt_len
-offset
);
1198 return AIRPDCAP_RET_SUCCESS
;
1201 /* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */
1203 AirPDcapRsna4WHandshake(
1204 PAIRPDCAP_CONTEXT ctx
,
1206 AIRPDCAP_SEC_ASSOCIATION
*sa
,
1207 PAIRPDCAP_KEY_ITEM key
,
1210 AIRPDCAP_KEY_ITEM
*tmp_key
, *tmp_pkt_key
, pkt_key
;
1211 AIRPDCAP_SEC_ASSOCIATION
*tmp_sa
;
1214 UCHAR useCache
=FALSE
;
1215 UCHAR eapol
[AIRPDCAP_EAPOL_MAX_LEN
];
1221 /* a 4-way handshake packet use a Pairwise key type (IEEE 802.11i-2004, pg. 79) */
1222 if (AIRPDCAP_EAP_KEY(data
[offset
+1])!=1) {
1223 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Group/STAKey message (not used)", AIRPDCAP_DEBUG_LEVEL_5
);
1224 return AIRPDCAP_RET_NO_VALID_HANDSHAKE
;
1227 /* TODO timeouts? */
1229 /* This saves the sa since we are reauthenticating which will overwrite our current sa GCS*/
1230 if(sa
->handshake
== 4) {
1231 tmp_sa
=(AIRPDCAP_SEC_ASSOCIATION
*)se_alloc(sizeof(AIRPDCAP_SEC_ASSOCIATION
));
1232 memcpy(tmp_sa
, sa
, sizeof(AIRPDCAP_SEC_ASSOCIATION
));
1236 /* TODO consider key-index */
1238 /* TODO considera Deauthentications */
1240 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake...", AIRPDCAP_DEBUG_LEVEL_5
);
1242 /* manage 4-way handshake packets; this step completes the 802.1X authentication process (IEEE 802.11i-2004, pag. 85) */
1244 /* message 1: Authenticator->Supplicant (Sec=0, Mic=0, Ack=1, Inst=0, Key=1(pairwise), KeyRSC=0, Nonce=ANonce, MIC=0) */
1245 if (AIRPDCAP_EAP_INST(data
[offset
+1])==0 &&
1246 AIRPDCAP_EAP_ACK(data
[offset
+1])==1 &&
1247 AIRPDCAP_EAP_MIC(data
[offset
])==0)
1249 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 1", AIRPDCAP_DEBUG_LEVEL_3
);
1251 /* On reception of Message 1, the Supplicant determines whether the Key Replay Counter field value has been */
1252 /* used before with the current PMKSA. If the Key Replay Counter field value is less than or equal to the current */
1253 /* local value, the Supplicant discards the message. */
1254 /* -> not checked, the Authenticator will be send another Message 1 (hopefully!) */
1256 /* save ANonce (from authenticator) to derive the PTK with the SNonce (from the 2 message) */
1257 memcpy(sa
->wpa
.nonce
, data
+offset
+12, 32);
1259 /* get the Key Descriptor Version (to select algorithm used in decryption -CCMP or TKIP-) */
1260 sa
->wpa
.key_ver
=AIRPDCAP_EAP_KEY_DESCR_VER(data
[offset
+1]);
1264 return AIRPDCAP_RET_SUCCESS_HANDSHAKE
;
1267 /* 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)) */
1268 if (AIRPDCAP_EAP_INST(data
[offset
+1])==0 &&
1269 AIRPDCAP_EAP_ACK(data
[offset
+1])==0 &&
1270 AIRPDCAP_EAP_MIC(data
[offset
])==1)
1272 if (AIRPDCAP_EAP_SEC(data
[offset
])==0) {
1274 /* PATCH: some implementations set secure bit to 0 also in the 4th message */
1275 /* to recognize which message is this check if wep_key data length is 0 */
1276 /* in the 4th message */
1277 if (data
[offset
+92]!=0 || data
[offset
+93]!=0) {
1279 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 2", AIRPDCAP_DEBUG_LEVEL_3
);
1281 /* On reception of Message 2, the Authenticator checks that the key replay counter corresponds to the */
1282 /* outstanding Message 1. If not, it silently discards the message. */
1283 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, */
1284 /* the Authenticator silently discards Message 2. */
1285 /* -> not checked; the Supplicant will send another message 2 (hopefully!) */
1287 /* now you can derive the PTK */
1288 for (key_index
=0; key_index
<(INT
)ctx
->keys_nr
|| useCache
; key_index
++) {
1289 /* use the cached one, or try all keys */
1291 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try WPA key...", AIRPDCAP_DEBUG_LEVEL_3
);
1292 tmp_key
=&ctx
->keys
[key_index
];
1294 /* there is a cached key in the security association, if it's a WPA key try it... */
1295 if (sa
->key
!=NULL
&&
1296 (sa
->key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PWD
||
1297 sa
->key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PSK
||
1298 sa
->key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PMK
)) {
1299 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try cached WPA key...", AIRPDCAP_DEBUG_LEVEL_3
);
1302 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Cached key is of a wrong type, try WPA key...", AIRPDCAP_DEBUG_LEVEL_3
);
1303 tmp_key
=&ctx
->keys
[key_index
];
1307 /* obviously, try only WPA keys... */
1308 if (tmp_key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PWD
||
1309 tmp_key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PSK
||
1310 tmp_key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PMK
)
1312 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
) {
1313 /* We have a "wildcard" SSID. Use the one from the packet. */
1314 memcpy(&pkt_key
, tmp_key
, sizeof(pkt_key
));
1315 memcpy(&pkt_key
.UserPwd
.Ssid
, ctx
->pkt_ssid
, ctx
->pkt_ssid_len
);
1316 pkt_key
.UserPwd
.SsidLen
= ctx
->pkt_ssid_len
;
1317 AirPDcapRsnaPwd2Psk(pkt_key
.UserPwd
.Passphrase
, pkt_key
.UserPwd
.Ssid
,
1318 pkt_key
.UserPwd
.SsidLen
, pkt_key
.KeyData
.Wpa
.Psk
);
1319 tmp_pkt_key
= &pkt_key
;
1321 tmp_pkt_key
= tmp_key
;
1324 /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */
1325 AirPDcapRsnaPrfX(sa
, /* authenticator nonce, bssid, station mac */
1326 tmp_pkt_key
->KeyData
.Wpa
.Pmk
, /* PMK */
1327 data
+offset
+12, /* supplicant nonce */
1331 /* verify the MIC (compare the MIC in the packet included in this message with a MIC calculated with the PTK) */
1332 eapol_len
=pntohs(data
+offset
-3)+4;
1333 memcpy(eapol
, &data
[offset
-5], (eapol_len
<AIRPDCAP_EAPOL_MAX_LEN
?eapol_len
:AIRPDCAP_EAPOL_MAX_LEN
));
1334 ret_value
=AirPDcapRsnaMicCheck(eapol
, /* eapol frame (header also) */
1335 eapol_len
, /* eapol frame length */
1336 sa
->wpa
.ptk
, /* Key Confirmation Key */
1337 AIRPDCAP_EAP_KEY_DESCR_VER(data
[offset
+1])); /* EAPOL-Key description version */
1339 /* If the MIC is valid, the Authenticator checks that the RSN information element bit-wise matches */
1340 /* that from the (Re)Association Request message. */
1341 /* i) TODO If these are not exactly the same, the Authenticator uses MLME-DEAUTHENTICATE.request */
1342 /* primitive to terminate the association. */
1343 /* ii) If they do match bit-wise, the Authenticator constructs Message 3. */
1347 (tmp_key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PWD
||
1348 tmp_key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PSK
||
1349 tmp_key
->KeyType
==AIRPDCAP_KEY_TYPE_WPA_PMK
))
1351 /* the temporary key is the correct one, cached in the Security Association */
1356 memcpy(key
, &tmp_key
, sizeof(AIRPDCAP_KEY_ITEM
));
1357 if (AIRPDCAP_EAP_KEY_DESCR_VER(data
[offset
+1])==AIRPDCAP_WPA_KEY_VER_NOT_CCMP
)
1358 key
->KeyType
=AIRPDCAP_KEY_TYPE_TKIP
;
1359 else if (AIRPDCAP_EAP_KEY_DESCR_VER(data
[offset
+1])==AIRPDCAP_WPA_KEY_VER_AES_CCMP
)
1360 key
->KeyType
=AIRPDCAP_KEY_TYPE_CCMP
;
1365 /* the cached key was not valid, try other keys */
1367 if (useCache
==TRUE
) {
1375 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "handshake step failed", AIRPDCAP_DEBUG_LEVEL_3
);
1376 return AIRPDCAP_RET_NO_VALID_HANDSHAKE
;
1381 return AIRPDCAP_RET_SUCCESS_HANDSHAKE
;
1385 /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
1387 /* TODO check MIC and Replay Counter */
1388 /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */
1389 /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */
1390 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */
1391 /* Authenticator silently discards Message 4. */
1393 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4 (patched)", AIRPDCAP_DEBUG_LEVEL_3
);
1399 return AIRPDCAP_RET_SUCCESS_HANDSHAKE
;
1406 /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
1408 /* TODO check MIC and Replay Counter */
1409 /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */
1410 /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */
1411 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */
1412 /* Authenticator silently discards Message 4. */
1414 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4", AIRPDCAP_DEBUG_LEVEL_3
);
1420 return AIRPDCAP_RET_SUCCESS_HANDSHAKE
;
1424 /* message 3: Authenticator->Supplicant (Sec=1, Mic=1, Ack=1, Inst=0/1, Key=1(pairwise), KeyRSC=???, Nonce=ANonce, MIC=1) */
1425 if (AIRPDCAP_EAP_ACK(data
[offset
+1])==1 &&
1426 AIRPDCAP_EAP_MIC(data
[offset
])==1)
1428 const EAPOL_RSN_KEY
*pEAPKey
;
1429 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 3", AIRPDCAP_DEBUG_LEVEL_3
);
1431 /* On reception of Message 3, the Supplicant silently discards the message if the Key Replay Counter field */
1432 /* value has already been used or if the ANonce value in Message 3 differs from the ANonce value in Message 1. */
1433 /* -> not checked, the Authenticator will send another message 3 (hopefully!) */
1435 /* TODO check page 88 (RNS) */
1437 /* If using WPA2 PSK, message 3 will contain an RSN for the group key (GTK KDE).
1438 In order to properly support decrypting WPA2-PSK packets, we need to parse this to get the group key. */
1439 pEAPKey
= (const EAPOL_RSN_KEY
*)(&(data
[offset
-1]));
1440 if (pEAPKey
->type
== AIRPDCAP_RSN_WPA2_KEY_DESCRIPTOR
){
1441 PAIRPDCAP_SEC_ASSOCIATION broadcast_sa
;
1442 AIRPDCAP_SEC_ASSOCIATION_ID id
;
1444 /* Get broadcacst SA for the current BSSID */
1445 memcpy(id
.sta
, broadcast_mac
, AIRPDCAP_MAC_LEN
);
1446 memcpy(id
.bssid
, sa
->saId
.bssid
, AIRPDCAP_MAC_LEN
);
1447 broadcast_sa
= AirPDcapGetSaPtr(ctx
, &id
);
1449 if (broadcast_sa
== NULL
){
1450 return AIRPDCAP_RET_UNSUCCESS
;
1452 AirPDcapDecryptWPABroadcastKey(pEAPKey
, sa
->wpa
.ptk
+16, broadcast_sa
);
1455 return AIRPDCAP_RET_SUCCESS_HANDSHAKE
;
1458 return AIRPDCAP_RET_UNSUCCESS
;
1462 AirPDcapRsnaMicCheck(
1465 UCHAR KCK
[AIRPDCAP_WPA_KCK_LEN
],
1468 UCHAR mic
[AIRPDCAP_WPA_MICKEY_LEN
];
1469 UCHAR c_mic
[20]; /* MIC 16 byte, the HMAC-SHA1 use a buffer of 20 bytes */
1471 /* copy the MIC from the EAPOL packet */
1472 memcpy(mic
, eapol
+AIRPDCAP_WPA_MICKEY_OFFSET
+4, AIRPDCAP_WPA_MICKEY_LEN
);
1474 /* set to 0 the MIC in the EAPOL packet (to calculate the MIC) */
1475 memset(eapol
+AIRPDCAP_WPA_MICKEY_OFFSET
+4, 0, AIRPDCAP_WPA_MICKEY_LEN
);
1477 if (key_ver
==AIRPDCAP_WPA_KEY_VER_NOT_CCMP
) {
1478 /* use HMAC-MD5 for the EAPOL-Key MIC */
1479 md5_hmac(eapol
, eapol_len
, KCK
, AIRPDCAP_WPA_KCK_LEN
, c_mic
);
1480 } else if (key_ver
==AIRPDCAP_WPA_KEY_VER_AES_CCMP
) {
1481 /* use HMAC-SHA1-128 for the EAPOL-Key MIC */
1482 sha1_hmac(KCK
, AIRPDCAP_WPA_KCK_LEN
, eapol
, eapol_len
, c_mic
);
1484 /* key descriptor version not recognized */
1485 return AIRPDCAP_RET_UNSUCCESS
;
1487 /* compare calculated MIC with the Key MIC and return result (0 means success) */
1488 return memcmp(mic
, c_mic
, AIRPDCAP_WPA_MICKEY_LEN
);
1492 AirPDcapValidateKey(
1493 PAIRPDCAP_KEY_ITEM key
)
1497 AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey");
1500 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "NULL key", AIRPDCAP_DEBUG_LEVEL_5
);
1501 AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey");
1505 switch (key
->KeyType
) {
1506 case AIRPDCAP_KEY_TYPE_WEP
:
1507 /* check key size limits */
1508 len
=key
->KeyData
.Wep
.WepKeyLen
;
1509 if (len
<AIRPDCAP_WEP_KEY_MINLEN
|| len
>AIRPDCAP_WEP_KEY_MAXLEN
) {
1510 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WEP key: key length not accepted", AIRPDCAP_DEBUG_LEVEL_5
);
1515 case AIRPDCAP_KEY_TYPE_WEP_40
:
1516 /* set the standard length and use a generic WEP key type */
1517 key
->KeyData
.Wep
.WepKeyLen
=AIRPDCAP_WEP_40_KEY_LEN
;
1518 key
->KeyType
=AIRPDCAP_KEY_TYPE_WEP
;
1521 case AIRPDCAP_KEY_TYPE_WEP_104
:
1522 /* set the standard length and use a generic WEP key type */
1523 key
->KeyData
.Wep
.WepKeyLen
=AIRPDCAP_WEP_104_KEY_LEN
;
1524 key
->KeyType
=AIRPDCAP_KEY_TYPE_WEP
;
1527 case AIRPDCAP_KEY_TYPE_WPA_PWD
:
1528 /* check passphrase and SSID size limits */
1529 len
=strlen(key
->UserPwd
.Passphrase
);
1530 if (len
<AIRPDCAP_WPA_PASSPHRASE_MIN_LEN
|| len
>AIRPDCAP_WPA_PASSPHRASE_MAX_LEN
) {
1531 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: passphrase length not accepted", AIRPDCAP_DEBUG_LEVEL_5
);
1535 len
=key
->UserPwd
.SsidLen
;
1536 if (len
>AIRPDCAP_WPA_SSID_MAX_LEN
) {
1537 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: ssid length not accepted", AIRPDCAP_DEBUG_LEVEL_5
);
1543 case AIRPDCAP_KEY_TYPE_WPA_PSK
:
1546 case AIRPDCAP_KEY_TYPE_WPA_PMK
:
1553 AIRPDCAP_DEBUG_TRACE_END("AirPDcapValidateKey");
1559 PAIRPDCAP_CONTEXT ctx
,
1560 AIRPDCAP_SEC_ASSOCIATION_ID
*id
)
1564 if (ctx
->sa_index
!=-1) {
1565 /* at least one association was stored */
1566 /* search for the association from sa_index to 0 (most recent added) */
1567 for (sa_index
=ctx
->sa_index
; sa_index
>=0; sa_index
--) {
1568 if (ctx
->sa
[sa_index
].used
) {
1569 if (memcmp(id
, &(ctx
->sa
[sa_index
].saId
), sizeof(AIRPDCAP_SEC_ASSOCIATION_ID
))==0) {
1570 ctx
->index
=sa_index
;
1582 PAIRPDCAP_CONTEXT ctx
,
1583 AIRPDCAP_SEC_ASSOCIATION_ID
*id
)
1587 if (ctx
->sa
[ctx
->first_free_index
].used
) {
1588 /* last addition was in the middle of the array (and the first_free_index was just incremented by 1) */
1589 /* search for a free space from the first_free_index to AIRPDCAP_STA_INFOS_NR (to avoid free blocks in */
1591 for (last_free
=ctx
->first_free_index
; last_free
<AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR
; last_free
++)
1592 if (!ctx
->sa
[last_free
].used
)
1595 if (last_free
>=AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR
) {
1596 /* there is no empty space available. FAILURE */
1600 /* store first free space index */
1601 ctx
->first_free_index
=last_free
;
1605 ctx
->index
=ctx
->first_free_index
;
1607 /* reset the info structure */
1608 memset(ctx
->sa
+ctx
->index
, 0, sizeof(AIRPDCAP_SEC_ASSOCIATION
));
1610 ctx
->sa
[ctx
->index
].used
=1;
1612 /* set the info structure */
1613 memcpy(&(ctx
->sa
[ctx
->index
].saId
), id
, sizeof(AIRPDCAP_SEC_ASSOCIATION_ID
));
1615 /* increment by 1 the first_free_index (heuristic) */
1616 ctx
->first_free_index
++;
1618 /* set the sa_index if the added index is greater the the sa_index */
1619 if (ctx
->index
> ctx
->sa_index
)
1620 ctx
->sa_index
=ctx
->index
;
1626 * AirPDcapGetBssidAddress() and AirPDcapGetBssidAddress() are used for
1627 * key caching. In each case, it's more important to return a value than
1628 * to return a _correct_ value, so we fudge addresses in some cases, e.g.
1629 * the BSSID in bridged connections.
1630 * FromDS ToDS Sta BSSID
1637 static const UCHAR
*
1638 AirPDcapGetStaAddress(
1639 const AIRPDCAP_MAC_FRAME_ADDR4
*frame
)
1641 switch(AIRPDCAP_DS_BITS(frame
->fc
[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
1644 return frame
->addr2
;
1646 return frame
->addr1
;
1648 if (memcmp(frame
->addr1
, frame
->addr2
, AIRPDCAP_MAC_LEN
) < 0)
1649 return frame
->addr1
;
1651 return frame
->addr2
;
1658 static const UCHAR
*
1659 AirPDcapGetBssidAddress(
1660 const AIRPDCAP_MAC_FRAME_ADDR4
*frame
)
1662 switch(AIRPDCAP_DS_BITS(frame
->fc
[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
1664 return frame
->addr3
;
1666 return frame
->addr1
;
1668 return frame
->addr2
;
1670 if (memcmp(frame
->addr1
, frame
->addr2
, AIRPDCAP_MAC_LEN
) > 0)
1671 return frame
->addr1
;
1673 return frame
->addr2
;
1680 /* Function used to derive the PTK. Refer to IEEE 802.11I-2004, pag. 74 */
1683 AIRPDCAP_SEC_ASSOCIATION
*sa
,
1684 const UCHAR pmk
[32],
1685 const UCHAR snonce
[32],
1686 const INT x
, /* for TKIP 512, for CCMP 384 */
1691 INT offset
=sizeof("Pairwise key expansion");
1695 memcpy(R
, "Pairwise key expansion", offset
);
1697 /* Min(AA, SPA) || Max(AA, SPA) */
1698 if (memcmp(sa
->saId
.sta
, sa
->saId
.bssid
, AIRPDCAP_MAC_LEN
) < 0)
1700 memcpy(R
+ offset
, sa
->saId
.sta
, AIRPDCAP_MAC_LEN
);
1701 memcpy(R
+ offset
+AIRPDCAP_MAC_LEN
, sa
->saId
.bssid
, AIRPDCAP_MAC_LEN
);
1705 memcpy(R
+ offset
, sa
->saId
.bssid
, AIRPDCAP_MAC_LEN
);
1706 memcpy(R
+ offset
+AIRPDCAP_MAC_LEN
, sa
->saId
.sta
, AIRPDCAP_MAC_LEN
);
1709 offset
+=AIRPDCAP_MAC_LEN
*2;
1711 /* Min(ANonce,SNonce) || Max(ANonce,SNonce) */
1712 if( memcmp(snonce
, sa
->wpa
.nonce
, 32) < 0 )
1714 memcpy(R
+ offset
, snonce
, 32);
1715 memcpy(R
+ offset
+ 32, sa
->wpa
.nonce
, 32);
1719 memcpy(R
+ offset
, sa
->wpa
.nonce
, 32);
1720 memcpy(R
+ offset
+ 32, snonce
, 32);
1725 for(i
= 0; i
< (x
+159)/160; i
++)
1728 sha1_hmac(pmk
, 32, R
, 100, ptk
+ i
* 20);
1733 AirPDcapRsnaPwd2PskStep(
1734 const guint8
*ppBytes
,
1735 const guint ppLength
,
1737 const size_t ssidLength
,
1738 const INT iterations
,
1742 UCHAR digest
[64], digest1
[64];
1745 if (ssidLength
+4 > 36)
1746 return AIRPDCAP_RET_UNSUCCESS
;
1748 memset(digest
, 0, 64);
1749 memset(digest1
, 0, 64);
1751 /* U1 = PRF(P, S || INT(i)) */
1752 memcpy(digest
, ssid
, ssidLength
);
1753 digest
[ssidLength
] = (UCHAR
)((count
>>24) & 0xff);
1754 digest
[ssidLength
+1] = (UCHAR
)((count
>>16) & 0xff);
1755 digest
[ssidLength
+2] = (UCHAR
)((count
>>8) & 0xff);
1756 digest
[ssidLength
+3] = (UCHAR
)(count
& 0xff);
1757 sha1_hmac(ppBytes
, ppLength
, digest
, (guint32
) ssidLength
+4, digest1
);
1760 memcpy(output
, digest1
, AIRPDCAP_SHA_DIGEST_LEN
);
1761 for (i
= 1; i
< iterations
; i
++) {
1762 /* Un = PRF(P, Un-1) */
1763 sha1_hmac(ppBytes
, ppLength
, digest1
, AIRPDCAP_SHA_DIGEST_LEN
, digest
);
1765 memcpy(digest1
, digest
, AIRPDCAP_SHA_DIGEST_LEN
);
1766 /* output = output xor Un */
1767 for (j
= 0; j
< AIRPDCAP_SHA_DIGEST_LEN
; j
++) {
1768 output
[j
] ^= digest
[j
];
1772 return AIRPDCAP_RET_SUCCESS
;
1776 AirPDcapRsnaPwd2Psk(
1777 const CHAR
*passphrase
,
1779 const size_t ssidLength
,
1782 UCHAR m_output
[AIRPDCAP_WPA_PSK_LEN
];
1783 GByteArray
*pp_ba
= g_byte_array_new();
1785 memset(m_output
, 0, AIRPDCAP_WPA_PSK_LEN
);
1787 if (!uri_str_to_bytes(passphrase
, pp_ba
)) {
1788 g_byte_array_free(pp_ba
, TRUE
);
1792 AirPDcapRsnaPwd2PskStep(pp_ba
->data
, pp_ba
->len
, ssid
, ssidLength
, 4096, 1, m_output
);
1793 AirPDcapRsnaPwd2PskStep(pp_ba
->data
, pp_ba
->len
, ssid
, ssidLength
, 4096, 2, &m_output
[AIRPDCAP_SHA_DIGEST_LEN
]);
1795 memcpy(output
, m_output
, AIRPDCAP_WPA_PSK_LEN
);
1796 g_byte_array_free(pp_ba
, TRUE
);
1802 * Returns the decryption_key_t struct given a string describing the key.
1803 * Returns NULL if the input_string cannot be parsed.
1806 parse_key_string(gchar
* input_string
, guint8 key_type
)
1811 GString
*key_string
= NULL
;
1812 GByteArray
*ssid_ba
= NULL
, *key_ba
;
1817 decryption_key_t
*dk
;
1819 if(input_string
== NULL
)
1823 * Parse the input_string. WEP and WPA will be just a string
1824 * of hexadecimal characters (if key is wrong, null will be
1826 * WPA-PWD should be in the form
1827 * <key data>[:<ssid>]
1832 case AIRPDCAP_KEY_TYPE_WEP
:
1833 case AIRPDCAP_KEY_TYPE_WEP_40
:
1834 case AIRPDCAP_KEY_TYPE_WEP_104
:
1836 key_ba
= g_byte_array_new();
1837 res
= hex_str_to_bytes(input_string
, key_ba
, FALSE
);
1839 if (res
&& key_ba
->len
> 0) {
1840 /* Key is correct! It was probably an 'old style' WEP key */
1841 /* Create the decryption_key_t structure, fill it and return it*/
1842 dk
= (decryption_key_t
*)g_malloc(sizeof(decryption_key_t
));
1844 dk
->type
= AIRPDCAP_KEY_TYPE_WEP
;
1845 /* XXX - The current key handling code in the GUI requires
1846 * no separators and lower case */
1847 dk
->key
= g_string_new(bytes_to_str(key_ba
->data
, key_ba
->len
));
1848 g_string_ascii_down(dk
->key
);
1849 dk
->bits
= key_ba
->len
* 8;
1852 g_byte_array_free(key_ba
, TRUE
);
1856 /* Key doesn't work */
1857 g_byte_array_free(key_ba
, TRUE
);
1860 case AIRPDCAP_KEY_TYPE_WPA_PWD
:
1862 tokens
= g_strsplit(input_string
,":",0);
1864 /* Tokens is a null termiated array of strings ... */
1865 while(tokens
[n
] != NULL
)
1870 /* Free the array of strings */
1876 * The first token is the key
1878 key
= g_strdup(tokens
[0]);
1881 /* Maybe there is a second token (an ssid, if everything else is ok) */
1884 ssid
= g_strdup(tokens
[1]);
1887 /* Create a new string */
1888 key_string
= g_string_new(key
);
1891 /* Two (or more) tokens mean that the user entered a WPA-PWD key ... */
1892 if( ((key_string
->len
) > WPA_KEY_MAX_CHAR_SIZE
) || ((key_string
->len
) < WPA_KEY_MIN_CHAR_SIZE
))
1894 g_string_free(key_string
, TRUE
);
1899 /* Free the array of strings */
1904 if(ssid
!= NULL
) /* more than two tokens found, means that the user specified the ssid */
1906 ssid_ba
= g_byte_array_new();
1907 if (! uri_str_to_bytes(ssid
, ssid_ba
)) {
1908 g_string_free(key_string
, TRUE
);
1909 g_byte_array_free(ssid_ba
, TRUE
);
1912 /* Free the array of strings */
1917 if(ssid_ba
->len
> WPA_SSID_MAX_CHAR_SIZE
)
1919 g_string_free(key_string
, TRUE
);
1920 g_byte_array_free(ssid_ba
, TRUE
);
1925 /* Free the array of strings */
1931 /* Key was correct!!! Create the new decryption_key_t ... */
1932 dk
= (decryption_key_t
*)g_malloc(sizeof(decryption_key_t
));
1934 dk
->type
= AIRPDCAP_KEY_TYPE_WPA_PWD
;
1935 dk
->key
= g_string_new(key
);
1936 dk
->bits
= 256; /* This is the length of the array pf bytes that will be generated using key+ssid ...*/
1937 dk
->ssid
= byte_array_dup(ssid_ba
); /* NULL if ssid_ba is NULL */
1939 g_string_free(key_string
, TRUE
);
1940 if (ssid_ba
!= NULL
)
1941 g_byte_array_free(ssid_ba
, TRUE
);
1947 /* Free the array of strings */
1951 case AIRPDCAP_KEY_TYPE_WPA_PSK
:
1953 key_ba
= g_byte_array_new();
1954 res
= hex_str_to_bytes(input_string
, key_ba
, FALSE
);
1956 /* Two tokens means that the user should have entered a WPA-BIN key ... */
1957 if(!res
|| ((key_ba
->len
) != WPA_PSK_KEY_SIZE
))
1959 g_byte_array_free(key_ba
, TRUE
);
1961 /* No ssid has been created ... */
1965 /* Key was correct!!! Create the new decryption_key_t ... */
1966 dk
= (decryption_key_t
*)g_malloc(sizeof(decryption_key_t
));
1968 dk
->type
= AIRPDCAP_KEY_TYPE_WPA_PSK
;
1969 dk
->key
= g_string_new(input_string
);
1970 dk
->bits
= (guint
) dk
->key
->len
* 4;
1973 g_byte_array_free(key_ba
, TRUE
);
1977 /* Type not supported */
1982 * Returns a newly allocated string representing the given decryption_key_t
1983 * struct, or NULL if something is wrong...
1986 get_key_string(decryption_key_t
* dk
)
1988 gchar
* output_string
= NULL
;
1990 if(dk
== NULL
|| dk
->key
== NULL
)
1994 case AIRPDCAP_KEY_TYPE_WEP
:
1995 output_string
= g_strdup(dk
->key
->str
);
1997 case AIRPDCAP_KEY_TYPE_WPA_PWD
:
1998 if(dk
->ssid
== NULL
)
1999 output_string
= g_strdup(dk
->key
->str
);
2001 output_string
= g_strdup_printf("%s:%s",
2002 dk
->key
->str
, format_uri(dk
->ssid
, ":"));
2004 case AIRPDCAP_KEY_TYPE_WPA_PMK
:
2005 output_string
= g_strdup(dk
->key
->str
);
2011 return output_string
;
2018 /****************************************************************************/
2026 * indent-tabs-mode: nil
2029 * ex: set shiftwidth=4 tabstop=8 expandtab:
2030 * :indentSize=4:tabSize=8:noTabs=true: