wpa_ft.c
来自「最新的Host AP 新添加了许多pcmcia 的驱动」· C语言 代码 · 共 1,500 行 · 第 1/3 页
C
1,500 行
/* Mobility Domain Information */ res = wpa_write_mdie(conf, pos, end - pos); if (res < 0) return pos; mdie = pos; mdie_len = res; pos += res; /* Fast BSS Transition Information */ if (auth_alg == WLAN_AUTH_FT) { subelem = wpa_ft_gtk_subelem(sm, &subelem_len); r0kh_id = sm->r0kh_id; r0kh_id_len = sm->r0kh_id_len;#ifdef CONFIG_IEEE80211W if (sm->mgmt_frame_prot) { u8 *igtk; size_t igtk_len; u8 *nbuf; igtk = wpa_ft_igtk_subelem(sm, &igtk_len); if (igtk == NULL) { os_free(subelem); return pos; } nbuf = os_realloc(subelem, subelem_len + igtk_len); if (nbuf == NULL) { os_free(subelem); os_free(igtk); return pos; } subelem = nbuf; os_memcpy(subelem + subelem_len, igtk, igtk_len); subelem_len += igtk_len; os_free(igtk); }#endif /* CONFIG_IEEE80211W */ } else { r0kh_id = conf->r0_key_holder; r0kh_id_len = conf->r0_key_holder_len; } res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, NULL, NULL, pos, end - pos, subelem, subelem_len); os_free(subelem); if (res < 0) return pos; ftie = pos; ftie_len = res; pos += res; _ftie = (struct rsn_ftie *) (ftie + 2); _ftie->mic_control[1] = 3; /* Information element count */ if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6, mdie, mdie_len, ftie, ftie_len, rsnie, rsnie_len, NULL, 0, _ftie->mic) < 0) wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); return pos;}struct wpa_ft_ies { const u8 *mdie; size_t mdie_len; const u8 *ftie; size_t ftie_len; const u8 *r1kh_id; const u8 *gtk; size_t gtk_len; const u8 *r0kh_id; size_t r0kh_id_len; const u8 *rsn; size_t rsn_len; const u8 *rsn_pmkid;};static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, struct wpa_ft_ies *parse){ const u8 *end, *pos; parse->ftie = ie; parse->ftie_len = ie_len; pos = ie + sizeof(struct rsn_ftie); end = ie + ie_len; while (pos + 2 <= end && pos + 2 + pos[1] <= end) { switch (pos[0]) { case FTIE_SUBELEM_R1KH_ID: if (pos[1] != FT_R1KH_ID_LEN) { wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID " "length in FTIE: %d", pos[1]); return -1; } parse->r1kh_id = pos + 2; break; case FTIE_SUBELEM_GTK: parse->gtk = pos + 2; parse->gtk_len = pos[1]; break; case FTIE_SUBELEM_R0KH_ID: if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) { wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID " "length in FTIE: %d", pos[1]); return -1; } parse->r0kh_id = pos + 2; parse->r0kh_id_len = pos[1]; break; } pos += 2 + pos[1]; } return 0;}static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse){ const u8 *end, *pos; struct wpa_ie_data data; int ret; os_memset(parse, 0, sizeof(*parse)); if (ies == NULL) return 0; pos = ies; end = ies + ies_len; while (pos + 2 <= end && pos + 2 + pos[1] <= end) { switch (pos[0]) { case WLAN_EID_RSN: parse->rsn = pos + 2; parse->rsn_len = pos[1]; ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, parse->rsn_len + 2, &data); if (ret < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse " "RSN IE: %d", ret); return -1; } if (data.num_pmkid == 1 && data.pmkid) parse->rsn_pmkid = data.pmkid; break; case WLAN_EID_MOBILITY_DOMAIN: parse->mdie = pos + 2; parse->mdie_len = pos[1]; break; case WLAN_EID_FAST_BSS_TRANSITION: if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) return -1; break; } pos += 2 + pos[1]; } return 0;}static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, int vlan_id, const char *alg, const u8 *addr, int idx, u8 *key, size_t key_len){ if (wpa_auth->cb.set_key == NULL) return -1; return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx, key, key_len);}static void wpa_ft_install_ptk(struct wpa_state_machine *sm){ char *alg; int klen; /* MLME-SETKEYS.request(PTK) */ if (sm->pairwise == WPA_CIPHER_TKIP) { alg = "TKIP"; klen = 32; } else if (sm->pairwise == WPA_CIPHER_CCMP) { alg = "CCMP"; klen = 16; } else return; /* FIX: add STA entry to kernel/driver here? The set_key will fail * most likely without this.. At the moment, STA entry is added only * after association has been completed. Alternatively, could * re-configure PTK at that point(?). */ if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, sm->PTK.tk1, klen)) return; /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE;}static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len, u8 **resp_ies, size_t *resp_ies_len){ struct rsn_mdie *mdie; struct rsn_ftie *ftie; u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN]; u8 ptk_name[WPA_PMK_NAME_LEN]; struct wpa_auth_config *conf; struct wpa_ft_ies parse; size_t buflen; int ret; u8 *pos, *end; *resp_ies = NULL; *resp_ies_len = 0; sm->pmk_r1_name_valid = 0; conf = &sm->wpa_auth->conf; wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs", ies, ies_len); if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } mdie = (struct rsn_mdie *) parse.mdie; if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || os_memcmp(mdie->mobility_domain, sm->wpa_auth->conf.mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); return WLAN_STATUS_INVALID_MDIE; } ftie = (struct rsn_ftie *) parse.ftie; if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); return WLAN_STATUS_INVALID_FTIE; } os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); if (parse.r0kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID"); return WLAN_STATUS_INVALID_FTIE; } wpa_hexdump(MSG_DEBUG, "FT: STA R0KH-ID", parse.r0kh_id, parse.r0kh_id_len); os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len); sm->r0kh_id_len = parse.r0kh_id_len; if (parse.rsn_pmkid == NULL) { wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE"); return WLAN_STATUS_INVALID_PMKID; } wpa_hexdump(MSG_DEBUG, "FT: Requested PMKR0Name", parse.rsn_pmkid, WPA_PMK_NAME_LEN); wpa_derive_pmk_r1_name(parse.rsn_pmkid, sm->wpa_auth->conf.r1_key_holder, sm->addr, pmk_r1_name); wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1) < 0) { if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id, sm->r0kh_id_len, parse.rsn_pmkid) < 0) { wpa_printf(MSG_DEBUG, "FT: Did not have matching " "PMK-R1 and unknown R0KH-ID"); return WLAN_STATUS_INVALID_PMKID; } /* * TODO: Should return "status pending" (and the caller should * not send out response now). The real response will be sent * once the response from R0KH is received. */ return WLAN_STATUS_INVALID_PMKID; } wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN); sm->pmk_r1_name_valid = 1; os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); if (os_get_random(sm->ANonce, WPA_NONCE_LEN)) { wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " "ANonce"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", sm->SNonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce", sm->ANonce, WPA_NONCE_LEN); wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, sm->wpa_auth->addr, pmk_r1_name, (u8 *) &sm->PTK, sizeof(sm->PTK), ptk_name); wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) &sm->PTK, sizeof(sm->PTK)); wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); wpa_ft_install_ptk(sm); buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + 2 + FT_R1KH_ID_LEN + 200; *resp_ies = os_zalloc(buflen); if (*resp_ies == NULL) { return WLAN_STATUS_UNSPECIFIED_FAILURE; } pos = *resp_ies; end = *resp_ies + buflen; ret = wpa_write_rsn_ie(conf, pos, end - pos, parse.rsn_pmkid); if (ret < 0) { os_free(*resp_ies); *resp_ies = NULL; return WLAN_STATUS_UNSPECIFIED_FAILURE; } pos += ret; ret = wpa_write_mdie(conf, pos, end - pos); if (ret < 0) { os_free(*resp_ies); *resp_ies = NULL; return WLAN_STATUS_UNSPECIFIED_FAILURE; } pos += ret; ret = wpa_write_ftie(conf, parse.r0kh_id, parse.r0kh_id_len, sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0); if (ret < 0) { os_free(*resp_ies); *resp_ies = NULL; return WLAN_STATUS_UNSPECIFIED_FAILURE; } pos += ret; *resp_ies_len = pos - *resp_ies; return WLAN_STATUS_SUCCESS;}void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, u16 auth_transaction, const u8 *ies, size_t ies_len, void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, u16 auth_transaction, u16 status, const u8 *ies, size_t ies_len), void *ctx){ u16 status; u8 *resp_ies; size_t resp_ies_len; if (sm == NULL) { wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but " "WPA SM not available"); return; } wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR " BSSID=" MACSTR " transaction=%d", MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction); status = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies, &resp_ies_len); wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR " auth_transaction=%d status=%d", MAC2STR(sm->addr), auth_transaction + 1, status); wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len); cb(ctx, sm->addr, bssid, auth_transaction + 1, status, resp_ies, resp_ies_len); os_free(resp_ies);}u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len){ struct wpa_ft_ies parse; struct rsn_mdie *mdie; struct rsn_ftie *ftie; u8 mic[16]; if (sm == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } if (parse.rsn == NULL) { wpa_printf(MSG_DEBUG, "FT: No RSNIE in Reassoc Req"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } if (parse.rsn_pmkid == NULL) { wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE"); return WLAN_STATUS_INVALID_PMKID; } if (os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match " "with the PMKR1Name derived from auth request"); return WLAN_STATUS_INVALID_PMKID; } mdie = (struct rsn_mdie *) parse.mdie; if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || os_memcmp(mdie->mobility_domain, sm->wpa_auth->conf.mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); return WLAN_STATUS_INVALID_MDIE; } ftie = (struct rsn_ftie *) parse.ftie; if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); return WLAN_STATUS_INVALID_FTIE; } /* * Assume that MDIE, FTIE, and RSN IE are protected and that there is * no RIC, so total of 3 protected IEs. */ if (ftie->mic_control[1] != 3) { wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)", ftie->mic_control[1]); return WLAN_STATUS_INVALID_FTIE; } if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 5, parse.mdie - 2, parse.mdie_len + 2, parse.ftie - 2, parse.ftie_len + 2, parse.rsn - 2, parse.rsn_len + 2, NULL, 0, mic) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } if (os_memcmp(mic, ftie->mic, 16) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE"); wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16); wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); return WLAN_STATUS_INVALID_FTIE; } return WLAN_STATUS_SUCCESS;}int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len){ const u8 *sta_addr, *target_ap; const u8 *ies; size_t ies_len; u8 action; struct ft_rrb_frame *frame; if (sm == NULL) return -1; /* * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6] * FT Request action frame body[variable] */ if (len < 14) { wpa_printf(MSG_DEBUG, "FT: Too short FT Action frame " "(len=%lu)", (unsigned long) len); return -1; } action = data[1]; sta_addr = data + 2; target_ap = data + 8; ies = data + 14; ies_len = len - 14; wpa_printf(MSG_DEBUG, "FT: Received FT Action frame (STA=" MACSTR " Target AP=" MACSTR " Action=%d)", MAC2STR(sta_addr), MAC2STR(target_ap), action);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?