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>
49 #include "airpdcap_system.h"
50 #include "airpdcap_int.h"
52 #include "crypt-sha1.h"
53 #include "crypt-md5.h"
55 #include "airpdcap_debug.h"
57 #include "wep-wpadefs.h"
59 #ifdef NEED_G_ASCII_STRCASECMP_H
60 #include "../g_ascii_strcasecmp.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_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 /****************************************************************************/
104 /****************************************************************************/
105 /* Macro definitions */
107 extern const UINT32 crc32_table[256];
108 #define CRC(crc, ch) (crc = (crc >> 8) ^ crc32_table[(crc ^ (ch)) & 0xff])
110 #define AIRPDCAP_GET_TK(ptk) (ptk + 32)
112 /****************************************************************************/
114 /****************************************************************************/
115 /* Type definitions */
117 /* Internal function prototype declarations */
124 * It is a step of the PBKDF2 (specifically the PKCS #5 v2.0) defined in
125 * the RFC 2898 to derive a key (used as PMK in WPA)
126 * @param password [IN] pointer to a password (sequence of between 8 and
127 * 63 ASCII encoded characters)
128 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
130 * @param iterations [IN] times to hash the password (4096 for WPA)
131 * @param count [IN] ???
132 * @param output [OUT] pointer to a preallocated buffer of
133 * AIRPDCAP_SHA_DIGEST_LEN characters that will contain a part of the key
135 static INT AirPDcapRsnaPwd2PskStep(
136 const guint8 *ppbytes,
137 const guint passLength,
139 const size_t ssidLength,
140 const INT iterations,
146 * It calculates the passphrase-to-PSK mapping reccomanded for use with
147 * RSNAs. This implementation uses the PBKDF2 method defined in the RFC
149 * @param password [IN] pointer to a password (sequence of between 8 and
150 * 63 ASCII encoded characters)
151 * @param ssid [IN] pointer to the SSID string encoded in max 32 ASCII
153 * @param output [OUT] calculated PSK (to use as PMK in WPA)
155 * Described in 802.11i-2004, page 165
157 static INT AirPDcapRsnaPwd2Psk(
158 const CHAR *passphrase,
160 const size_t ssidLength,
164 static INT AirPDcapRsnaMng(
166 guint mac_header_len,
168 PAIRPDCAP_KEY_ITEM key,
169 AIRPDCAP_SEC_ASSOCIATION *sa,
173 static INT AirPDcapWepMng(
174 PAIRPDCAP_CONTEXT ctx,
176 guint mac_header_len,
178 PAIRPDCAP_KEY_ITEM key,
179 AIRPDCAP_SEC_ASSOCIATION *sa,
183 static INT AirPDcapRsna4WHandshake(
184 PAIRPDCAP_CONTEXT ctx,
186 AIRPDCAP_SEC_ASSOCIATION *sa,
187 PAIRPDCAP_KEY_ITEM key,
191 * It checks whether the specified key is corrected or not.
193 * For a standard WEP key the length will be changed to the standard
194 * length, and the type changed in a generic WEP key.
195 * @param key [IN] pointer to the key to validate
197 * - TRUE: the key contains valid fields and values
198 * - FALSE: the key has some invalid field or value
200 static INT AirPDcapValidateKey(
201 PAIRPDCAP_KEY_ITEM key)
204 static INT AirPDcapRsnaMicCheck(
207 UCHAR KCK[AIRPDCAP_WPA_KCK_LEN],
212 * @param ctx [IN] pointer to the current context
213 * @param id [IN] id of the association (composed by BSSID and MAC of
216 * - index of the Security Association structure if found
217 * - -1, if the specified addresses pair BSSID-STA MAC has not been found
219 static INT AirPDcapGetSa(
220 PAIRPDCAP_CONTEXT ctx,
221 AIRPDCAP_SEC_ASSOCIATION_ID *id)
224 static INT AirPDcapStoreSa(
225 PAIRPDCAP_CONTEXT ctx,
226 AIRPDCAP_SEC_ASSOCIATION_ID *id)
229 static const UCHAR * AirPDcapGetStaAddress(
230 const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
233 static const UCHAR * AirPDcapGetBssidAddress(
234 const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
237 static void AirPDcapRsnaPrfX(
238 AIRPDCAP_SEC_ASSOCIATION *sa,
240 const UCHAR snonce[32],
241 const INT x, /* for TKIP 512, for CCMP 384 */
249 /****************************************************************************/
251 /****************************************************************************/
252 /* Exported function definitions */
258 INT AirPDcapPacketProcess(
259 PAIRPDCAP_CONTEXT ctx,
261 const guint mac_header_len,
265 PAIRPDCAP_KEY_ITEM key,
266 gboolean mngHandshake,
269 const UCHAR *address;
270 AIRPDCAP_SEC_ASSOCIATION_ID id;
272 PAIRPDCAP_SEC_ASSOCIATION sa;
275 const guint8 dot1x_header[] = {
276 0xAA, /* DSAP=SNAP */
277 0xAA, /* SSAP=SNAP */
278 0x03, /* Control field=Unnumbered frame */
279 0x00, 0x00, 0x00, /* Org. code=encaps. Ethernet */
280 0x88, 0x8E /* Type: 802.1X authentication */
287 AIRPDCAP_DEBUG_TRACE_START("AirPDcapPacketProcess");
290 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
291 AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess");
292 return AIRPDCAP_RET_UNSUCCESS;
294 if (data==NULL || tot_len==0) {
295 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "NULL data or length=0", AIRPDCAP_DEBUG_LEVEL_5);
296 AIRPDCAP_DEBUG_TRACE_END("AirPDcapPacketProcess");
297 return AIRPDCAP_RET_UNSUCCESS;
300 /* check if the packet is of data type */
301 if (AIRPDCAP_TYPE(data[0])!=AIRPDCAP_TYPE_DATA) {
302 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "not data packet", AIRPDCAP_DEBUG_LEVEL_5);
303 return AIRPDCAP_RET_NO_DATA;
306 /* check correct packet size, to avoid wrong elaboration of encryption algorithms */
307 if (tot_len < (UINT)(mac_header_len+AIRPDCAP_CRYPTED_DATA_MINLEN)) {
308 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "minimum length violated", AIRPDCAP_DEBUG_LEVEL_5);
309 return AIRPDCAP_RET_WRONG_DATA_SIZE;
313 if ( (address=AirPDcapGetBssidAddress((const AIRPDCAP_MAC_FRAME_ADDR4 *)(data))) != NULL) {
314 memcpy(id.bssid, address, AIRPDCAP_MAC_LEN);
316 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]);
318 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3);
320 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "BSSID not found", AIRPDCAP_DEBUG_LEVEL_5);
321 return AIRPDCAP_RET_REQ_DATA;
324 /* get STA address */
325 if ( (address=AirPDcapGetStaAddress((const AIRPDCAP_MAC_FRAME_ADDR4 *)(data))) != NULL) {
326 memcpy(id.sta, address, AIRPDCAP_MAC_LEN);
328 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]);
330 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", msgbuf, AIRPDCAP_DEBUG_LEVEL_3);
332 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "SA not found", AIRPDCAP_DEBUG_LEVEL_5);
333 return AIRPDCAP_RET_REQ_DATA;
336 /* search for a cached Security Association for current BSSID and station MAC */
337 if ((index=AirPDcapGetSa(ctx, &id))==-1) {
338 /* create a new Security Association */
339 if ((index=AirPDcapStoreSa(ctx, &id))==-1) {
340 return AIRPDCAP_RET_UNSUCCESS;
344 /* get the Security Association structure */
347 /* cache offset in the packet data (to scan encryption data) */
348 offset = mac_header_len;
350 /* check if data is encrypted (use the WEP bit in the Frame Control field) */
351 if (AIRPDCAP_WEP(data[1])==0)
354 /* data is sent in cleartext, check if is an authentication message or end the process */
355 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Unencrypted data", AIRPDCAP_DEBUG_LEVEL_3);
357 /* check if the packet as an LLC header and the packet is 802.1X authentication (IEEE 802.1X-2004, pg. 24) */
358 if (memcmp(data+offset, dot1x_header, 8) == 0) {
359 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Authentication: EAPOL packet", AIRPDCAP_DEBUG_LEVEL_3);
361 /* skip LLC header */
364 /* check the version of the EAPOL protocol used (IEEE 802.1X-2004, pg. 24) */
365 /* TODO EAPOL protocol version to check? */
366 /*if (data[offset]!=2) {
367 AIRPDCAP_DEBUG_PRINT_LINE("EAPOL protocol version not recognized", AIRPDCAP_DEBUG_LEVEL_5);
368 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
371 /* check if the packet is a EAPOL-Key (0x03) (IEEE 802.1X-2004, pg. 25) */
372 if (data[offset+1]!=3) {
373 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not EAPOL-Key", AIRPDCAP_DEBUG_LEVEL_5);
374 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
377 /* get and check the body length (IEEE 802.1X-2004, pg. 25) */
378 bodyLength=pntohs(data+offset+2);
379 if ((tot_len-offset-4) < bodyLength) {
380 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "EAPOL body too short", AIRPDCAP_DEBUG_LEVEL_5);
381 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
384 /* skip EAPOL MPDU and go to the first byte of the body */
387 /* check if the key descriptor type is valid (IEEE 802.1X-2004, pg. 27) */
388 if (/*data[offset]!=0x1 &&*/ /* RC4 Key Descriptor Type (deprecated) */
389 data[offset]!=0x2 && /* IEEE 802.11 Key Descriptor Type */
390 data[offset]!=0xFE) /* TODO what's this value??? */
392 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Not valid key descriptor type", AIRPDCAP_DEBUG_LEVEL_5);
393 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
396 /* start with descriptor body */
399 /* manage the 4-way handshake to define the key */
400 return AirPDcapRsna4WHandshake(ctx, data, sa, key, offset);
402 /* cleartext message, not authentication */
403 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "No authentication data", AIRPDCAP_DEBUG_LEVEL_5);
404 return AIRPDCAP_RET_NO_DATA_ENCRYPTED;
410 if (decrypt_data==NULL)
411 return AIRPDCAP_RET_UNSUCCESS;
413 /* create new header and data to modify */
414 *decrypt_len = tot_len;
415 memcpy(decrypt_data, data, *decrypt_len);
418 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "Encrypted data", AIRPDCAP_DEBUG_LEVEL_3);
420 /* check the Extension IV to distinguish between WEP encryption and WPA encryption */
421 /* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */
422 /* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */
423 /* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */
424 if (AIRPDCAP_EXTIV(data[offset+3])==0) {
425 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "WEP encryption", AIRPDCAP_DEBUG_LEVEL_3);
426 return AirPDcapWepMng(ctx, decrypt_data, mac_header_len, decrypt_len, key, sa, offset);
428 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapPacketProcess", "TKIP or CCMP encryption", AIRPDCAP_DEBUG_LEVEL_3);
429 return AirPDcapRsnaMng(decrypt_data, mac_header_len, decrypt_len, key, sa, offset);
434 return AIRPDCAP_RET_UNSUCCESS;
438 PAIRPDCAP_CONTEXT ctx,
439 AIRPDCAP_KEY_ITEM keys[],
440 const size_t keys_nr)
444 AIRPDCAP_DEBUG_TRACE_START("AirPDcapSetKeys");
446 if (ctx==NULL || keys==NULL) {
447 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "NULL context or NULL keys array", AIRPDCAP_DEBUG_LEVEL_3);
448 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
452 if (keys_nr>AIRPDCAP_MAX_KEYS_NR) {
453 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Keys number greater than maximum", AIRPDCAP_DEBUG_LEVEL_3);
454 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
458 /* clean key and SA collections before setting new ones */
459 AirPDcapInitContext(ctx);
461 /* check and insert keys */
462 for (i=0, success=0; i<(INT)keys_nr; i++) {
463 if (AirPDcapValidateKey(keys+i)==TRUE) {
464 if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD) {
465 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PWD key", AIRPDCAP_DEBUG_LEVEL_4);
466 AirPDcapRsnaPwd2Psk(keys[i].UserPwd.Passphrase, keys[i].UserPwd.Ssid, keys[i].UserPwd.SsidLen, keys[i].KeyData.Wpa.Psk);
469 else if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK) {
470 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WPA-PMK key", AIRPDCAP_DEBUG_LEVEL_4);
471 } else if (keys[i].KeyType==AIRPDCAP_KEY_TYPE_WEP) {
472 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a WEP key", AIRPDCAP_DEBUG_LEVEL_4);
474 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapSetKeys", "Set a key", AIRPDCAP_DEBUG_LEVEL_4);
477 memcpy(&ctx->keys[success], &keys[i], sizeof(keys[i]));
482 ctx->keys_nr=success;
484 AIRPDCAP_DEBUG_TRACE_END("AirPDcapSetKeys");
490 const PAIRPDCAP_CONTEXT ctx,
491 AIRPDCAP_KEY_ITEM keys[],
492 const size_t keys_nr)
496 AIRPDCAP_DEBUG_TRACE_START("AirPDcapGetKeys");
499 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
500 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
502 } else if (keys==NULL) {
503 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "NULL keys array", AIRPDCAP_DEBUG_LEVEL_5);
504 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
505 return (INT)ctx->keys_nr;
507 for (i=0, j=0; i<ctx->keys_nr && i<keys_nr && i<AIRPDCAP_MAX_KEYS_NR; i++) {
508 memcpy(&keys[j], &ctx->keys[i], sizeof(keys[j]));
510 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapGetKeys", "Got a key", AIRPDCAP_DEBUG_LEVEL_5);
513 AIRPDCAP_DEBUG_TRACE_END("AirPDcapGetKeys");
519 * XXX - This won't be reliable if a packet containing SSID "B" shows
520 * up in the middle of a 4-way handshake for SSID "A".
521 * We should probably use a small array or hash table to keep multiple
524 INT AirPDcapSetLastSSID(
525 PAIRPDCAP_CONTEXT ctx,
529 if (!ctx || !pkt_ssid || pkt_ssid_len < 1 || pkt_ssid_len > WPA_SSID_MAX_SIZE)
530 return AIRPDCAP_RET_UNSUCCESS;
532 memcpy(ctx->pkt_ssid, pkt_ssid, pkt_ssid_len);
533 ctx->pkt_ssid_len = pkt_ssid_len;
535 return AIRPDCAP_RET_SUCCESS;
538 INT AirPDcapInitContext(
539 PAIRPDCAP_CONTEXT ctx)
541 AIRPDCAP_DEBUG_TRACE_START("AirPDcapInitContext");
544 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
545 AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext");
546 return AIRPDCAP_RET_UNSUCCESS;
549 memset(ctx->keys, 0, sizeof(AIRPDCAP_KEY_ITEM) * AIRPDCAP_MAX_KEYS_NR);
551 memset(ctx->sa, 0, AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR * sizeof(AIRPDCAP_SEC_ASSOCIATION));
553 ctx->first_free_index=0;
556 ctx->pkt_ssid_len = 0;
558 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapInitContext", "Context initialized!", AIRPDCAP_DEBUG_LEVEL_5);
559 AIRPDCAP_DEBUG_TRACE_END("AirPDcapInitContext");
560 return AIRPDCAP_RET_SUCCESS;
563 INT AirPDcapDestroyContext(
564 PAIRPDCAP_CONTEXT ctx)
566 AIRPDCAP_DEBUG_TRACE_START("AirPDcapDestroyContext");
569 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "NULL context", AIRPDCAP_DEBUG_LEVEL_5);
570 AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext");
571 return AIRPDCAP_RET_UNSUCCESS;
574 ctx->first_free_index=0;
578 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapDestroyContext", "Context destroyed!", AIRPDCAP_DEBUG_LEVEL_5);
579 AIRPDCAP_DEBUG_TRACE_END("AirPDcapDestroyContext");
580 return AIRPDCAP_RET_SUCCESS;
587 /****************************************************************************/
589 /****************************************************************************/
590 /* Internal function definitions */
599 guint mac_header_len,
601 PAIRPDCAP_KEY_ITEM key,
602 AIRPDCAP_SEC_ASSOCIATION *sa,
608 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "No key associated", AIRPDCAP_DEBUG_LEVEL_3);
609 return AIRPDCAP_RET_REQ_DATA;
611 if (sa->validKey==FALSE) {
612 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "Key not yet valid", AIRPDCAP_DEBUG_LEVEL_3);
613 return AIRPDCAP_RET_UNSUCCESS;
615 if (sa->wpa.key_ver==1) {
616 /* CCMP -> HMAC-MD5 is the EAPOL-Key MIC, RC4 is the EAPOL-Key encryption algorithm */
617 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP", AIRPDCAP_DEBUG_LEVEL_3);
619 ret_value=AirPDcapTkipDecrypt(decrypt_data+offset, *decrypt_len-offset, decrypt_data+AIRPDCAP_TA_OFFSET, AIRPDCAP_GET_TK(sa->wpa.ptk));
623 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "TKIP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
624 /* remove MIC (8bytes) and ICV (4bytes) from the end of packet */
627 /* AES-CCMP -> HMAC-SHA1-128 is the EAPOL-Key MIC, AES wep_key wrap is the EAPOL-Key encryption algorithm */
628 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP", AIRPDCAP_DEBUG_LEVEL_3);
630 ret_value=AirPDcapCcmpDecrypt(decrypt_data, mac_header_len, (INT)*decrypt_len, AIRPDCAP_GET_TK(sa->wpa.ptk));
634 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsnaMng", "CCMP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
635 /* remove MIC (8bytes) from the end of packet */
639 /* remove protection bit */
640 decrypt_data[1]&=0xBF;
642 /* remove TKIP/CCMP header */
643 offset = mac_header_len;
645 memcpy(decrypt_data+offset, decrypt_data+offset+8, *decrypt_len-offset);
648 memcpy(key, sa->key, sizeof(AIRPDCAP_KEY_ITEM));
650 if (sa->wpa.key_ver==AIRPDCAP_WPA_KEY_VER_CCMP)
651 key->KeyType=AIRPDCAP_KEY_TYPE_TKIP;
652 else if (sa->wpa.key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP)
653 key->KeyType=AIRPDCAP_KEY_TYPE_CCMP;
656 return AIRPDCAP_RET_SUCCESS;
661 PAIRPDCAP_CONTEXT ctx,
663 guint mac_header_len,
665 PAIRPDCAP_KEY_ITEM key,
666 AIRPDCAP_SEC_ASSOCIATION *sa,
669 UCHAR wep_key[AIRPDCAP_WEP_KEY_MAXLEN+AIRPDCAP_WEP_IVLEN];
673 AIRPDCAP_KEY_ITEM *tmp_key;
674 UINT8 useCache=FALSE;
675 UCHAR *try_data = ep_alloc(*decrypt_len);
680 for (key_index=0; key_index<(INT)ctx->keys_nr; key_index++) {
681 /* use the cached one, or try all keys */
683 tmp_key=&ctx->keys[key_index];
685 if (sa->key!=NULL && sa->key->KeyType==AIRPDCAP_KEY_TYPE_WEP) {
686 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try cached WEP key...", AIRPDCAP_DEBUG_LEVEL_3);
689 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Cached key is not valid, try another WEP key...", AIRPDCAP_DEBUG_LEVEL_3);
690 tmp_key=&ctx->keys[key_index];
694 /* obviously, try only WEP keys... */
695 if (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP)
697 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "Try WEP key...", AIRPDCAP_DEBUG_LEVEL_3);
699 memset(wep_key, 0, sizeof(wep_key));
700 memcpy(try_data, decrypt_data, *decrypt_len);
702 /* 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) */
703 memcpy(wep_key, try_data+mac_header_len, AIRPDCAP_WEP_IVLEN);
704 keylen=tmp_key->KeyData.Wep.WepKeyLen;
705 memcpy(wep_key+AIRPDCAP_WEP_IVLEN, tmp_key->KeyData.Wep.WepKey, keylen);
707 ret_value=AirPDcapWepDecrypt(wep_key,
708 keylen+AIRPDCAP_WEP_IVLEN,
709 try_data + (mac_header_len+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN),
710 *decrypt_len-(mac_header_len+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN+AIRPDCAP_CRC_LEN));
712 if (ret_value == AIRPDCAP_RET_SUCCESS)
713 memcpy(decrypt_data, try_data, *decrypt_len);
716 if (!ret_value && tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WEP) {
717 /* the tried key is the correct one, cached in the Security Association */
722 memcpy(key, &sa->key, sizeof(AIRPDCAP_KEY_ITEM));
723 key->KeyType=AIRPDCAP_KEY_TYPE_WEP;
728 /* the cached key was not valid, try other keys */
730 if (useCache==TRUE) {
740 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapWepMng", "WEP DECRYPTED!!!", AIRPDCAP_DEBUG_LEVEL_3);
742 /* remove ICV (4bytes) from the end of packet */
745 /* remove protection bit */
746 decrypt_data[1]&=0xBF;
748 /* remove IC header */
749 offset = mac_header_len;
751 memcpy(decrypt_data+offset, decrypt_data+offset+AIRPDCAP_WEP_IVLEN+AIRPDCAP_WEP_KIDLEN, *decrypt_len-offset);
753 return AIRPDCAP_RET_SUCCESS;
756 /* Refer to IEEE 802.11i-2004, 8.5.3, pag. 85 */
758 AirPDcapRsna4WHandshake(
759 PAIRPDCAP_CONTEXT ctx,
761 AIRPDCAP_SEC_ASSOCIATION *sa,
762 PAIRPDCAP_KEY_ITEM key,
765 AIRPDCAP_KEY_ITEM *tmp_key, pkt_key;
768 UCHAR useCache=FALSE;
769 UCHAR eapol[AIRPDCAP_EAPOL_MAX_LEN];
775 /* a 4-way handshake packet use a Pairwise key type (IEEE 802.11i-2004, pg. 79) */
776 if (AIRPDCAP_EAP_KEY(data[offset+1])!=1) {
777 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Group/STAKey message (not used)", AIRPDCAP_DEBUG_LEVEL_5);
778 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
781 /* TODO timeouts? reauthentication? */
783 /* TODO consider key-index */
785 /* TODO considera Deauthentications */
787 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake...", AIRPDCAP_DEBUG_LEVEL_5);
789 /* manage 4-way handshake packets; this step completes the 802.1X authentication process (IEEE 802.11i-2004, pag. 85) */
791 /* message 1: Authenticator->Supplicant (Sec=0, Mic=0, Ack=1, Inst=0, Key=1(pairwise), KeyRSC=0, Nonce=ANonce, MIC=0) */
792 if (AIRPDCAP_EAP_INST(data[offset+1])==0 &&
793 AIRPDCAP_EAP_ACK(data[offset+1])==1 &&
794 AIRPDCAP_EAP_MIC(data[offset])==0)
796 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 1", AIRPDCAP_DEBUG_LEVEL_3);
798 /* On reception of Message 1, the Supplicant determines whether the Key Replay Counter field value has been */
799 /* used before with the current PMKSA. If the Key Replay Counter field value is less than or equal to the current */
800 /* local value, the Supplicant discards the message. */
801 /* -> not checked, the Authenticator will be send another Message 1 (hopefully!) */
803 /* save ANonce (from authenticator) to derive the PTK with the SNonce (from the 2 message) */
804 memcpy(sa->wpa.nonce, data+offset+12, 32);
806 /* get the Key Descriptor Version (to select algorithm used in decryption -CCMP or TKIP-) */
807 sa->wpa.key_ver=AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1]);
811 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
814 /* 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)) */
815 if (AIRPDCAP_EAP_INST(data[offset+1])==0 &&
816 AIRPDCAP_EAP_ACK(data[offset+1])==0 &&
817 AIRPDCAP_EAP_MIC(data[offset])==1)
819 if (AIRPDCAP_EAP_SEC(data[offset])==0) {
821 /* PATCH: some implementations set secure bit to 0 also in the 4th message */
822 /* to recognize which message is this check if wep_key data length is 0 */
823 /* in the 4th message */
824 if (data[offset+92]!=0 || data[offset+93]!=0) {
826 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 2", AIRPDCAP_DEBUG_LEVEL_3);
828 /* On reception of Message 2, the Authenticator checks that the key replay counter corresponds to the */
829 /* outstanding Message 1. If not, it silently discards the message. */
830 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, */
831 /* the Authenticator silently discards Message 2. */
832 /* -> not checked; the Supplicant will send another message 2 (hopefully!) */
834 /* now you can derive the PTK */
835 for (key_index=0; key_index<(INT)ctx->keys_nr || useCache; key_index++) {
836 /* use the cached one, or try all keys */
838 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try WPA key...", AIRPDCAP_DEBUG_LEVEL_3);
839 tmp_key=&ctx->keys[key_index];
841 /* there is a cached key in the security association, if it's a WPA key try it... */
843 (sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD ||
844 sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK ||
845 sa->key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK)) {
846 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Try cached WPA key...", AIRPDCAP_DEBUG_LEVEL_3);
849 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "Cached key is of a wrong type, try WPA key...", AIRPDCAP_DEBUG_LEVEL_3);
850 tmp_key=&ctx->keys[key_index];
854 /* obviously, try only WPA keys... */
855 if (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD ||
856 tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK ||
857 tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK)
859 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) {
860 /* We have a "wildcard" SSID. Use the one from the packet. */
861 memcpy(&pkt_key, tmp_key, sizeof(pkt_key));
862 memcpy(&pkt_key.UserPwd.Ssid, ctx->pkt_ssid, ctx->pkt_ssid_len);
863 pkt_key.UserPwd.SsidLen = ctx->pkt_ssid_len;
864 AirPDcapRsnaPwd2Psk(pkt_key.UserPwd.Passphrase, pkt_key.UserPwd.Ssid,
865 pkt_key.UserPwd.SsidLen, pkt_key.KeyData.Wpa.Psk);
869 /* derive the PTK from the BSSID, STA MAC, PMK, SNonce, ANonce */
870 AirPDcapRsnaPrfX(sa, /* authenticator nonce, bssid, station mac */
871 tmp_key->KeyData.Wpa.Pmk, /* PMK */
872 data+offset+12, /* supplicant nonce */
876 /* verify the MIC (compare the MIC in the packet included in this message with a MIC calculated with the PTK) */
877 eapol_len=pntohs(data+offset-3)+4;
878 memcpy(eapol, &data[offset-5], (eapol_len<AIRPDCAP_EAPOL_MAX_LEN?eapol_len:AIRPDCAP_EAPOL_MAX_LEN));
879 ret_value=AirPDcapRsnaMicCheck(eapol, /* eapol frame (header also) */
880 eapol_len, /* eapol frame length */
881 sa->wpa.ptk, /* Key Confirmation Key */
882 AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])); /* EAPOL-Key description version */
884 /* If the MIC is valid, the Authenticator checks that the RSN information element bit-wise matches */
885 /* that from the (Re)Association Request message. */
886 /* i) TODO If these are not exactly the same, the Authenticator uses MLME-DEAUTHENTICATE.request */
887 /* primitive to terminate the association. */
888 /* ii) If they do match bit-wise, the Authenticator constructs Message 3. */
892 (tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PWD ||
893 tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PSK ||
894 tmp_key->KeyType==AIRPDCAP_KEY_TYPE_WPA_PMK))
896 /* the temporary key is the correct one, cached in the Security Association */
901 memcpy(key, &tmp_key, sizeof(AIRPDCAP_KEY_ITEM));
902 if (AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])==AIRPDCAP_WPA_KEY_VER_CCMP)
903 key->KeyType=AIRPDCAP_KEY_TYPE_TKIP;
904 else if (AIRPDCAP_EAP_KEY_DESCR_VER(data[offset+1])==AIRPDCAP_WPA_KEY_VER_AES_CCMP)
905 key->KeyType=AIRPDCAP_KEY_TYPE_CCMP;
910 /* the cached key was not valid, try other keys */
912 if (useCache==TRUE) {
920 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "handshake step failed", AIRPDCAP_DEBUG_LEVEL_3);
921 return AIRPDCAP_RET_NO_VALID_HANDSHAKE;
926 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
930 /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
932 /* TODO check MIC and Replay Counter */
933 /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */
934 /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */
935 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */
936 /* Authenticator silently discards Message 4. */
938 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4 (patched)", AIRPDCAP_DEBUG_LEVEL_3);
944 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
951 /* TODO "Note that when the 4-Way Handshake is first used Message 4 is sent in the clear." */
953 /* TODO check MIC and Replay Counter */
954 /* On reception of Message 4, the Authenticator verifies that the Key Replay Counter field value is one */
955 /* that it used on this 4-Way Handshake; if it is not, it silently discards the message. */
956 /* If the calculated MIC does not match the MIC that the Supplicant included in the EAPOL-Key frame, the */
957 /* Authenticator silently discards Message 4. */
959 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 4", AIRPDCAP_DEBUG_LEVEL_3);
965 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
969 /* message 3: Authenticator->Supplicant (Sec=1, Mic=1, Ack=1, Inst=0/1, Key=1(pairwise), KeyRSC=???, Nonce=ANonce, MIC=1) */
970 if (AIRPDCAP_EAP_ACK(data[offset+1])==1 &&
971 AIRPDCAP_EAP_MIC(data[offset])==1)
973 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapRsna4WHandshake", "4-way handshake message 3", AIRPDCAP_DEBUG_LEVEL_3);
975 /* On reception of Message 3, the Supplicant silently discards the message if the Key Replay Counter field */
976 /* value has already been used or if the ANonce value in Message 3 differs from the ANonce value in Message 1. */
977 /* -> not checked, the Authenticator will send another message 3 (hopefully!) */
979 /* TODO check page 88 (RNS) */
981 return AIRPDCAP_RET_SUCCESS_HANDSHAKE;
984 return AIRPDCAP_RET_UNSUCCESS;
988 AirPDcapRsnaMicCheck(
991 UCHAR KCK[AIRPDCAP_WPA_KCK_LEN],
994 UCHAR mic[AIRPDCAP_WPA_MICKEY_LEN];
995 UCHAR c_mic[20]; /* MIC 16 byte, the HMAC-SHA1 use a buffer of 20 bytes */
997 /* copy the MIC from the EAPOL packet */
998 memcpy(mic, eapol+AIRPDCAP_WPA_MICKEY_OFFSET+4, AIRPDCAP_WPA_MICKEY_LEN);
1000 /* set to 0 the MIC in the EAPOL packet (to calculate the MIC) */
1001 memset(eapol+AIRPDCAP_WPA_MICKEY_OFFSET+4, 0, AIRPDCAP_WPA_MICKEY_LEN);
1003 if (key_ver==AIRPDCAP_WPA_KEY_VER_CCMP) {
1004 /* use HMAC-MD5 for the EAPOL-Key MIC */
1005 md5_hmac(eapol, eapol_len, KCK, AIRPDCAP_WPA_KCK_LEN, c_mic);
1006 } else if (key_ver==AIRPDCAP_WPA_KEY_VER_AES_CCMP) {
1007 /* use HMAC-SHA1-128 for the EAPOL-Key MIC */
1008 sha1_hmac(KCK, AIRPDCAP_WPA_KCK_LEN, eapol, eapol_len, c_mic);
1010 /* key descriptor version not recognized */
1011 return AIRPDCAP_RET_UNSUCCESS;
1013 /* compare calculated MIC with the Key MIC and return result (0 means success) */
1014 return memcmp(mic, c_mic, AIRPDCAP_WPA_MICKEY_LEN);
1018 AirPDcapValidateKey(
1019 PAIRPDCAP_KEY_ITEM key)
1023 AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey");
1026 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "NULL key", AIRPDCAP_DEBUG_LEVEL_5);
1027 AIRPDCAP_DEBUG_TRACE_START("AirPDcapValidateKey");
1031 switch (key->KeyType) {
1032 case AIRPDCAP_KEY_TYPE_WEP:
1033 /* check key size limits */
1034 len=key->KeyData.Wep.WepKeyLen;
1035 if (len<AIRPDCAP_WEP_KEY_MINLEN || len>AIRPDCAP_WEP_KEY_MAXLEN) {
1036 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WEP key: key length not accepted", AIRPDCAP_DEBUG_LEVEL_5);
1041 case AIRPDCAP_KEY_TYPE_WEP_40:
1042 /* set the standard length and use a generic WEP key type */
1043 key->KeyData.Wep.WepKeyLen=AIRPDCAP_WEP_40_KEY_LEN;
1044 key->KeyType=AIRPDCAP_KEY_TYPE_WEP;
1047 case AIRPDCAP_KEY_TYPE_WEP_104:
1048 /* set the standard length and use a generic WEP key type */
1049 key->KeyData.Wep.WepKeyLen=AIRPDCAP_WEP_104_KEY_LEN;
1050 key->KeyType=AIRPDCAP_KEY_TYPE_WEP;
1053 case AIRPDCAP_KEY_TYPE_WPA_PWD:
1054 /* check passphrase and SSID size limits */
1055 len=strlen(key->UserPwd.Passphrase);
1056 if (len<AIRPDCAP_WPA_PASSPHRASE_MIN_LEN || len>AIRPDCAP_WPA_PASSPHRASE_MAX_LEN) {
1057 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: passphrase length not accepted", AIRPDCAP_DEBUG_LEVEL_5);
1061 len=key->UserPwd.SsidLen;
1062 if (len>AIRPDCAP_WPA_SSID_MAX_LEN) {
1063 AIRPDCAP_DEBUG_PRINT_LINE("AirPDcapValidateKey", "WPA-PWD key: ssid length not accepted", AIRPDCAP_DEBUG_LEVEL_5);
1069 case AIRPDCAP_KEY_TYPE_WPA_PSK:
1072 case AIRPDCAP_KEY_TYPE_WPA_PMK:
1079 AIRPDCAP_DEBUG_TRACE_END("AirPDcapValidateKey");
1085 PAIRPDCAP_CONTEXT ctx,
1086 AIRPDCAP_SEC_ASSOCIATION_ID *id)
1090 if (ctx->sa_index!=-1) {
1091 /* at least one association was stored */
1092 /* search for the association from sa_index to 0 (most recent added) */
1093 for (index=ctx->sa_index; index>=0; index--) {
1094 if (ctx->sa[index].used) {
1095 if (memcmp(id, &(ctx->sa[index].saId), sizeof(AIRPDCAP_SEC_ASSOCIATION_ID))==0) {
1108 PAIRPDCAP_CONTEXT ctx,
1109 AIRPDCAP_SEC_ASSOCIATION_ID *id)
1113 if (ctx->sa[ctx->first_free_index].used) {
1114 /* last addition was in the middle of the array (and the first_free_index was just incremented by 1) */
1115 /* search for a free space from the first_free_index to AIRPDCAP_STA_INFOS_NR (to avoid free blocks in */
1117 for (last_free=ctx->first_free_index; last_free<AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR; last_free++)
1118 if (!ctx->sa[last_free].used)
1121 if (last_free>=AIRPDCAP_MAX_SEC_ASSOCIATIONS_NR) {
1122 /* there is no empty space available. FAILURE */
1126 /* store first free space index */
1127 ctx->first_free_index=last_free;
1131 ctx->index=ctx->first_free_index;
1133 /* reset the info structure */
1134 memset(ctx->sa+ctx->index, 0, sizeof(AIRPDCAP_SEC_ASSOCIATION));
1136 ctx->sa[ctx->index].used=1;
1138 /* set the info structure */
1139 memcpy(&(ctx->sa[ctx->index].saId), id, sizeof(AIRPDCAP_SEC_ASSOCIATION_ID));
1141 /* increment by 1 the first_free_index (heuristic) */
1142 ctx->first_free_index++;
1144 /* set the sa_index if the added index is greater the the sa_index */
1145 if (ctx->index > ctx->sa_index)
1146 ctx->sa_index=ctx->index;
1152 * AirPDcapGetBssidAddress() and AirPDcapGetBssidAddress() are used for
1153 * key caching. In each case, it's more important to return a value than
1154 * to return a _correct_ value, so we fudge addresses in some cases, e.g.
1155 * the BSSID in bridged connections.
1156 * FromDS ToDS Sta BSSID
1163 static const UCHAR *
1164 AirPDcapGetStaAddress(
1165 const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
1167 switch(AIRPDCAP_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
1171 return frame->addr2;
1173 return frame->addr1;
1179 static const UCHAR *
1180 AirPDcapGetBssidAddress(
1181 const AIRPDCAP_MAC_FRAME_ADDR4 *frame)
1183 switch(AIRPDCAP_DS_BITS(frame->fc[1])) { /* Bit 1 = FromDS, bit 0 = ToDS */
1185 return frame->addr3;
1188 return frame->addr1;
1190 return frame->addr2;
1196 /* Function used to derive the PTK. Refer to IEEE 802.11I-2004, pag. 74 */
1199 AIRPDCAP_SEC_ASSOCIATION *sa,
1200 const UCHAR pmk[32],
1201 const UCHAR snonce[32],
1202 const INT x, /* for TKIP 512, for CCMP 384 */
1207 INT offset=sizeof("Pairwise key expansion");
1211 memcpy(R, "Pairwise key expansion", offset);
1213 /* Min(AA, SPA) || Max(AA, SPA) */
1214 if (memcmp(sa->saId.sta, sa->saId.bssid, AIRPDCAP_MAC_LEN) < 0)
1216 memcpy(R + offset, sa->saId.sta, AIRPDCAP_MAC_LEN);
1217 memcpy(R + offset+AIRPDCAP_MAC_LEN, sa->saId.bssid, AIRPDCAP_MAC_LEN);
1221 memcpy(R + offset, sa->saId.bssid, AIRPDCAP_MAC_LEN);
1222 memcpy(R + offset+AIRPDCAP_MAC_LEN, sa->saId.sta, AIRPDCAP_MAC_LEN);
1225 offset+=AIRPDCAP_MAC_LEN*2;
1227 /* Min(ANonce,SNonce) || Max(ANonce,SNonce) */
1228 if( memcmp(snonce, sa->wpa.nonce, 32) < 0 )
1230 memcpy(R + offset, snonce, 32);
1231 memcpy(R + offset + 32, sa->wpa.nonce, 32);
1235 memcpy(R + offset, sa->wpa.nonce, 32);
1236 memcpy(R + offset + 32, snonce, 32);
1241 for(i = 0; i < (x+159)/160; i++)
1244 sha1_hmac(pmk, 32, R, 100, ptk + i * 20);
1249 AirPDcapRsnaPwd2PskStep(
1250 const guint8 *ppBytes,
1251 const guint ppLength,
1253 const size_t ssidLength,
1254 const INT iterations,
1258 UCHAR digest[36], digest1[AIRPDCAP_SHA_DIGEST_LEN];
1261 /* U1 = PRF(P, S || INT(i)) */
1262 memcpy(digest, ssid, ssidLength);
1263 digest[ssidLength] = (UCHAR)((count>>24) & 0xff);
1264 digest[ssidLength+1] = (UCHAR)((count>>16) & 0xff);
1265 digest[ssidLength+2] = (UCHAR)((count>>8) & 0xff);
1266 digest[ssidLength+3] = (UCHAR)(count & 0xff);
1267 sha1_hmac(ppBytes, ppLength, digest, ssidLength+4, digest1);
1270 memcpy(output, digest1, AIRPDCAP_SHA_DIGEST_LEN);
1271 for (i = 1; i < iterations; i++) {
1272 /* Un = PRF(P, Un-1) */
1273 sha1_hmac(ppBytes, ppLength, digest1, AIRPDCAP_SHA_DIGEST_LEN, digest);
1275 memcpy(digest1, digest, AIRPDCAP_SHA_DIGEST_LEN);
1276 /* output = output xor Un */
1277 for (j = 0; j < AIRPDCAP_SHA_DIGEST_LEN; j++) {
1278 output[j] ^= digest[j];
1282 return AIRPDCAP_RET_SUCCESS;
1286 AirPDcapRsnaPwd2Psk(
1287 const CHAR *passphrase,
1289 const size_t ssidLength,
1292 UCHAR m_output[AIRPDCAP_WPA_PSK_LEN];
1293 GByteArray *pp_ba = g_byte_array_new();
1295 memset(m_output, 0, AIRPDCAP_WPA_PSK_LEN);
1297 if (!uri_str_to_bytes(passphrase, pp_ba)) {
1298 g_byte_array_free(pp_ba, TRUE);
1302 AirPDcapRsnaPwd2PskStep(pp_ba->data, pp_ba->len, ssid, ssidLength, 4096, 1, m_output);
1303 AirPDcapRsnaPwd2PskStep(pp_ba->data, pp_ba->len, ssid, ssidLength, 4096, 2, &m_output[AIRPDCAP_SHA_DIGEST_LEN]);
1305 memcpy(output, m_output, AIRPDCAP_WPA_PSK_LEN);
1306 g_byte_array_free(pp_ba, TRUE);
1312 * Returns the decryption_key_t struct given a string describing the key.
1313 * Returns NULL if the key_string cannot be parsed.
1316 parse_key_string(gchar* input_string)
1322 GString *key_string = NULL;
1323 GByteArray *ssid_ba = NULL, *key_ba;
1328 decryption_key_t *dk;
1329 gchar *first_nibble = input_string;
1331 if(input_string == NULL)
1335 * Parse the input_string. It should be in the form
1336 * <key type>:<key data>[:<ssid>]
1337 * XXX - For backward compatibility, the a WEP key can be just a string
1338 * of hexadecimal characters (if WEP key is wrong, null will be
1342 /* First, check for a WEP string */
1343 /* XXX - This duplicates code in packet-ieee80211.c */
1344 if (g_ascii_strncasecmp(input_string, STRING_KEY_TYPE_WEP ":", 4) == 0) {
1348 key_ba = g_byte_array_new();
1349 res = hex_str_to_bytes(first_nibble, key_ba, FALSE);
1351 if (res && key_ba->len > 0) {
1352 /* Key is correct! It was probably an 'old style' WEP key */
1353 /* Create the decryption_key_t structure, fill it and return it*/
1354 dk = g_malloc(sizeof(decryption_key_t));
1356 dk->type = AIRPDCAP_KEY_TYPE_WEP;
1357 /* XXX - The current key handling code in the GUI requires
1358 * no separators and lower case */
1359 dk->key = g_string_new(bytes_to_str(key_ba->data, key_ba->len));
1360 g_string_down(dk->key);
1361 dk->bits = key_ba->len * 8;
1364 g_byte_array_free(key_ba, TRUE);
1367 g_byte_array_free(key_ba, TRUE);
1370 tokens = g_strsplit(input_string,":",0);
1372 /* Tokens is a null termiated array of strings ... */
1373 while(tokens[n] != NULL)
1378 /* Free the array of strings */
1383 type = g_strdup(tokens[0]);
1386 * The second token is the key (right now it doesn't matter
1387 * if it is a passphrase[+ssid] or an hexadecimal one)
1389 key = g_strdup(tokens[1]);
1392 /* Maybe there is a third token (an ssid, if everything else is ok) */
1395 ssid = g_strdup(tokens[2]);
1398 if (g_ascii_strcasecmp(type,STRING_KEY_TYPE_WPA_PSK) == 0) /* WPA key */
1400 /* Create a new string */
1401 key_string = g_string_new(key);
1403 key_ba = g_byte_array_new();
1404 res = hex_str_to_bytes(key, key_ba, FALSE);
1406 /* Two tokens means that the user should have entered a WPA-BIN key ... */
1407 if(!res || ((key_string->len) != WPA_PSK_KEY_CHAR_SIZE))
1409 g_string_free(key_string, TRUE);
1410 g_byte_array_free(key_ba, TRUE);
1414 /* No ssid has been created ... */
1415 /* Free the array of strings */
1420 /* Key was correct!!! Create the new decryption_key_t ... */
1421 dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
1423 dk->type = AIRPDCAP_KEY_TYPE_WPA_PMK;
1424 dk->key = g_string_new(key);
1425 dk->bits = dk->key->len * 4;
1428 g_string_free(key_string, TRUE);
1429 g_byte_array_free(key_ba, TRUE);
1433 /* Free the array of strings */
1437 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... */
1439 /* Create a new string */
1440 key_string = g_string_new(key);
1443 /* Three (or more) tokens mean that the user entered a WPA-PWD key ... */
1444 if( ((key_string->len) > WPA_KEY_MAX_CHAR_SIZE) || ((key_string->len) < WPA_KEY_MIN_CHAR_SIZE))
1446 g_string_free(key_string, TRUE);
1452 /* Free the array of strings */
1457 if(ssid != NULL) /* more than three tokens found, means that the user specified the ssid */
1459 ssid_ba = g_byte_array_new();
1460 if (! uri_str_to_bytes(ssid, ssid_ba)) {
1461 g_string_free(key_string, TRUE);
1462 g_byte_array_free(ssid_ba, TRUE);
1466 /* Free the array of strings */
1471 if(ssid_ba->len > WPA_SSID_MAX_CHAR_SIZE)
1473 g_string_free(key_string, TRUE);
1474 g_byte_array_free(ssid_ba, TRUE);
1480 /* Free the array of strings */
1486 /* Key was correct!!! Create the new decryption_key_t ... */
1487 dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
1489 dk->type = AIRPDCAP_KEY_TYPE_WPA_PWD;
1490 dk->key = g_string_new(key);
1491 dk->bits = 256; /* This is the length of the array pf bytes that will be generated using key+ssid ...*/
1492 dk->ssid = byte_array_dup(ssid_ba); /* NULL if ssid_ba is NULL */
1494 g_string_free(key_string, TRUE);
1495 if (ssid_ba != NULL)
1496 g_byte_array_free(ssid_ba, TRUE);
1503 /* Free the array of strings */
1508 /* Something was wrong ... free everything */
1513 g_free(ssid); /* It is not always present */
1514 if (ssid_ba != NULL)
1515 g_byte_array_free(ssid_ba, TRUE);
1517 /* Free the array of strings */
1524 * Returns a newly allocated string representing the given decryption_key_t
1525 * struct, or NULL if something is wrong...
1528 get_key_string(decryption_key_t* dk)
1530 gchar* output_string = NULL;
1532 if(dk == NULL || dk->key == NULL)
1536 case AIRPDCAP_KEY_TYPE_WEP:
1537 output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WEP,dk->key->str);
1539 case AIRPDCAP_KEY_TYPE_WPA_PWD:
1540 if(dk->ssid == NULL)
1541 output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WPA_PWD,dk->key->str);
1543 output_string = g_strdup_printf("%s:%s:%s",
1544 STRING_KEY_TYPE_WPA_PWD, dk->key->str,
1545 format_uri(dk->ssid, ":"));
1547 case AIRPDCAP_KEY_TYPE_WPA_PMK:
1548 output_string = g_strdup_printf("%s:%s",STRING_KEY_TYPE_WPA_PSK,dk->key->str);
1555 return output_string;
1562 /****************************************************************************/
1570 * set-tabs-mode: nil
1573 * ex: set shiftwidth=4 tabstop=8 expandtab
1574 * :indentSize=4:tabSize=8:noTabs=true: