summaryrefslogtreecommitdiff
path: root/src/rsn_supp/wpa_ft.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rsn_supp/wpa_ft.c')
-rw-r--r--src/rsn_supp/wpa_ft.c264
1 files changed, 28 insertions, 236 deletions
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 23063bc2d472b..2df060ca87eb7 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -2,53 +2,22 @@
* WPA Supplicant - IEEE 802.11r - Fast BSS Transition
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "crypto/aes_wrap.h"
+#include "crypto/random.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "wpa.h"
#include "wpa_i.h"
-#include "wpa_ie.h"
#ifdef CONFIG_IEEE80211R
-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;
- const u8 *tie;
- size_t tie_len;
- const u8 *igtk;
- size_t igtk_len;
- const u8 *ric;
- size_t ric_len;
-};
-
-static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
- struct wpa_ft_ies *parse);
-
-
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
const struct wpa_eapol_key *key,
struct wpa_ptk *ptk, size_t ptk_len)
@@ -202,16 +171,16 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
pos = (u8 *) (rsnie + 1);
/* Group Suite Selector */
- if (sm->group_cipher == WPA_CIPHER_CCMP)
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
- else if (sm->group_cipher == WPA_CIPHER_TKIP)
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
- else {
+ if (sm->group_cipher != WPA_CIPHER_CCMP &&
+ sm->group_cipher != WPA_CIPHER_GCMP &&
+ sm->group_cipher != WPA_CIPHER_TKIP) {
wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
sm->group_cipher);
os_free(buf);
return NULL;
}
+ RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+ sm->group_cipher));
pos += RSN_SELECTOR_LEN;
/* Pairwise Suite Count */
@@ -219,16 +188,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
pos += 2;
/* Pairwise Suite List */
- if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
- else if (sm->pairwise_cipher == WPA_CIPHER_TKIP)
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
- else {
+ if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
sm->pairwise_cipher);
os_free(buf);
return NULL;
}
+ RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+ sm->pairwise_cipher));
pos += RSN_SELECTOR_LEN;
/* Authenticated Key Management Suite Count */
@@ -346,155 +313,6 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
}
-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;
-#ifdef CONFIG_IEEE80211W
- case FTIE_SUBELEM_IGTK:
- parse->igtk = pos + 2;
- parse->igtk_len = pos[1];
- break;
-#endif /* CONFIG_IEEE80211W */
- }
-
- 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;
- const struct rsn_ftie *ftie;
- int prot_ie_count = 0;
-
- 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 (pos[1] < sizeof(*ftie))
- return -1;
- ftie = (const struct rsn_ftie *) (pos + 2);
- prot_ie_count = ftie->mic_control[1];
- if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
- return -1;
- break;
- case WLAN_EID_TIMEOUT_INTERVAL:
- parse->tie = pos + 2;
- parse->tie_len = pos[1];
- break;
- case WLAN_EID_RIC_DATA:
- if (parse->ric == NULL)
- parse->ric = pos;
- }
-
- pos += 2 + pos[1];
- }
-
- if (prot_ie_count == 0)
- return 0; /* no MIC */
-
- /*
- * Check that the protected IE count matches with IEs included in the
- * frame.
- */
- if (parse->rsn)
- prot_ie_count--;
- if (parse->mdie)
- prot_ie_count--;
- if (parse->ftie)
- prot_ie_count--;
- if (parse->tie)
- prot_ie_count--;
- if (prot_ie_count < 0) {
- wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
- "the protected IE count");
- return -1;
- }
-
- if (prot_ie_count == 0 && parse->ric) {
- wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
- "included in protected IE count");
- return -1;
- }
-
- /* Determine the end of the RIC IE(s) */
- pos = parse->ric;
- while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
- prot_ie_count) {
- prot_ie_count--;
- pos += 2 + pos[1];
- }
- parse->ric_len = pos - parse->ric;
- if (prot_ie_count) {
- wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
- "frame", (int) prot_ie_count);
- return -1;
- }
-
- return 0;
-}
-
-
static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
{
int keylen;
@@ -503,21 +321,15 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");
- switch (sm->pairwise_cipher) {
- case WPA_CIPHER_CCMP:
- alg = WPA_ALG_CCMP;
- keylen = 16;
- break;
- case WPA_CIPHER_TKIP:
- alg = WPA_ALG_TKIP;
- keylen = 32;
- break;
- default:
+ if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d",
sm->pairwise_cipher);
return -1;
}
+ alg = wpa_cipher_to_alg(sm->pairwise_cipher);
+ keylen = wpa_cipher_key_len(sm->pairwise_cipher);
+
if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc,
sizeof(null_rsc), (u8 *) sm->ptk.tk1, keylen) < 0) {
wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
@@ -540,7 +352,7 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie)
size_t ft_ies_len;
/* Generate a new SNonce */
- if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {
+ if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
return -1;
}
@@ -663,7 +475,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
bssid = target_ap;
- ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64;
+ ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64;
wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr,
bssid, sm->pmk_r1_name,
(u8 *) &sm->ptk, ptk_len, ptk_name);
@@ -751,28 +563,10 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
return -1;
}
- switch (sm->group_cipher) {
- case WPA_CIPHER_CCMP:
- keylen = 16;
- rsc_len = 6;
- alg = WPA_ALG_CCMP;
- break;
- case WPA_CIPHER_TKIP:
- keylen = 32;
- rsc_len = 6;
- alg = WPA_ALG_TKIP;
- break;
- case WPA_CIPHER_WEP104:
- keylen = 13;
- rsc_len = 0;
- alg = WPA_ALG_WEP;
- break;
- case WPA_CIPHER_WEP40:
- keylen = 5;
- rsc_len = 0;
- alg = WPA_ALG_WEP;
- break;
- default:
+ keylen = wpa_cipher_key_len(sm->group_cipher);
+ rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
+ alg = wpa_cipher_to_alg(sm->group_cipher);
+ if (alg == WPA_ALG_NONE) {
wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
sm->group_cipher);
return -1;
@@ -795,9 +589,8 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
}
wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
- if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
- keyidx, 0, gtk_elem + 3, rsc_len, gtk, keylen) <
- 0) {
+ if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
+ gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
"driver.");
return -1;
@@ -848,9 +641,8 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
WPA_IGTK_LEN);
- if (wpa_sm_set_key(sm, WPA_ALG_IGTK, (u8 *) "\xff\xff\xff\xff\xff\xff",
- keyidx, 0, igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) <
- 0) {
+ if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0,
+ igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) {
wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
"driver.");
return -1;
@@ -951,8 +743,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
}
count = 3;
- if (parse.tie)
- count++;
+ if (parse.ric)
+ count += ieee802_11_ie_count(parse.ric, parse.ric_len);
if (ftie->mic_control[1] != count) {
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
"Control: received %u expected %u",
@@ -1020,7 +812,7 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
MAC2STR(target_ap));
/* Generate a new SNonce */
- if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {
+ if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
return -1;
}