wpa_common.c
Go to the documentation of this file.
00001 /*
00002  * WPA/RSN - Shared functions for supplicant and authenticator
00003  * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #include "common.h"
00018 #include "crypto/md5.h"
00019 #include "crypto/sha1.h"
00020 #include "crypto/sha256.h"
00021 #include "crypto/aes_wrap.h"
00022 #include "crypto/crypto.h"
00023 #include "ieee802_11_defs.h"
00024 #include "defs.h"
00025 #include "wpa_common.h"
00026 
00027 
00046 int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
00047                       u8 *mic)
00048 {
00049         u8 hash[SHA1_MAC_LEN];
00050 
00051         switch (ver) {
00052         case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
00053                 return hmac_md5(key, 16, buf, len, mic);
00054         case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
00055                 if (hmac_sha1(key, 16, buf, len, hash))
00056                         return -1;
00057                 os_memcpy(mic, hash, MD5_MAC_LEN);
00058                 break;
00059 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
00060         case WPA_KEY_INFO_TYPE_AES_128_CMAC:
00061                 return omac1_aes_128(key, buf, len, mic);
00062 #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
00063         default:
00064                 return -1;
00065         }
00066 
00067         return 0;
00068 }
00069 
00070 
00093 void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
00094                     const u8 *addr1, const u8 *addr2,
00095                     const u8 *nonce1, const u8 *nonce2,
00096                     u8 *ptk, size_t ptk_len, int use_sha256)
00097 {
00098         u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
00099 
00100         if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
00101                 os_memcpy(data, addr1, ETH_ALEN);
00102                 os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
00103         } else {
00104                 os_memcpy(data, addr2, ETH_ALEN);
00105                 os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
00106         }
00107 
00108         if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
00109                 os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
00110                 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
00111                           WPA_NONCE_LEN);
00112         } else {
00113                 os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
00114                 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
00115                           WPA_NONCE_LEN);
00116         }
00117 
00118 #ifdef CONFIG_IEEE80211W
00119         if (use_sha256)
00120                 sha256_prf(pmk, pmk_len, label, data, sizeof(data),
00121                            ptk, ptk_len);
00122         else
00123 #endif /* CONFIG_IEEE80211W */
00124                 sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
00125                          ptk_len);
00126 
00127         wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
00128                    MAC2STR(addr1), MAC2STR(addr2));
00129         wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
00130         wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
00131 }
00132 
00133 
00134 #ifdef CONFIG_IEEE80211R
00135 int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
00136                u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
00137                const u8 *ftie, size_t ftie_len,
00138                const u8 *rsnie, size_t rsnie_len,
00139                const u8 *ric, size_t ric_len, u8 *mic)
00140 {
00141         u8 *buf, *pos;
00142         size_t buf_len;
00143 
00144         buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
00145         buf = os_malloc(buf_len);
00146         if (buf == NULL)
00147                 return -1;
00148 
00149         pos = buf;
00150         os_memcpy(pos, sta_addr, ETH_ALEN);
00151         pos += ETH_ALEN;
00152         os_memcpy(pos, ap_addr, ETH_ALEN);
00153         pos += ETH_ALEN;
00154         *pos++ = transaction_seqnum;
00155         if (rsnie) {
00156                 os_memcpy(pos, rsnie, rsnie_len);
00157                 pos += rsnie_len;
00158         }
00159         if (mdie) {
00160                 os_memcpy(pos, mdie, mdie_len);
00161                 pos += mdie_len;
00162         }
00163         if (ftie) {
00164                 struct rsn_ftie *_ftie;
00165                 os_memcpy(pos, ftie, ftie_len);
00166                 if (ftie_len < 2 + sizeof(*_ftie)) {
00167                         os_free(buf);
00168                         return -1;
00169                 }
00170                 _ftie = (struct rsn_ftie *) (pos + 2);
00171                 os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
00172                 pos += ftie_len;
00173         }
00174         if (ric) {
00175                 os_memcpy(pos, ric, ric_len);
00176                 pos += ric_len;
00177         }
00178 
00179         wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
00180         if (omac1_aes_128(kck, buf, pos - buf, mic)) {
00181                 os_free(buf);
00182                 return -1;
00183         }
00184 
00185         os_free(buf);
00186 
00187         return 0;
00188 }
00189 #endif /* CONFIG_IEEE80211R */
00190 
00191 
00192 #ifndef CONFIG_NO_WPA2
00193 static int rsn_selector_to_bitfield(const u8 *s)
00194 {
00195         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
00196                 return WPA_CIPHER_NONE;
00197         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
00198                 return WPA_CIPHER_WEP40;
00199         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
00200                 return WPA_CIPHER_TKIP;
00201         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
00202                 return WPA_CIPHER_CCMP;
00203         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
00204                 return WPA_CIPHER_WEP104;
00205 #ifdef CONFIG_IEEE80211W
00206         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
00207                 return WPA_CIPHER_AES_128_CMAC;
00208 #endif /* CONFIG_IEEE80211W */
00209         return 0;
00210 }
00211 
00212 
00213 static int rsn_key_mgmt_to_bitfield(const u8 *s)
00214 {
00215         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
00216                 return WPA_KEY_MGMT_IEEE8021X;
00217         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
00218                 return WPA_KEY_MGMT_PSK;
00219 #ifdef CONFIG_IEEE80211R
00220         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
00221                 return WPA_KEY_MGMT_FT_IEEE8021X;
00222         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
00223                 return WPA_KEY_MGMT_FT_PSK;
00224 #endif /* CONFIG_IEEE80211R */
00225 #ifdef CONFIG_IEEE80211W
00226         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
00227                 return WPA_KEY_MGMT_IEEE8021X_SHA256;
00228         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
00229                 return WPA_KEY_MGMT_PSK_SHA256;
00230 #endif /* CONFIG_IEEE80211W */
00231         return 0;
00232 }
00233 #endif /* CONFIG_NO_WPA2 */
00234 
00235 
00243 int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
00244                          struct wpa_ie_data *data)
00245 {
00246 #ifndef CONFIG_NO_WPA2
00247         const struct rsn_ie_hdr *hdr;
00248         const u8 *pos;
00249         int left;
00250         int i, count;
00251 
00252         os_memset(data, 0, sizeof(*data));
00253         data->proto = WPA_PROTO_RSN;
00254         data->pairwise_cipher = WPA_CIPHER_CCMP;
00255         data->group_cipher = WPA_CIPHER_CCMP;
00256         data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
00257         data->capabilities = 0;
00258         data->pmkid = NULL;
00259         data->num_pmkid = 0;
00260 #ifdef CONFIG_IEEE80211W
00261         data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
00262 #else /* CONFIG_IEEE80211W */
00263         data->mgmt_group_cipher = 0;
00264 #endif /* CONFIG_IEEE80211W */
00265 
00266         if (rsn_ie_len == 0) {
00267                 /* No RSN IE - fail silently */
00268                 return -1;
00269         }
00270 
00271         if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
00272                 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
00273                            __func__, (unsigned long) rsn_ie_len);
00274                 return -1;
00275         }
00276 
00277         hdr = (const struct rsn_ie_hdr *) rsn_ie;
00278 
00279         if (hdr->elem_id != WLAN_EID_RSN ||
00280             hdr->len != rsn_ie_len - 2 ||
00281             WPA_GET_LE16(hdr->version) != RSN_VERSION) {
00282                 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
00283                            __func__);
00284                 return -2;
00285         }
00286 
00287         pos = (const u8 *) (hdr + 1);
00288         left = rsn_ie_len - sizeof(*hdr);
00289 
00290         if (left >= RSN_SELECTOR_LEN) {
00291                 data->group_cipher = rsn_selector_to_bitfield(pos);
00292 #ifdef CONFIG_IEEE80211W
00293                 if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {
00294                         wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "
00295                                    "cipher", __func__);
00296                         return -1;
00297                 }
00298 #endif /* CONFIG_IEEE80211W */
00299                 pos += RSN_SELECTOR_LEN;
00300                 left -= RSN_SELECTOR_LEN;
00301         } else if (left > 0) {
00302                 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
00303                            __func__, left);
00304                 return -3;
00305         }
00306 
00307         if (left >= 2) {
00308                 data->pairwise_cipher = 0;
00309                 count = WPA_GET_LE16(pos);
00310                 pos += 2;
00311                 left -= 2;
00312                 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
00313                         wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
00314                                    "count %u left %u", __func__, count, left);
00315                         return -4;
00316                 }
00317                 for (i = 0; i < count; i++) {
00318                         data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
00319                         pos += RSN_SELECTOR_LEN;
00320                         left -= RSN_SELECTOR_LEN;
00321                 }
00322 #ifdef CONFIG_IEEE80211W
00323                 if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
00324                         wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
00325                                    "pairwise cipher", __func__);
00326                         return -1;
00327                 }
00328 #endif /* CONFIG_IEEE80211W */
00329         } else if (left == 1) {
00330                 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
00331                            __func__);
00332                 return -5;
00333         }
00334 
00335         if (left >= 2) {
00336                 data->key_mgmt = 0;
00337                 count = WPA_GET_LE16(pos);
00338                 pos += 2;
00339                 left -= 2;
00340                 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
00341                         wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
00342                                    "count %u left %u", __func__, count, left);
00343                         return -6;
00344                 }
00345                 for (i = 0; i < count; i++) {
00346                         data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
00347                         pos += RSN_SELECTOR_LEN;
00348                         left -= RSN_SELECTOR_LEN;
00349                 }
00350         } else if (left == 1) {
00351                 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
00352                            __func__);
00353                 return -7;
00354         }
00355 
00356         if (left >= 2) {
00357                 data->capabilities = WPA_GET_LE16(pos);
00358                 pos += 2;
00359                 left -= 2;
00360         }
00361 
00362         if (left >= 2) {
00363                 data->num_pmkid = WPA_GET_LE16(pos);
00364                 pos += 2;
00365                 left -= 2;
00366                 if (left < (int) data->num_pmkid * PMKID_LEN) {
00367                         wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
00368                                    "(num_pmkid=%lu left=%d)",
00369                                    __func__, (unsigned long) data->num_pmkid,
00370                                    left);
00371                         data->num_pmkid = 0;
00372                         return -9;
00373                 } else {
00374                         data->pmkid = pos;
00375                         pos += data->num_pmkid * PMKID_LEN;
00376                         left -= data->num_pmkid * PMKID_LEN;
00377                 }
00378         }
00379 
00380 #ifdef CONFIG_IEEE80211W
00381         if (left >= 4) {
00382                 data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
00383                 if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
00384                         wpa_printf(MSG_DEBUG, "%s: Unsupported management "
00385                                    "group cipher 0x%x", __func__,
00386                                    data->mgmt_group_cipher);
00387                         return -10;
00388                 }
00389                 pos += RSN_SELECTOR_LEN;
00390                 left -= RSN_SELECTOR_LEN;
00391         }
00392 #endif /* CONFIG_IEEE80211W */
00393 
00394         if (left > 0) {
00395                 wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
00396                            __func__, left);
00397         }
00398 
00399         return 0;
00400 #else /* CONFIG_NO_WPA2 */
00401         return -1;
00402 #endif /* CONFIG_NO_WPA2 */
00403 }
00404 
00405 
00406 #ifdef CONFIG_IEEE80211R
00407 
00413 void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
00414                        const u8 *ssid, size_t ssid_len,
00415                        const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
00416                        const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
00417 {
00418         u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
00419                FT_R0KH_ID_MAX_LEN + ETH_ALEN];
00420         u8 *pos, r0_key_data[48], hash[32];
00421         const u8 *addr[2];
00422         size_t len[2];
00423 
00424         /*
00425          * R0-Key-Data = KDF-384(XXKey, "FT-R0",
00426          *                       SSIDlength || SSID || MDID || R0KHlength ||
00427          *                       R0KH-ID || S0KH-ID)
00428          * XXKey is either the second 256 bits of MSK or PSK.
00429          * PMK-R0 = L(R0-Key-Data, 0, 256)
00430          * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
00431          */
00432         if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
00433                 return;
00434         pos = buf;
00435         *pos++ = ssid_len;
00436         os_memcpy(pos, ssid, ssid_len);
00437         pos += ssid_len;
00438         os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
00439         pos += MOBILITY_DOMAIN_ID_LEN;
00440         *pos++ = r0kh_id_len;
00441         os_memcpy(pos, r0kh_id, r0kh_id_len);
00442         pos += r0kh_id_len;
00443         os_memcpy(pos, s0kh_id, ETH_ALEN);
00444         pos += ETH_ALEN;
00445 
00446         sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
00447                    r0_key_data, sizeof(r0_key_data));
00448         os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
00449 
00450         /*
00451          * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
00452          */
00453         addr[0] = (const u8 *) "FT-R0N";
00454         len[0] = 6;
00455         addr[1] = r0_key_data + PMK_LEN;
00456         len[1] = 16;
00457 
00458         sha256_vector(2, addr, len, hash);
00459         os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
00460 }
00461 
00462 
00468 void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
00469                             const u8 *s1kh_id, u8 *pmk_r1_name)
00470 {
00471         u8 hash[32];
00472         const u8 *addr[4];
00473         size_t len[4];
00474 
00475         /*
00476          * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
00477          *                                  R1KH-ID || S1KH-ID))
00478          */
00479         addr[0] = (const u8 *) "FT-R1N";
00480         len[0] = 6;
00481         addr[1] = pmk_r0_name;
00482         len[1] = WPA_PMK_NAME_LEN;
00483         addr[2] = r1kh_id;
00484         len[2] = FT_R1KH_ID_LEN;
00485         addr[3] = s1kh_id;
00486         len[3] = ETH_ALEN;
00487 
00488         sha256_vector(4, addr, len, hash);
00489         os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
00490 }
00491 
00492 
00498 void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
00499                        const u8 *r1kh_id, const u8 *s1kh_id,
00500                        u8 *pmk_r1, u8 *pmk_r1_name)
00501 {
00502         u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
00503         u8 *pos;
00504 
00505         /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
00506         pos = buf;
00507         os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
00508         pos += FT_R1KH_ID_LEN;
00509         os_memcpy(pos, s1kh_id, ETH_ALEN);
00510         pos += ETH_ALEN;
00511 
00512         sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
00513 
00514         wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
00515 }
00516 
00517 
00523 void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
00524                        const u8 *sta_addr, const u8 *bssid,
00525                        const u8 *pmk_r1_name,
00526                        u8 *ptk, size_t ptk_len, u8 *ptk_name)
00527 {
00528         u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
00529         u8 *pos, hash[32];
00530         const u8 *addr[6];
00531         size_t len[6];
00532 
00533         /*
00534          * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
00535          *                  BSSID || STA-ADDR)
00536          */
00537         pos = buf;
00538         os_memcpy(pos, snonce, WPA_NONCE_LEN);
00539         pos += WPA_NONCE_LEN;
00540         os_memcpy(pos, anonce, WPA_NONCE_LEN);
00541         pos += WPA_NONCE_LEN;
00542         os_memcpy(pos, bssid, ETH_ALEN);
00543         pos += ETH_ALEN;
00544         os_memcpy(pos, sta_addr, ETH_ALEN);
00545         pos += ETH_ALEN;
00546 
00547         sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len);
00548 
00549         /*
00550          * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
00551          *                                ANonce || BSSID || STA-ADDR))
00552          */
00553         addr[0] = pmk_r1_name;
00554         len[0] = WPA_PMK_NAME_LEN;
00555         addr[1] = (const u8 *) "FT-PTKN";
00556         len[1] = 7;
00557         addr[2] = snonce;
00558         len[2] = WPA_NONCE_LEN;
00559         addr[3] = anonce;
00560         len[3] = WPA_NONCE_LEN;
00561         addr[4] = bssid;
00562         len[4] = ETH_ALEN;
00563         addr[5] = sta_addr;
00564         len[5] = ETH_ALEN;
00565 
00566         sha256_vector(6, addr, len, hash);
00567         os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
00568 }
00569 
00570 #endif /* CONFIG_IEEE80211R */
00571 
00572 
00585 void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
00586                u8 *pmkid, int use_sha256)
00587 {
00588         char *title = "PMK Name";
00589         const u8 *addr[3];
00590         const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
00591         unsigned char hash[SHA256_MAC_LEN];
00592 
00593         addr[0] = (u8 *) title;
00594         addr[1] = aa;
00595         addr[2] = spa;
00596 
00597 #ifdef CONFIG_IEEE80211W
00598         if (use_sha256)
00599                 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
00600         else
00601 #endif /* CONFIG_IEEE80211W */
00602                 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
00603         os_memcpy(pmkid, hash, PMKID_LEN);
00604 }
00605 
00606 
00612 const char * wpa_cipher_txt(int cipher)
00613 {
00614         switch (cipher) {
00615         case WPA_CIPHER_NONE:
00616                 return "NONE";
00617         case WPA_CIPHER_WEP40:
00618                 return "WEP-40";
00619         case WPA_CIPHER_WEP104:
00620                 return "WEP-104";
00621         case WPA_CIPHER_TKIP:
00622                 return "TKIP";
00623         case WPA_CIPHER_CCMP:
00624                 return "CCMP";
00625         case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
00626                 return "CCMP+TKIP";
00627         default:
00628                 return "UNKNOWN";
00629         }
00630 }
00631 
00632 
00639 const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
00640 {
00641         switch (key_mgmt) {
00642         case WPA_KEY_MGMT_IEEE8021X:
00643                 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
00644                         return "WPA2+WPA/IEEE 802.1X/EAP";
00645                 return proto == WPA_PROTO_RSN ?
00646                         "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
00647         case WPA_KEY_MGMT_PSK:
00648                 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
00649                         return "WPA2-PSK+WPA-PSK";
00650                 return proto == WPA_PROTO_RSN ?
00651                         "WPA2-PSK" : "WPA-PSK";
00652         case WPA_KEY_MGMT_NONE:
00653                 return "NONE";
00654         case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
00655                 return "IEEE 802.1X (no WPA)";
00656 #ifdef CONFIG_IEEE80211R
00657         case WPA_KEY_MGMT_FT_IEEE8021X:
00658                 return "FT-EAP";
00659         case WPA_KEY_MGMT_FT_PSK:
00660                 return "FT-PSK";
00661 #endif /* CONFIG_IEEE80211R */
00662 #ifdef CONFIG_IEEE80211W
00663         case WPA_KEY_MGMT_IEEE8021X_SHA256:
00664                 return "WPA2-EAP-SHA256";
00665         case WPA_KEY_MGMT_PSK_SHA256:
00666                 return "WPA2-PSK-SHA256";
00667 #endif /* CONFIG_IEEE80211W */
00668         default:
00669                 return "UNKNOWN";
00670         }
00671 }
00672 
00673 
00674 int wpa_compare_rsn_ie(int ft_initial_assoc,
00675                        const u8 *ie1, size_t ie1len,
00676                        const u8 *ie2, size_t ie2len)
00677 {
00678         if (ie1 == NULL || ie2 == NULL)
00679                 return -1;
00680 
00681         if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
00682                 return 0; /* identical IEs */
00683 
00684 #ifdef CONFIG_IEEE80211R
00685         if (ft_initial_assoc) {
00686                 struct wpa_ie_data ie1d, ie2d;
00687                 /*
00688                  * The PMKID-List in RSN IE is different between Beacon/Probe
00689                  * Response/(Re)Association Request frames and EAPOL-Key
00690                  * messages in FT initial mobility domain association. Allow
00691                  * for this, but verify that other parts of the RSN IEs are
00692                  * identical.
00693                  */
00694                 if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
00695                     wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
00696                         return -1;
00697                 if (ie1d.proto == ie2d.proto &&
00698                     ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
00699                     ie1d.group_cipher == ie2d.group_cipher &&
00700                     ie1d.key_mgmt == ie2d.key_mgmt &&
00701                     ie1d.capabilities == ie2d.capabilities &&
00702                     ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
00703                         return 0;
00704         }
00705 #endif /* CONFIG_IEEE80211R */
00706 
00707         return -1;
00708 }
00709 
00710 
00711 #ifdef CONFIG_IEEE80211R
00712 int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
00713 {
00714         u8 *start, *end, *rpos, *rend;
00715         int added = 0;
00716 
00717         start = ies;
00718         end = ies + ies_len;
00719 
00720         while (start < end) {
00721                 if (*start == WLAN_EID_RSN)
00722                         break;
00723                 start += 2 + start[1];
00724         }
00725         if (start >= end) {
00726                 wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
00727                            "IEs data");
00728                 return -1;
00729         }
00730         wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
00731                     start, 2 + start[1]);
00732 
00733         /* Find start of PMKID-Count */
00734         rpos = start + 2;
00735         rend = rpos + start[1];
00736 
00737         /* Skip Version and Group Data Cipher Suite */
00738         rpos += 2 + 4;
00739         /* Skip Pairwise Cipher Suite Count and List */
00740         rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
00741         /* Skip AKM Suite Count and List */
00742         rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
00743 
00744         if (rpos == rend) {
00745                 /* Add RSN Capabilities */
00746                 os_memmove(rpos + 2, rpos, end - rpos);
00747                 *rpos++ = 0;
00748                 *rpos++ = 0;
00749         } else {
00750                 /* Skip RSN Capabilities */
00751                 rpos += 2;
00752                 if (rpos > rend) {
00753                         wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
00754                                    "IEs data");
00755                         return -1;
00756                 }
00757         }
00758 
00759         if (rpos == rend) {
00760                 /* No PMKID-Count field included; add it */
00761                 os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
00762                 WPA_PUT_LE16(rpos, 1);
00763                 rpos += 2;
00764                 os_memcpy(rpos, pmkid, PMKID_LEN);
00765                 added += 2 + PMKID_LEN;
00766                 start[1] += 2 + PMKID_LEN;
00767         } else {
00768                 /* PMKID-Count was included; use it */
00769                 if (WPA_GET_LE16(rpos) != 0) {
00770                         wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
00771                                    "in RSN IE in EAPOL-Key data");
00772                         return -1;
00773                 }
00774                 WPA_PUT_LE16(rpos, 1);
00775                 rpos += 2;
00776                 os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
00777                 os_memcpy(rpos, pmkid, PMKID_LEN);
00778                 added += PMKID_LEN;
00779                 start[1] += PMKID_LEN;
00780         }
00781 
00782         wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
00783                     "(PMKID inserted)", start, 2 + start[1]);
00784 
00785         return added;
00786 }
00787 #endif /* CONFIG_IEEE80211R */


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:36