1 /* 2 * WPA Supplicant - IEEE 802.11r - Fast BSS Transition 3 * Copyright (c) 2006-2018, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "crypto/aes_wrap.h" 13 #include "crypto/sha384.h" 14 #include "crypto/sha512.h" 15 #include "crypto/random.h" 16 #include "common/ieee802_11_defs.h" 17 #include "common/ieee802_11_common.h" 18 #include "common/ocv.h" 19 #include "common/wpa_ctrl.h" 20 #include "drivers/driver.h" 21 #include "wpa.h" 22 #include "wpa_i.h" 23 #include "wpa_ie.h" 24 #include "pmksa_cache.h" 25 26 #ifdef CONFIG_IEEE80211R 27 28 #ifdef CONFIG_PASN 29 static void wpa_ft_pasn_store_r1kh(struct wpa_sm *sm, const u8 *bssid); 30 #else /* CONFIG_PASN */ 31 static void wpa_ft_pasn_store_r1kh(struct wpa_sm *sm, const u8 *bssid) 32 { 33 } 34 #endif /* CONFIG_PASN */ 35 36 37 int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, 38 const struct wpa_eapol_key *key, struct wpa_ptk *ptk) 39 { 40 u8 ptk_name[WPA_PMK_NAME_LEN]; 41 const u8 *anonce = key->key_nonce; 42 int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); 43 const u8 *mpmk; 44 size_t mpmk_len, kdk_len; 45 int ret = 0; 46 47 if (sm->xxkey_len > 0) { 48 mpmk = sm->xxkey; 49 mpmk_len = sm->xxkey_len; 50 } else if (sm->cur_pmksa) { 51 mpmk = sm->cur_pmksa->pmk; 52 mpmk_len = sm->cur_pmksa->pmk_len; 53 } else { 54 wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " 55 "derivation"); 56 return -1; 57 } 58 59 if (wpa_key_mgmt_sae_ext_key(sm->key_mgmt)) 60 sm->pmk_r0_len = mpmk_len; 61 else 62 sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; 63 if (wpa_derive_pmk_r0(mpmk, mpmk_len, sm->ssid, 64 sm->ssid_len, sm->mobility_domain, 65 sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, 66 sm->pmk_r0, sm->pmk_r0_name, sm->key_mgmt) < 0) 67 return -1; 68 sm->pmk_r1_len = sm->pmk_r0_len; 69 if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name, 70 sm->r1kh_id, sm->own_addr, sm->pmk_r1, 71 sm->pmk_r1_name) < 0) 72 return -1; 73 74 wpa_ft_pasn_store_r1kh(sm, src_addr); 75 76 if (sm->force_kdk_derivation || 77 (sm->secure_ltf && 78 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) 79 kdk_len = WPA_KDK_MAX_LEN; 80 else 81 kdk_len = 0; 82 83 ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, 84 anonce, sm->own_addr, wpa_sm_get_auth_addr(sm), 85 sm->pmk_r1_name, ptk, ptk_name, sm->key_mgmt, 86 sm->pairwise_cipher, kdk_len); 87 if (ret) { 88 wpa_printf(MSG_ERROR, "FT: PTK derivation failed"); 89 return ret; 90 } 91 92 os_memcpy(sm->key_mobility_domain, sm->mobility_domain, 93 MOBILITY_DOMAIN_ID_LEN); 94 95 #ifdef CONFIG_PASN 96 if (sm->secure_ltf && 97 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) 98 ret = wpa_ltf_keyseed(ptk, sm->key_mgmt, sm->pairwise_cipher); 99 #endif /* CONFIG_PASN */ 100 101 return ret; 102 } 103 104 105 /** 106 * wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters 107 * @sm: Pointer to WPA state machine data from wpa_sm_init() 108 * @ies: Association Response IEs or %NULL to clear FT parameters 109 * @ies_len: Length of ies buffer in octets 110 * Returns: 0 on success, -1 on failure 111 */ 112 int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) 113 { 114 struct wpa_ft_ies ft; 115 116 if (sm == NULL) 117 return 0; 118 119 if (!get_ie(ies, ies_len, WLAN_EID_MOBILITY_DOMAIN)) { 120 os_free(sm->assoc_resp_ies); 121 sm->assoc_resp_ies = NULL; 122 sm->assoc_resp_ies_len = 0; 123 os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN); 124 os_memset(sm->r0kh_id, 0, FT_R0KH_ID_MAX_LEN); 125 sm->r0kh_id_len = 0; 126 os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN); 127 return 0; 128 } 129 130 if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt, false) < 0) 131 return -1; 132 133 if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { 134 wpa_ft_parse_ies_free(&ft); 135 return -1; 136 } 137 138 wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", 139 ft.mdie, MOBILITY_DOMAIN_ID_LEN); 140 os_memcpy(sm->mobility_domain, ft.mdie, MOBILITY_DOMAIN_ID_LEN); 141 sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN]; 142 wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x", 143 sm->mdie_ft_capab); 144 145 if (ft.r0kh_id) { 146 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", 147 ft.r0kh_id, ft.r0kh_id_len); 148 os_memcpy(sm->r0kh_id, ft.r0kh_id, ft.r0kh_id_len); 149 sm->r0kh_id_len = ft.r0kh_id_len; 150 } else { 151 /* FIX: When should R0KH-ID be cleared? We need to keep the 152 * old R0KH-ID in order to be able to use this during FT. */ 153 /* 154 * os_memset(sm->r0kh_id, 0, FT_R0KH_ID_LEN); 155 * sm->r0kh_id_len = 0; 156 */ 157 } 158 159 if (ft.r1kh_id) { 160 wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", 161 ft.r1kh_id, FT_R1KH_ID_LEN); 162 os_memcpy(sm->r1kh_id, ft.r1kh_id, FT_R1KH_ID_LEN); 163 } else 164 os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN); 165 166 os_free(sm->assoc_resp_ies); 167 sm->assoc_resp_ies = os_malloc(ft.mdie_len + 2 + ft.ftie_len + 2); 168 if (sm->assoc_resp_ies) { 169 u8 *pos = sm->assoc_resp_ies; 170 171 os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2); 172 pos += ft.mdie_len + 2; 173 174 if (ft.ftie) { 175 os_memcpy(pos, ft.ftie - 2, ft.ftie_len + 2); 176 pos += ft.ftie_len + 2; 177 } 178 sm->assoc_resp_ies_len = pos - sm->assoc_resp_ies; 179 wpa_hexdump(MSG_DEBUG, "FT: Stored MDIE and FTIE from " 180 "(Re)Association Response", 181 sm->assoc_resp_ies, sm->assoc_resp_ies_len); 182 } 183 184 wpa_ft_parse_ies_free(&ft); 185 return 0; 186 } 187 188 189 /** 190 * wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth/ReAssoc Request 191 * @sm: Pointer to WPA state machine data from wpa_sm_init() 192 * @len: Buffer for returning the length of the IEs 193 * @anonce: ANonce or %NULL if not yet available 194 * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List 195 * @kck: KCK for MIC or %NULL if no MIC is used 196 * @kck_len: KCK length in octets 197 * @target_ap: Target AP address 198 * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL 199 * @ric_ies_len: Length of ric_ies buffer in octets 200 * @ap_mdie: Mobility Domain IE from the target AP 201 * @omit_rsnxe: Whether RSNXE is omitted from Reassociation Request frame 202 * Returns: Pointer to buffer with IEs or %NULL on failure 203 * 204 * Caller is responsible for freeing the returned buffer with os_free(); 205 */ 206 static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, 207 const u8 *anonce, const u8 *pmk_name, 208 const u8 *kck, size_t kck_len, 209 const u8 *target_ap, 210 const u8 *ric_ies, size_t ric_ies_len, 211 const u8 *ap_mdie, int omit_rsnxe) 212 { 213 size_t buf_len; 214 u8 *buf, *pos, *ftie_len, *ftie_pos, *fte_mic, *elem_count; 215 struct rsn_mdie *mdie; 216 struct rsn_ie_hdr *rsnie; 217 int mdie_len; 218 u8 rsnxe[10]; 219 size_t rsnxe_len; 220 int rsnxe_used; 221 int res; 222 u8 mic_control; 223 224 sm->ft_completed = 0; 225 sm->ft_reassoc_completed = 0; 226 227 buf_len = 2 + sizeof(struct rsn_mdie) + 2 + 228 sizeof(struct rsn_ftie_sha512) + 229 2 + sm->r0kh_id_len + ric_ies_len + 100; 230 buf = os_zalloc(buf_len); 231 if (buf == NULL) 232 return NULL; 233 pos = buf; 234 235 /* RSNIE[PMKR0Name/PMKR1Name] */ 236 rsnie = (struct rsn_ie_hdr *) pos; 237 rsnie->elem_id = WLAN_EID_RSN; 238 WPA_PUT_LE16(rsnie->version, RSN_VERSION); 239 pos = (u8 *) (rsnie + 1); 240 241 /* Group Suite Selector */ 242 if (!wpa_cipher_valid_group(sm->group_cipher)) { 243 wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)", 244 sm->group_cipher); 245 os_free(buf); 246 return NULL; 247 } 248 RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, 249 sm->group_cipher)); 250 pos += RSN_SELECTOR_LEN; 251 252 /* Pairwise Suite Count */ 253 WPA_PUT_LE16(pos, 1); 254 pos += 2; 255 256 /* Pairwise Suite List */ 257 if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) { 258 wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)", 259 sm->pairwise_cipher); 260 os_free(buf); 261 return NULL; 262 } 263 RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, 264 sm->pairwise_cipher)); 265 pos += RSN_SELECTOR_LEN; 266 267 /* Authenticated Key Management Suite Count */ 268 WPA_PUT_LE16(pos, 1); 269 pos += 2; 270 271 /* Authenticated Key Management Suite List */ 272 if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) 273 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); 274 #ifdef CONFIG_SHA384 275 else if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) 276 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384); 277 #endif /* CONFIG_SHA384 */ 278 else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) 279 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); 280 else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE) 281 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); 282 else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY) 283 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY); 284 #ifdef CONFIG_FILS 285 else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256) 286 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256); 287 else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) 288 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384); 289 #endif /* CONFIG_FILS */ 290 else { 291 wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)", 292 sm->key_mgmt); 293 os_free(buf); 294 return NULL; 295 } 296 pos += RSN_SELECTOR_LEN; 297 298 /* RSN Capabilities */ 299 WPA_PUT_LE16(pos, rsn_supp_capab(sm)); 300 pos += 2; 301 302 /* PMKID Count */ 303 WPA_PUT_LE16(pos, 1); 304 pos += 2; 305 306 /* PMKID List [PMKR0Name/PMKR1Name] */ 307 os_memcpy(pos, pmk_name, WPA_PMK_NAME_LEN); 308 pos += WPA_PMK_NAME_LEN; 309 310 /* Management Group Cipher Suite */ 311 switch (sm->mgmt_group_cipher) { 312 case WPA_CIPHER_AES_128_CMAC: 313 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 314 pos += RSN_SELECTOR_LEN; 315 break; 316 case WPA_CIPHER_BIP_GMAC_128: 317 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128); 318 pos += RSN_SELECTOR_LEN; 319 break; 320 case WPA_CIPHER_BIP_GMAC_256: 321 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256); 322 pos += RSN_SELECTOR_LEN; 323 break; 324 case WPA_CIPHER_BIP_CMAC_256: 325 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256); 326 pos += RSN_SELECTOR_LEN; 327 break; 328 } 329 330 rsnie->len = (pos - (u8 *) rsnie) - 2; 331 332 /* MDIE */ 333 mdie_len = wpa_ft_add_mdie(sm, pos, buf_len - (pos - buf), ap_mdie); 334 if (mdie_len <= 0) { 335 os_free(buf); 336 return NULL; 337 } 338 mdie = (struct rsn_mdie *) (pos + 2); 339 pos += mdie_len; 340 341 /* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */ 342 ftie_pos = pos; 343 *pos++ = WLAN_EID_FAST_BSS_TRANSITION; 344 ftie_len = pos++; 345 rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && anonce && 346 (sm->sae_pwe == SAE_PWE_HASH_TO_ELEMENT || 347 sm->sae_pwe == SAE_PWE_BOTH); 348 #ifdef CONFIG_TESTING_OPTIONS 349 if (anonce && sm->ft_rsnxe_used) { 350 rsnxe_used = sm->ft_rsnxe_used == 1; 351 wpa_printf(MSG_DEBUG, "TESTING: FT: Force RSNXE Used %d", 352 rsnxe_used); 353 } 354 #endif /* CONFIG_TESTING_OPTIONS */ 355 mic_control = rsnxe_used ? FTE_MIC_CTRL_RSNXE_USED : 0; 356 if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && 357 sm->pmk_r0_len == SHA512_MAC_LEN) { 358 struct rsn_ftie_sha512 *ftie; 359 360 ftie = (struct rsn_ftie_sha512 *) pos; 361 mic_control |= FTE_MIC_LEN_32 << FTE_MIC_CTRL_MIC_LEN_SHIFT; 362 ftie->mic_control[0] = mic_control; 363 fte_mic = ftie->mic; 364 elem_count = &ftie->mic_control[1]; 365 pos += sizeof(*ftie); 366 os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN); 367 if (anonce) 368 os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN); 369 } else if ((sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && 370 sm->pmk_r0_len == SHA384_MAC_LEN) || 371 wpa_key_mgmt_sha384(sm->key_mgmt)) { 372 struct rsn_ftie_sha384 *ftie; 373 374 ftie = (struct rsn_ftie_sha384 *) pos; 375 mic_control |= FTE_MIC_LEN_24 << FTE_MIC_CTRL_MIC_LEN_SHIFT; 376 ftie->mic_control[0] = mic_control; 377 fte_mic = ftie->mic; 378 elem_count = &ftie->mic_control[1]; 379 pos += sizeof(*ftie); 380 os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN); 381 if (anonce) 382 os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN); 383 } else { 384 struct rsn_ftie *ftie; 385 386 ftie = (struct rsn_ftie *) pos; 387 mic_control |= FTE_MIC_LEN_16 << FTE_MIC_CTRL_MIC_LEN_SHIFT; 388 ftie->mic_control[0] = mic_control; 389 fte_mic = ftie->mic; 390 elem_count = &ftie->mic_control[1]; 391 pos += sizeof(*ftie); 392 os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN); 393 if (anonce) 394 os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN); 395 } 396 if (kck) { 397 /* R1KH-ID sub-element in third FT message */ 398 *pos++ = FTIE_SUBELEM_R1KH_ID; 399 *pos++ = FT_R1KH_ID_LEN; 400 os_memcpy(pos, sm->r1kh_id, FT_R1KH_ID_LEN); 401 pos += FT_R1KH_ID_LEN; 402 } 403 /* R0KH-ID sub-element */ 404 *pos++ = FTIE_SUBELEM_R0KH_ID; 405 *pos++ = sm->r0kh_id_len; 406 os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len); 407 pos += sm->r0kh_id_len; 408 #ifdef CONFIG_OCV 409 if (kck && wpa_sm_ocv_enabled(sm)) { 410 /* OCI sub-element in the third FT message */ 411 struct wpa_channel_info ci; 412 413 if (wpa_sm_channel_info(sm, &ci) != 0) { 414 wpa_printf(MSG_WARNING, 415 "Failed to get channel info for OCI element in FTE"); 416 os_free(buf); 417 return NULL; 418 } 419 #ifdef CONFIG_TESTING_OPTIONS 420 if (sm->oci_freq_override_ft_assoc) { 421 wpa_printf(MSG_INFO, 422 "TEST: Override OCI KDE frequency %d -> %d MHz", 423 ci.frequency, sm->oci_freq_override_ft_assoc); 424 ci.frequency = sm->oci_freq_override_ft_assoc; 425 } 426 #endif /* CONFIG_TESTING_OPTIONS */ 427 428 *pos++ = FTIE_SUBELEM_OCI; 429 *pos++ = OCV_OCI_LEN; 430 if (ocv_insert_oci(&ci, &pos) < 0) { 431 os_free(buf); 432 return NULL; 433 } 434 } 435 #endif /* CONFIG_OCV */ 436 *ftie_len = pos - ftie_len - 1; 437 438 if (ric_ies) { 439 /* RIC Request */ 440 os_memcpy(pos, ric_ies, ric_ies_len); 441 pos += ric_ies_len; 442 } 443 444 if (omit_rsnxe) { 445 rsnxe_len = 0; 446 } else { 447 res = wpa_gen_rsnxe(sm, rsnxe, sizeof(rsnxe)); 448 if (res < 0) { 449 os_free(buf); 450 return NULL; 451 } 452 rsnxe_len = res; 453 } 454 455 if (kck) { 456 /* 457 * IEEE Std 802.11r-2008, 11A.8.4 458 * MIC shall be calculated over: 459 * non-AP STA MAC address 460 * Target AP MAC address 461 * Transaction seq number (5 for ReassocReq, 3 otherwise) 462 * RSN IE 463 * MDIE 464 * FTIE (with MIC field set to 0) 465 * RIC-Request (if present) 466 * RSNXE (if present) 467 */ 468 /* Information element count */ 469 *elem_count = 3 + ieee802_11_ie_count(ric_ies, ric_ies_len); 470 if (rsnxe_len) 471 *elem_count += 1; 472 if (wpa_ft_mic(sm->key_mgmt, kck, kck_len, 473 sm->own_addr, target_ap, 5, 474 ((u8 *) mdie) - 2, 2 + sizeof(*mdie), 475 ftie_pos, 2 + *ftie_len, 476 (u8 *) rsnie, 2 + rsnie->len, ric_ies, 477 ric_ies_len, rsnxe_len ? rsnxe : NULL, rsnxe_len, 478 NULL, 479 fte_mic) < 0) { 480 wpa_printf(MSG_INFO, "FT: Failed to calculate MIC"); 481 os_free(buf); 482 return NULL; 483 } 484 } 485 486 *len = pos - buf; 487 488 return buf; 489 } 490 491 492 static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid) 493 { 494 int keylen; 495 enum wpa_alg alg; 496 u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 }; 497 498 wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver."); 499 500 if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) { 501 wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d", 502 sm->pairwise_cipher); 503 return -1; 504 } 505 506 alg = wpa_cipher_to_alg(sm->pairwise_cipher); 507 keylen = wpa_cipher_key_len(sm->pairwise_cipher); 508 509 /* TODO: AP MLD address for MLO */ 510 if (wpa_sm_set_key(sm, -1, alg, bssid, 0, 1, null_rsc, sizeof(null_rsc), 511 (u8 *) sm->ptk.tk, keylen, 512 KEY_FLAG_PAIRWISE_RX_TX) < 0) { 513 wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver"); 514 return -1; 515 } 516 sm->tk_set = true; 517 518 wpa_sm_store_ptk(sm, bssid, sm->pairwise_cipher, 519 sm->dot11RSNAConfigPMKLifetime, &sm->ptk); 520 return 0; 521 } 522 523 524 /** 525 * wpa_ft_prepare_auth_request - Generate over-the-air auth request 526 * @sm: Pointer to WPA state machine data from wpa_sm_init() 527 * @mdie: Target AP MDIE 528 * Returns: 0 on success, -1 on failure 529 */ 530 int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie) 531 { 532 u8 *ft_ies; 533 size_t ft_ies_len; 534 535 /* Generate a new SNonce */ 536 if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { 537 wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce"); 538 return -1; 539 } 540 541 ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, 542 NULL, 0, sm->bssid, NULL, 0, mdie, 0); 543 if (ft_ies) { 544 wpa_sm_update_ft_ies(sm, sm->mobility_domain, 545 ft_ies, ft_ies_len); 546 os_free(ft_ies); 547 } 548 549 return 0; 550 } 551 552 553 int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *buf, size_t buf_len, 554 const u8 *ap_mdie) 555 { 556 u8 *pos = buf; 557 struct rsn_mdie *mdie; 558 559 if (buf_len < 2 + sizeof(*mdie)) { 560 wpa_printf(MSG_INFO, 561 "FT: Failed to add MDIE: short buffer, length=%zu", 562 buf_len); 563 return 0; 564 } 565 566 *pos++ = WLAN_EID_MOBILITY_DOMAIN; 567 *pos++ = sizeof(*mdie); 568 mdie = (struct rsn_mdie *) pos; 569 os_memcpy(mdie->mobility_domain, sm->mobility_domain, 570 MOBILITY_DOMAIN_ID_LEN); 571 mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] : 572 sm->mdie_ft_capab; 573 574 return 2 + sizeof(*mdie); 575 } 576 577 578 const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm) 579 { 580 return sm->mobility_domain; 581 } 582 583 584 int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, 585 int ft_action, const u8 *target_ap, 586 const u8 *ric_ies, size_t ric_ies_len) 587 { 588 u8 *ft_ies; 589 size_t ft_ies_len; 590 struct wpa_ft_ies parse; 591 struct rsn_mdie *mdie; 592 u8 ptk_name[WPA_PMK_NAME_LEN]; 593 int ret = -1, res; 594 const u8 *bssid; 595 const u8 *kck; 596 size_t kck_len, kdk_len; 597 598 os_memset(&parse, 0, sizeof(parse)); 599 600 wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); 601 wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len); 602 603 if (ft_action) { 604 if (!sm->over_the_ds_in_progress) { 605 wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress " 606 "- drop FT Action Response"); 607 goto fail; 608 } 609 610 if (!ether_addr_equal(target_ap, sm->target_ap)) { 611 wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress " 612 "with this Target AP - drop FT Action " 613 "Response"); 614 goto fail; 615 } 616 } 617 618 if (!wpa_key_mgmt_ft(sm->key_mgmt)) { 619 wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not " 620 "enabled for this connection"); 621 goto fail; 622 } 623 624 if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt, 625 !ft_action) < 0) { 626 wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); 627 goto fail; 628 } 629 630 mdie = (struct rsn_mdie *) parse.mdie; 631 if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || 632 os_memcmp(mdie->mobility_domain, sm->mobility_domain, 633 MOBILITY_DOMAIN_ID_LEN) != 0) { 634 wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); 635 goto fail; 636 } 637 638 if (!parse.ftie || !parse.fte_anonce || !parse.fte_snonce) { 639 wpa_printf(MSG_DEBUG, "FT: Invalid FTE"); 640 goto fail; 641 } 642 643 if (os_memcmp(parse.fte_snonce, sm->snonce, WPA_NONCE_LEN) != 0) { 644 wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); 645 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", 646 parse.fte_snonce, WPA_NONCE_LEN); 647 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", 648 sm->snonce, WPA_NONCE_LEN); 649 goto fail; 650 } 651 652 if (parse.r0kh_id == NULL) { 653 wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); 654 goto fail; 655 } 656 657 if (parse.r0kh_id_len != sm->r0kh_id_len || 658 os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) 659 { 660 wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " 661 "the current R0KH-ID"); 662 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", 663 parse.r0kh_id, parse.r0kh_id_len); 664 wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", 665 sm->r0kh_id, sm->r0kh_id_len); 666 goto fail; 667 } 668 669 if (parse.r1kh_id == NULL) { 670 wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); 671 goto fail; 672 } 673 674 if (parse.rsn_pmkid == NULL || 675 os_memcmp_const(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN)) 676 { 677 wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in " 678 "RSNIE"); 679 goto fail; 680 } 681 682 if (sm->mfp == 2 && !(parse.rsn_capab & WPA_CAPABILITY_MFPC)) { 683 wpa_printf(MSG_INFO, 684 "FT: Target AP does not support PMF, but local configuration requires that"); 685 goto fail; 686 } 687 688 os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); 689 wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN); 690 wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN); 691 wpa_hexdump(MSG_DEBUG, "FT: ANonce", parse.fte_anonce, WPA_NONCE_LEN); 692 os_memcpy(sm->anonce, parse.fte_anonce, WPA_NONCE_LEN); 693 if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name, 694 sm->r1kh_id, sm->own_addr, sm->pmk_r1, 695 sm->pmk_r1_name) < 0) 696 goto fail; 697 sm->pmk_r1_len = sm->pmk_r0_len; 698 699 bssid = target_ap; 700 701 wpa_ft_pasn_store_r1kh(sm, bssid); 702 703 if (sm->force_kdk_derivation || 704 (sm->secure_ltf && 705 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) 706 kdk_len = WPA_KDK_MAX_LEN; 707 else 708 kdk_len = 0; 709 710 /* TODO: AP MLD address for MLO */ 711 if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, 712 parse.fte_anonce, sm->own_addr, bssid, 713 sm->pmk_r1_name, &sm->ptk, ptk_name, sm->key_mgmt, 714 sm->pairwise_cipher, 715 kdk_len) < 0) 716 goto fail; 717 718 os_memcpy(sm->key_mobility_domain, sm->mobility_domain, 719 MOBILITY_DOMAIN_ID_LEN); 720 721 #ifdef CONFIG_PASN 722 if (sm->secure_ltf && 723 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && 724 wpa_ltf_keyseed(&sm->ptk, sm->key_mgmt, sm->pairwise_cipher)) { 725 wpa_printf(MSG_DEBUG, "FT: Failed to derive LTF keyseed"); 726 goto fail; 727 } 728 #endif /* CONFIG_PASN */ 729 730 if (wpa_key_mgmt_fils(sm->key_mgmt)) { 731 kck = sm->ptk.kck2; 732 kck_len = sm->ptk.kck2_len; 733 } else { 734 kck = sm->ptk.kck; 735 kck_len = sm->ptk.kck_len; 736 } 737 ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, parse.fte_anonce, 738 sm->pmk_r1_name, 739 kck, kck_len, bssid, 740 ric_ies, ric_ies_len, 741 parse.mdie ? parse.mdie - 2 : NULL, 742 !sm->ap_rsnxe); 743 if (ft_ies) { 744 wpa_sm_update_ft_ies(sm, sm->mobility_domain, 745 ft_ies, ft_ies_len); 746 os_free(ft_ies); 747 } 748 749 wpa_sm_mark_authenticated(sm, bssid); 750 res = wpa_ft_install_ptk(sm, bssid); 751 if (res) { 752 /* 753 * Some drivers do not support key configuration when we are 754 * not associated with the target AP. Work around this by 755 * trying again after the following reassociation gets 756 * completed. 757 */ 758 wpa_printf(MSG_DEBUG, "FT: Failed to set PTK prior to " 759 "association - try again after reassociation"); 760 sm->set_ptk_after_assoc = 1; 761 } else 762 sm->set_ptk_after_assoc = 0; 763 764 sm->ft_completed = 1; 765 if (ft_action) { 766 /* 767 * The caller is expected trigger re-association with the 768 * Target AP. 769 */ 770 os_memcpy(sm->bssid, target_ap, ETH_ALEN); 771 } 772 773 ret = 0; 774 fail: 775 wpa_ft_parse_ies_free(&parse); 776 return ret; 777 } 778 779 780 int wpa_ft_is_completed(struct wpa_sm *sm) 781 { 782 if (sm == NULL) 783 return 0; 784 785 if (!wpa_key_mgmt_ft(sm->key_mgmt)) 786 return 0; 787 788 return sm->ft_completed; 789 } 790 791 792 void wpa_reset_ft_completed(struct wpa_sm *sm) 793 { 794 if (sm != NULL) 795 sm->ft_completed = 0; 796 } 797 798 799 static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, 800 size_t gtk_elem_len) 801 { 802 u8 gtk[32]; 803 int keyidx; 804 enum wpa_alg alg; 805 size_t gtk_len, keylen, rsc_len; 806 const u8 *kek; 807 size_t kek_len; 808 809 if (wpa_key_mgmt_fils(sm->key_mgmt)) { 810 kek = sm->ptk.kek2; 811 kek_len = sm->ptk.kek2_len; 812 } else { 813 kek = sm->ptk.kek; 814 kek_len = sm->ptk.kek_len; 815 } 816 817 if (gtk_elem == NULL) { 818 wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE"); 819 return 0; 820 } 821 822 wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp", 823 gtk_elem, gtk_elem_len); 824 825 if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 || 826 gtk_elem_len - 19 > sizeof(gtk)) { 827 wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem " 828 "length %lu", (unsigned long) gtk_elem_len); 829 return -1; 830 } 831 gtk_len = gtk_elem_len - 19; 832 if (aes_unwrap(kek, kek_len, gtk_len / 8, gtk_elem + 11, gtk)) { 833 wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " 834 "decrypt GTK"); 835 return -1; 836 } 837 838 keylen = wpa_cipher_key_len(sm->group_cipher); 839 rsc_len = wpa_cipher_rsc_len(sm->group_cipher); 840 alg = wpa_cipher_to_alg(sm->group_cipher); 841 if (alg == WPA_ALG_NONE) { 842 wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d", 843 sm->group_cipher); 844 return -1; 845 } 846 847 if (gtk_len < keylen) { 848 wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE"); 849 return -1; 850 } 851 852 /* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */ 853 854 keyidx = WPA_GET_LE16(gtk_elem) & 0x03; 855 856 if (gtk_elem[2] != keylen) { 857 wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d " 858 "negotiated %lu", 859 gtk_elem[2], (unsigned long) keylen); 860 return -1; 861 } 862 863 wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen); 864 if (sm->group_cipher == WPA_CIPHER_TKIP) { 865 /* Swap Tx/Rx keys for Michael MIC */ 866 u8 tmp[8]; 867 os_memcpy(tmp, gtk + 16, 8); 868 os_memcpy(gtk + 16, gtk + 24, 8); 869 os_memcpy(gtk + 24, tmp, 8); 870 } 871 if (wpa_sm_set_key(sm, -1, alg, broadcast_ether_addr, keyidx, 0, 872 gtk_elem + 3, rsc_len, gtk, keylen, 873 KEY_FLAG_GROUP_RX) < 0) { 874 wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the " 875 "driver."); 876 return -1; 877 } 878 879 return 0; 880 } 881 882 883 static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, 884 size_t igtk_elem_len) 885 { 886 u8 igtk[WPA_IGTK_MAX_LEN]; 887 size_t igtk_len; 888 u16 keyidx; 889 const u8 *kek; 890 size_t kek_len; 891 892 if (wpa_key_mgmt_fils(sm->key_mgmt)) { 893 kek = sm->ptk.kek2; 894 kek_len = sm->ptk.kek2_len; 895 } else { 896 kek = sm->ptk.kek; 897 kek_len = sm->ptk.kek_len; 898 } 899 900 if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && 901 sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && 902 sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && 903 sm->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256) 904 return 0; 905 906 if (igtk_elem == NULL) { 907 wpa_printf(MSG_DEBUG, "FT: No IGTK included in FTIE"); 908 return 0; 909 } 910 911 wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp", 912 igtk_elem, igtk_elem_len); 913 914 igtk_len = wpa_cipher_key_len(sm->mgmt_group_cipher); 915 if (igtk_elem_len != 2 + 6 + 1 + igtk_len + 8) { 916 wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem " 917 "length %lu", (unsigned long) igtk_elem_len); 918 return -1; 919 } 920 if (igtk_elem[8] != igtk_len) { 921 wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length " 922 "%d", igtk_elem[8]); 923 return -1; 924 } 925 926 if (aes_unwrap(kek, kek_len, igtk_len / 8, igtk_elem + 9, igtk)) { 927 wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " 928 "decrypt IGTK"); 929 return -1; 930 } 931 932 /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ 933 934 keyidx = WPA_GET_LE16(igtk_elem); 935 936 wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk, 937 igtk_len); 938 if (wpa_sm_set_key(sm, -1, wpa_cipher_to_alg(sm->mgmt_group_cipher), 939 broadcast_ether_addr, keyidx, 0, 940 igtk_elem + 2, 6, igtk, igtk_len, 941 KEY_FLAG_GROUP_RX) < 0) { 942 wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the " 943 "driver."); 944 forced_memzero(igtk, sizeof(igtk)); 945 return -1; 946 } 947 forced_memzero(igtk, sizeof(igtk)); 948 949 return 0; 950 } 951 952 953 static int wpa_ft_process_bigtk_subelem(struct wpa_sm *sm, const u8 *bigtk_elem, 954 size_t bigtk_elem_len) 955 { 956 u8 bigtk[WPA_BIGTK_MAX_LEN]; 957 size_t bigtk_len; 958 u16 keyidx; 959 const u8 *kek; 960 size_t kek_len; 961 962 if (!sm->beacon_prot || !bigtk_elem || 963 (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && 964 sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && 965 sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && 966 sm->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256)) 967 return 0; 968 969 if (wpa_key_mgmt_fils(sm->key_mgmt)) { 970 kek = sm->ptk.kek2; 971 kek_len = sm->ptk.kek2_len; 972 } else { 973 kek = sm->ptk.kek; 974 kek_len = sm->ptk.kek_len; 975 } 976 977 wpa_hexdump_key(MSG_DEBUG, "FT: Received BIGTK in Reassoc Resp", 978 bigtk_elem, bigtk_elem_len); 979 980 bigtk_len = wpa_cipher_key_len(sm->mgmt_group_cipher); 981 if (bigtk_elem_len != 2 + 6 + 1 + bigtk_len + 8) { 982 wpa_printf(MSG_DEBUG, 983 "FT: Invalid BIGTK sub-elem length %lu", 984 (unsigned long) bigtk_elem_len); 985 return -1; 986 } 987 if (bigtk_elem[8] != bigtk_len) { 988 wpa_printf(MSG_DEBUG, 989 "FT: Invalid BIGTK sub-elem Key Length %d", 990 bigtk_elem[8]); 991 return -1; 992 } 993 994 if (aes_unwrap(kek, kek_len, bigtk_len / 8, bigtk_elem + 9, bigtk)) { 995 wpa_printf(MSG_WARNING, 996 "FT: AES unwrap failed - could not decrypt BIGTK"); 997 return -1; 998 } 999 1000 /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ 1001 1002 keyidx = WPA_GET_LE16(bigtk_elem); 1003 1004 wpa_hexdump_key(MSG_DEBUG, "FT: BIGTK from Reassoc Resp", bigtk, 1005 bigtk_len); 1006 if (wpa_sm_set_key(sm, -1, wpa_cipher_to_alg(sm->mgmt_group_cipher), 1007 broadcast_ether_addr, keyidx, 0, 1008 bigtk_elem + 2, 6, bigtk, bigtk_len, 1009 KEY_FLAG_GROUP_RX) < 0) { 1010 wpa_printf(MSG_WARNING, 1011 "WPA: Failed to set BIGTK to the driver"); 1012 forced_memzero(bigtk, sizeof(bigtk)); 1013 return -1; 1014 } 1015 forced_memzero(bigtk, sizeof(bigtk)); 1016 1017 return 0; 1018 } 1019 1020 1021 int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, 1022 size_t ies_len, const u8 *src_addr) 1023 { 1024 struct wpa_ft_ies parse; 1025 struct rsn_mdie *mdie; 1026 unsigned int count; 1027 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; 1028 const u8 *kck; 1029 size_t kck_len; 1030 int own_rsnxe_used; 1031 size_t mic_len; 1032 int ret = -1; 1033 1034 os_memset(&parse, 0, sizeof(parse)); 1035 1036 wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); 1037 1038 if (!wpa_key_mgmt_ft(sm->key_mgmt)) { 1039 wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not " 1040 "enabled for this connection"); 1041 goto fail; 1042 } 1043 1044 if (sm->ft_reassoc_completed) { 1045 wpa_printf(MSG_DEBUG, "FT: Reassociation has already been completed for this FT protocol instance - ignore unexpected retransmission"); 1046 return 0; 1047 } 1048 1049 if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt, true) < 0) { 1050 wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); 1051 goto fail; 1052 } 1053 1054 mdie = (struct rsn_mdie *) parse.mdie; 1055 if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || 1056 os_memcmp(mdie->mobility_domain, sm->mobility_domain, 1057 MOBILITY_DOMAIN_ID_LEN) != 0) { 1058 wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); 1059 goto fail; 1060 } 1061 1062 if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && 1063 sm->pmk_r1_len == SHA512_MAC_LEN) 1064 mic_len = 32; 1065 else if ((sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && 1066 sm->pmk_r1_len == SHA384_MAC_LEN) || 1067 wpa_key_mgmt_sha384(sm->key_mgmt)) 1068 mic_len = 24; 1069 else 1070 mic_len = 16; 1071 1072 if (!parse.ftie || !parse.fte_anonce || !parse.fte_snonce || 1073 parse.fte_mic_len != mic_len) { 1074 wpa_printf(MSG_DEBUG, 1075 "FT: Invalid FTE (fte_mic_len=%zu mic_len=%zu)", 1076 parse.fte_mic_len, mic_len); 1077 goto fail; 1078 } 1079 1080 if (os_memcmp(parse.fte_snonce, sm->snonce, WPA_NONCE_LEN) != 0) { 1081 wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); 1082 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", 1083 parse.fte_snonce, WPA_NONCE_LEN); 1084 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", 1085 sm->snonce, WPA_NONCE_LEN); 1086 goto fail; 1087 } 1088 1089 if (os_memcmp(parse.fte_anonce, sm->anonce, WPA_NONCE_LEN) != 0) { 1090 wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE"); 1091 wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", 1092 parse.fte_anonce, WPA_NONCE_LEN); 1093 wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", 1094 sm->anonce, WPA_NONCE_LEN); 1095 goto fail; 1096 } 1097 1098 if (parse.r0kh_id == NULL) { 1099 wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); 1100 goto fail; 1101 } 1102 1103 if (parse.r0kh_id_len != sm->r0kh_id_len || 1104 os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) 1105 { 1106 wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " 1107 "the current R0KH-ID"); 1108 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", 1109 parse.r0kh_id, parse.r0kh_id_len); 1110 wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", 1111 sm->r0kh_id, sm->r0kh_id_len); 1112 goto fail; 1113 } 1114 1115 if (parse.r1kh_id == NULL) { 1116 wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); 1117 goto fail; 1118 } 1119 1120 if (os_memcmp_const(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) { 1121 wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " 1122 "ReassocResp"); 1123 goto fail; 1124 } 1125 1126 if (parse.rsn_pmkid == NULL || 1127 os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) 1128 { 1129 wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " 1130 "RSNIE (pmkid=%d)", !!parse.rsn_pmkid); 1131 goto fail; 1132 } 1133 1134 count = 3; 1135 if (parse.ric) 1136 count += ieee802_11_ie_count(parse.ric, parse.ric_len); 1137 if (parse.rsnxe) 1138 count++; 1139 if (parse.fte_elem_count != count) { 1140 wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " 1141 "Control: received %u expected %u", 1142 parse.fte_elem_count, count); 1143 goto fail; 1144 } 1145 1146 if (wpa_key_mgmt_fils(sm->key_mgmt)) { 1147 kck = sm->ptk.kck2; 1148 kck_len = sm->ptk.kck2_len; 1149 } else { 1150 kck = sm->ptk.kck; 1151 kck_len = sm->ptk.kck_len; 1152 } 1153 1154 if (wpa_ft_mic(sm->key_mgmt, kck, kck_len, sm->own_addr, src_addr, 6, 1155 parse.mdie - 2, parse.mdie_len + 2, 1156 parse.ftie - 2, parse.ftie_len + 2, 1157 parse.rsn - 2, parse.rsn_len + 2, 1158 parse.ric, parse.ric_len, 1159 parse.rsnxe ? parse.rsnxe - 2 : NULL, 1160 parse.rsnxe ? parse.rsnxe_len + 2 : 0, 1161 NULL, 1162 mic) < 0) { 1163 wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); 1164 goto fail; 1165 } 1166 1167 if (os_memcmp_const(mic, parse.fte_mic, mic_len) != 0) { 1168 wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE"); 1169 wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", 1170 parse.fte_mic, mic_len); 1171 wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len); 1172 goto fail; 1173 } 1174 1175 if (parse.fte_rsnxe_used && !sm->ap_rsnxe) { 1176 wpa_printf(MSG_INFO, 1177 "FT: FTE indicated that AP uses RSNXE, but RSNXE was not included in Beacon/Probe Response frames"); 1178 goto fail; 1179 } 1180 1181 if (!sm->ap_rsn_ie) { 1182 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1183 "FT: No RSNE for this AP known - trying to get from scan results"); 1184 if (wpa_sm_get_beacon_ie(sm) < 0) { 1185 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1186 "FT: Could not find AP from the scan results"); 1187 goto fail; 1188 } 1189 wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, 1190 "FT: Found the current AP from updated scan results"); 1191 } 1192 1193 if (sm->ap_rsn_ie && 1194 wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), 1195 sm->ap_rsn_ie, sm->ap_rsn_ie_len, 1196 parse.rsn - 2, parse.rsn_len + 2)) { 1197 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1198 "FT: RSNE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame"); 1199 wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp", 1200 sm->ap_rsn_ie, sm->ap_rsn_ie_len); 1201 wpa_hexdump(MSG_INFO, 1202 "RSNE in FT protocol Reassociation Response frame", 1203 parse.rsn ? parse.rsn - 2 : NULL, 1204 parse.rsn ? parse.rsn_len + 2 : 0); 1205 goto fail; 1206 } 1207 1208 own_rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && 1209 (sm->sae_pwe == SAE_PWE_HASH_TO_ELEMENT || 1210 sm->sae_pwe == SAE_PWE_BOTH); 1211 if ((sm->ap_rsnxe && !parse.rsnxe && own_rsnxe_used) || 1212 (!sm->ap_rsnxe && parse.rsnxe) || 1213 (sm->ap_rsnxe && parse.rsnxe && 1214 (sm->ap_rsnxe_len != 2 + parse.rsnxe_len || 1215 os_memcmp(sm->ap_rsnxe, parse.rsnxe - 2, 1216 sm->ap_rsnxe_len) != 0))) { 1217 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1218 "FT: RSNXE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame"); 1219 wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp", 1220 sm->ap_rsnxe, sm->ap_rsnxe_len); 1221 wpa_hexdump(MSG_INFO, 1222 "RSNXE in FT protocol Reassociation Response frame", 1223 parse.rsnxe ? parse.rsnxe - 2 : NULL, 1224 parse.rsnxe ? parse.rsnxe_len + 2 : 0); 1225 goto fail; 1226 } 1227 1228 #ifdef CONFIG_OCV 1229 if (wpa_sm_ocv_enabled(sm)) { 1230 struct wpa_channel_info ci; 1231 1232 if (wpa_sm_channel_info(sm, &ci) != 0) { 1233 wpa_printf(MSG_WARNING, 1234 "Failed to get channel info to validate received OCI in (Re)Assoc Response"); 1235 goto fail; 1236 } 1237 1238 if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, 1239 channel_width_to_int(ci.chanwidth), 1240 ci.seg1_idx) != OCI_SUCCESS) { 1241 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE 1242 "addr=" MACSTR " frame=ft-assoc error=%s", 1243 MAC2STR(src_addr), ocv_errorstr); 1244 goto fail; 1245 } 1246 } 1247 #endif /* CONFIG_OCV */ 1248 1249 sm->ft_reassoc_completed = 1; 1250 1251 if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0 || 1252 wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0 || 1253 wpa_ft_process_bigtk_subelem(sm, parse.bigtk, parse.bigtk_len) < 0) 1254 goto fail; 1255 1256 if (sm->set_ptk_after_assoc) { 1257 wpa_printf(MSG_DEBUG, "FT: Try to set PTK again now that we " 1258 "are associated"); 1259 if (wpa_ft_install_ptk(sm, src_addr) < 0) 1260 goto fail; 1261 sm->set_ptk_after_assoc = 0; 1262 } 1263 1264 if (parse.ric) { 1265 wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response", 1266 parse.ric, parse.ric_len); 1267 /* TODO: parse response and inform driver about results when 1268 * using wpa_supplicant SME */ 1269 } 1270 1271 wpa_printf(MSG_DEBUG, "FT: Completed successfully"); 1272 1273 ret = 0; 1274 fail: 1275 wpa_ft_parse_ies_free(&parse); 1276 return ret; 1277 } 1278 1279 1280 /** 1281 * wpa_ft_start_over_ds - Generate over-the-DS auth request 1282 * @sm: Pointer to WPA state machine data from wpa_sm_init() 1283 * @target_ap: Target AP Address 1284 * @mdie: Mobility Domain IE from the target AP 1285 * @force: Whether to force the request and ignore mobility domain differences 1286 * (only for testing purposes) 1287 * Returns: 0 on success, -1 on failure 1288 */ 1289 int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, 1290 const u8 *mdie, bool force) 1291 { 1292 u8 *ft_ies; 1293 size_t ft_ies_len; 1294 1295 if (!force && 1296 (!mdie || mdie[1] < 3 || !wpa_sm_has_ft_keys(sm, mdie + 2))) { 1297 wpa_printf(MSG_DEBUG, "FT: Cannot use over-the DS with " MACSTR 1298 " - no keys matching the mobility domain", 1299 MAC2STR(target_ap)); 1300 return -1; 1301 } 1302 1303 wpa_printf(MSG_DEBUG, "FT: Request over-the-DS with " MACSTR, 1304 MAC2STR(target_ap)); 1305 1306 /* Generate a new SNonce */ 1307 if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { 1308 wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce"); 1309 return -1; 1310 } 1311 1312 ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, 1313 NULL, 0, target_ap, NULL, 0, mdie, 0); 1314 if (ft_ies) { 1315 sm->over_the_ds_in_progress = 1; 1316 os_memcpy(sm->target_ap, target_ap, ETH_ALEN); 1317 wpa_sm_send_ft_action(sm, 1, target_ap, ft_ies, ft_ies_len); 1318 os_free(ft_ies); 1319 } 1320 1321 return 0; 1322 } 1323 1324 1325 #ifdef CONFIG_PASN 1326 1327 static struct pasn_ft_r1kh * wpa_ft_pasn_get_r1kh(struct wpa_sm *sm, 1328 const u8 *bssid) 1329 { 1330 size_t i; 1331 1332 for (i = 0; i < sm->n_pasn_r1kh; i++) 1333 if (ether_addr_equal(sm->pasn_r1kh[i].bssid, bssid)) 1334 return &sm->pasn_r1kh[i]; 1335 1336 return NULL; 1337 } 1338 1339 1340 static void wpa_ft_pasn_store_r1kh(struct wpa_sm *sm, const u8 *bssid) 1341 { 1342 struct pasn_ft_r1kh *tmp = wpa_ft_pasn_get_r1kh(sm, bssid); 1343 1344 if (tmp) 1345 return; 1346 1347 tmp = os_realloc_array(sm->pasn_r1kh, sm->n_pasn_r1kh + 1, 1348 sizeof(*tmp)); 1349 if (!tmp) { 1350 wpa_printf(MSG_DEBUG, "PASN: FT: Failed to store R1KH"); 1351 return; 1352 } 1353 1354 sm->pasn_r1kh = tmp; 1355 tmp = &sm->pasn_r1kh[sm->n_pasn_r1kh]; 1356 1357 wpa_printf(MSG_DEBUG, "PASN: FT: Store R1KH for " MACSTR, 1358 MAC2STR(bssid)); 1359 1360 os_memcpy(tmp->bssid, bssid, ETH_ALEN); 1361 os_memcpy(tmp->r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN); 1362 1363 sm->n_pasn_r1kh++; 1364 } 1365 1366 1367 int wpa_pasn_ft_derive_pmk_r1(struct wpa_sm *sm, int akmp, const u8 *bssid, 1368 u8 *pmk_r1, size_t *pmk_r1_len, u8 *pmk_r1_name) 1369 { 1370 struct pasn_ft_r1kh *r1kh_entry; 1371 1372 if (sm->key_mgmt != (unsigned int) akmp) { 1373 wpa_printf(MSG_DEBUG, 1374 "PASN: FT: Key management mismatch: %u != %u", 1375 sm->key_mgmt, akmp); 1376 return -1; 1377 } 1378 1379 r1kh_entry = wpa_ft_pasn_get_r1kh(sm, bssid); 1380 if (!r1kh_entry) { 1381 wpa_printf(MSG_DEBUG, 1382 "PASN: FT: Cannot find R1KH-ID for " MACSTR, 1383 MAC2STR(bssid)); 1384 return -1; 1385 } 1386 1387 /* 1388 * Note: PMK R0 etc. were already derived and are maintained by the 1389 * state machine, and as the same key hierarchy is used, there is no 1390 * need to derive them again, so only derive PMK R1 etc. 1391 */ 1392 if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name, 1393 r1kh_entry->r1kh_id, sm->own_addr, pmk_r1, 1394 pmk_r1_name) < 0) 1395 return -1; 1396 1397 *pmk_r1_len = sm->pmk_r0_len; 1398 1399 wpa_hexdump_key(MSG_DEBUG, "PASN: FT: PMK-R1", pmk_r1, sm->pmk_r0_len); 1400 wpa_hexdump(MSG_DEBUG, "PASN: FT: PMKR1Name", pmk_r1_name, 1401 WPA_PMK_NAME_LEN); 1402 1403 return 0; 1404 } 1405 1406 #endif /* CONFIG_PASN */ 1407 1408 #endif /* CONFIG_IEEE80211R */ 1409