Skip to content

Commit

Permalink
ath6kl: Delay initial group key setup in AP mode
Browse files Browse the repository at this point in the history
The target is not ready to accept addkey commands until the connect
event has been delivered, so delay these operations for the initial GTK.
In addition, properly set interface connected and mark netdev ready when
the AP mode setup has been completed.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
  • Loading branch information
Jouni Malinen authored and Kalle Valo committed Aug 31, 2011
1 parent 3c774bb commit 9a5b131
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 36 deletions.
31 changes: 30 additions & 1 deletion drivers/net/wireless/ath/ath6kl/cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,26 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
key_usage, key->seq_len);

ar->def_txkey_index = key_index;

if (ar->nw_type == AP_NETWORK && !pairwise &&
(key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) {
ar->ap_mode_bkey.valid = true;
ar->ap_mode_bkey.key_index = key_index;
ar->ap_mode_bkey.key_type = key_type;
ar->ap_mode_bkey.key_len = key->key_len;
memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
if (!test_bit(CONNECTED, &ar->flag)) {
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
"key configuration until AP mode has been "
"started\n");
/*
* The key will be set in ath6kl_connect_ap_mode() once
* the connected event is received from the target.
*/
return 0;
}
}

status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
key_type, key_usage, key->key_len,
key->seq, key->key, KEY_OP_INIT_VAL,
Expand Down Expand Up @@ -997,6 +1017,9 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
if (ar->prwise_crypto == WEP_CRYPT)
key_usage |= TX_USAGE;

if (ar->nw_type == AP_NETWORK && !test_bit(CONNECTED, &ar->flag))
return 0; /* Delay until AP mode has been started */

status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
ar->prwise_crypto, key_usage,
key->key_len, key->seq, key->key,
Expand Down Expand Up @@ -1495,6 +1518,8 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
if (!add)
return 0;

ar->ap_mode_bkey.valid = false;

/* TODO:
* info->interval
* info->dtim_period
Expand Down Expand Up @@ -1580,7 +1605,11 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
p.dot11_auth_mode = ar->dot11_auth_mode;
p.ch = cpu_to_le16(ar->next_chan);

return ath6kl_wmi_ap_profile_commit(ar->wmi, &p);
res = ath6kl_wmi_ap_profile_commit(ar->wmi, &p);
if (res < 0)
return res;

return 0;
}

static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev,
Expand Down
25 changes: 6 additions & 19 deletions drivers/net/wireless/ath/ath6kl/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,26 +335,13 @@ struct ath6kl_mbox_info {
#define ATH6KL_KEY_RECV 0x02
#define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */

/*
* WPA/RSN get/set key request. Specify the key/cipher
* type and whether the key is to be used for sending and/or
* receiving. The key index should be set only when working
* with global keys (use IEEE80211_KEYIX_NONE for ``no index'').
* Otherwise a unicast/pairwise key is specified by the bssid
* (on a station) or mac address (on an ap). They key length
* must include any MIC key data; otherwise it should be no
* more than ATH6KL_KEYBUF_SIZE.
*/
/* Initial group key for AP mode */
struct ath6kl_req_key {
u8 ik_type; /* key/cipher type */
u8 ik_pad;
u16 ik_keyix; /* key index */
u8 ik_keylen; /* key length in bytes */
u8 ik_flags;
u8 ik_macaddr[ETH_ALEN];
u64 ik_keyrsc; /* key receive sequence counter */
u64 ik_keytsc; /* key transmit sequence counter */
u8 ik_keydata[ATH6KL_KEYBUF_SIZE + ATH6KL_MICBUF_SIZE];
bool valid;
u8 key_index;
int key_type;
u8 key[WLAN_MAX_KEY_LEN];
u8 key_len;
};

/* Flag info */
Expand Down
36 changes: 20 additions & 16 deletions drivers/net/wireless/ath/ath6kl/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,11 +437,15 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
size_t ies_len = 0;
struct station_info sinfo;
struct ath6kl_req_key *ik;
enum crypto_type keyType = NONE_CRYPT;
int res;
u8 key_rsc[ATH6KL_KEY_SEQ_LEN];

if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) {
ik = &ar->ap_mode_bkey;

ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n",
channel);

switch (ar->auth_mode) {
case NONE_AUTH:
if (ar->prwise_crypto == WEP_CRYPT)
Expand All @@ -450,26 +454,26 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
case WPA_PSK_AUTH:
case WPA2_PSK_AUTH:
case (WPA_PSK_AUTH|WPA2_PSK_AUTH):
switch (ik->ik_type) {
case ATH6KL_CIPHER_TKIP:
keyType = TKIP_CRYPT;
break;
case ATH6KL_CIPHER_AES_CCM:
keyType = AES_CRYPT;
if (!ik->valid)
break;
default:
goto skip_key;

ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
"the initial group key for AP mode\n");
memset(key_rsc, 0, sizeof(key_rsc));
res = ath6kl_wmi_addkey_cmd(
ar->wmi, ik->key_index, ik->key_type,
GROUP_USAGE, ik->key_len, key_rsc, ik->key,
KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
if (res) {
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
"addkey failed: %d\n", res);
}
ath6kl_wmi_addkey_cmd(ar->wmi, ik->ik_keyix, keyType,
GROUP_USAGE, ik->ik_keylen,
(u8 *)&ik->ik_keyrsc,
ik->ik_keydata,
KEY_OP_INIT_VAL, ik->ik_macaddr,
SYNC_BOTH_WMIFLAG);
break;
}
skip_key:

ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
set_bit(CONNECTED, &ar->flag);
netif_carrier_on(ar->net_dev);
return;
}

Expand Down
4 changes: 4 additions & 0 deletions drivers/net/wireless/ath/ath6kl/wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1764,6 +1764,10 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
struct wmi_add_cipher_key_cmd *cmd;
int ret;

ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d "
"key_usage=%d key_len=%d key_op_ctrl=%d\n",
key_index, key_type, key_usage, key_len, key_op_ctrl);

if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) ||
(key_material == NULL))
return -EINVAL;
Expand Down

0 comments on commit 9a5b131

Please sign in to comment.