wl1271: Security sequence number handling for TX (for WPA)

Add security sequence number handling to the driver TX data path needed
by WPA.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Juuso Oikarinen 2009-10-08 21:56:19 +03:00 committed by John W. Linville
parent 3b4be9e08a
commit ac4e4ce54e
5 changed files with 38 additions and 5 deletions

View file

@ -337,6 +337,11 @@ struct wl1271 {
/* Pending TX frames */
struct sk_buff *tx_frames[16];
/* Security sequence number counters */
u8 tx_security_last_seq;
u16 tx_security_seq_16;
u32 tx_security_seq_32;
/* FW Rx counter */
u32 rx_counter;

View file

@ -228,6 +228,10 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
/* reset TX security counters */
wl->tx_security_last_seq = 0;
wl->tx_security_seq_16 = 0;
wl->tx_security_seq_32 = 0;
ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
if (ret < 0) {
@ -759,7 +763,8 @@ int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
}
int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr)
u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16)
{
struct wl1271_cmd_set_keys *cmd;
int ret = 0;
@ -777,12 +782,14 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
cmd->key_size = key_size;
cmd->key_type = key_type;
cmd->ac_seq_num16[0] = tx_seq_16;
cmd->ac_seq_num32[0] = tx_seq_32;
/* we have only one SSID profile */
cmd->ssid_profile = 0;
cmd->id = id;
/* FIXME: this is from wl1251, needs to be checked */
if (key_type == KEY_TKIP) {
/*
* We get the key in the following form:

View file

@ -49,7 +49,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len);
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr);
u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16);
enum wl1271_commands {
CMD_INTERROGATE = 1, /*use this to read information elements*/

View file

@ -592,6 +592,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->tx_blocks_available = 0;
wl->tx_results_count = 0;
wl->tx_packets_count = 0;
wl->tx_security_last_seq = 0;
wl->tx_security_seq_16 = 0;
wl->tx_security_seq_32 = 0;
wl->time_offset = 0;
wl->session_counter = 0;
for (i = 0; i < NUM_TX_QUEUES; i++)
@ -823,6 +826,8 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct wl1271 *wl = hw->priv;
const u8 *addr;
int ret;
u32 tx_seq_32 = 0;
u16 tx_seq_16 = 0;
u8 key_type;
static const u8 bcast_addr[ETH_ALEN] =
@ -861,11 +866,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
key_type = KEY_TKIP;
key_conf->hw_key_idx = key_conf->keyidx;
tx_seq_32 = wl->tx_security_seq_32;
tx_seq_16 = wl->tx_security_seq_16;
break;
case ALG_CCMP:
key_type = KEY_AES;
key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
tx_seq_32 = wl->tx_security_seq_32;
tx_seq_16 = wl->tx_security_seq_16;
break;
default:
wl1271_error("Unknown key algo 0x%x", key_conf->alg);
@ -879,7 +888,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
key_conf->keyidx, key_type,
key_conf->keylen, key_conf->key,
addr);
addr, tx_seq_32, tx_seq_16);
if (ret < 0) {
wl1271_error("Could not add or replace key");
goto out_sleep;
@ -890,7 +899,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
key_conf->keyidx, key_type,
key_conf->keylen, key_conf->key,
addr);
addr, 0, 0);
if (ret < 0) {
wl1271_error("Could not remove key");
goto out_sleep;

View file

@ -258,6 +258,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
struct ieee80211_tx_info *info;
struct sk_buff *skb;
u32 header_len;
u16 seq;
int id = result->id;
/* check for id legality */
@ -284,6 +285,16 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
/* info->status.retry_count = result->ack_failures; */
wl->stats.retry_count += result->ack_failures;
/* update security sequence number */
seq = wl->tx_security_seq_16 +
(result->lsb_security_sequence_number -
wl->tx_security_last_seq);
wl->tx_security_last_seq = result->lsb_security_sequence_number;
if (seq < wl->tx_security_seq_16)
wl->tx_security_seq_32++;
wl->tx_security_seq_16 = seq;
/* get header len */
if (info->control.hw_key &&
info->control.hw_key->alg == ALG_TKIP)