Skip to content

Commit

Permalink
wl1271: Security sequence number handling for TX (for WPA)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Juuso Oikarinen authored and John W. Linville committed Oct 27, 2009
1 parent 3b4be9e commit ac4e4ce
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 5 deletions.
5 changes: 5 additions & 0 deletions drivers/net/wireless/wl12xx/wl1271.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
11 changes: 9 additions & 2 deletions drivers/net/wireless/wl12xx/wl1271_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/wl12xx/wl1271_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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*/
Expand Down
13 changes: 11 additions & 2 deletions drivers/net/wireless/wl12xx/wl1271_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
Expand Down Expand Up @@ -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] =
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down
11 changes: 11 additions & 0 deletions drivers/net/wireless/wl12xx/wl1271_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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)
Expand Down

0 comments on commit ac4e4ce

Please sign in to comment.