00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
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
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
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
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
00231 return 0;
00232 }
00233 #endif
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
00263 data->mgmt_group_cipher = 0;
00264 #endif
00265
00266 if (rsn_ie_len == 0) {
00267
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
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
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
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
00401 return -1;
00402 #endif
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
00426
00427
00428
00429
00430
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
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
00477
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
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
00535
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
00551
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
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
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
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
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;
00683
00684 #ifdef CONFIG_IEEE80211R
00685 if (ft_initial_assoc) {
00686 struct wpa_ie_data ie1d, ie2d;
00687
00688
00689
00690
00691
00692
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
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
00734 rpos = start + 2;
00735 rend = rpos + start[1];
00736
00737
00738 rpos += 2 + 4;
00739
00740 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
00741
00742 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
00743
00744 if (rpos == rend) {
00745
00746 os_memmove(rpos + 2, rpos, end - rpos);
00747 *rpos++ = 0;
00748 *rpos++ = 0;
00749 } else {
00750
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
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
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