Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 111203
b: refs/heads/master
c: 2bb057d
h: refs/heads/master
i:
  111201: 254e94a
  111199: f7002c5
v: v3
  • Loading branch information
Ivo van Doorn authored and John W. Linville committed Aug 22, 2008
1 parent bc62a9e commit 149b002
Show file tree
Hide file tree
Showing 12 changed files with 687 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8e7cdbb6333ef7654e708bd60e50a123688dcd7b
refs/heads/master: 2bb057d07a0bc17475a7bf897fc41667ab08b73f
4 changes: 4 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ config RT2X00_LIB_FIRMWARE
depends on RT2X00_LIB
select FW_LOADER

config RT2X00_LIB_CRYPTO
boolean
depends on RT2X00_LIB

config RT2X00_LIB_RFKILL
boolean
depends on RT2X00_LIB
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/rt2x00/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ rt2x00lib-y += rt2x00mac.o
rt2x00lib-y += rt2x00config.o
rt2x00lib-y += rt2x00queue.o
rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o
rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
Expand Down
39 changes: 37 additions & 2 deletions trunk/drivers/net/wireless/rt2x00/rt2x00.h
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,23 @@ struct rt2x00lib_erp {
int ack_consume_time;
};

/*
* Configuration structure for hardware encryption.
*/
struct rt2x00lib_crypto {
enum cipher cipher;

enum set_key_cmd cmd;
const u8 *address;

u32 bssidx;
u32 aid;

u8 key[16];
u8 tx_mic[8];
u8 rx_mic[8];
};

/*
* Configuration structure wrapper around the
* rt2x00 interface configuration handler.
Expand Down Expand Up @@ -547,6 +564,12 @@ struct rt2x00lib_ops {
/*
* Configuration handlers.
*/
int (*config_shared_key) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
int (*config_pairwise_key) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
void (*config_filter) (struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void (*config_intf) (struct rt2x00_dev *rt2x00dev,
Expand Down Expand Up @@ -609,7 +632,7 @@ enum rt2x00_flags {
DEVICE_DIRTY_CONFIG,

/*
* Driver features
* Driver requirements
*/
DRIVER_REQUIRE_FIRMWARE,
DRIVER_REQUIRE_BEACON_GUARD,
Expand All @@ -618,9 +641,14 @@ enum rt2x00_flags {
DRIVER_REQUIRE_DMA,

/*
* Driver configuration
* Driver features
*/
CONFIG_SUPPORT_HW_BUTTON,
CONFIG_SUPPORT_HW_CRYPTO,

/*
* Driver configuration
*/
CONFIG_FRAME_TYPE,
CONFIG_RF_SEQUENCE,
CONFIG_EXTERNAL_LNA_A,
Expand Down Expand Up @@ -966,6 +994,13 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list);
#ifdef CONFIG_RT2X00_LIB_CRYPTO
int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_address, const u8 *address,
struct ieee80211_key_conf *key);
#else
#define rt2x00mac_set_key NULL
#endif /* CONFIG_RT2X00_LIB_CRYPTO */
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
Expand Down
215 changes: 215 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2x00crypto.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/*
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

/*
Module: rt2x00lib
Abstract: rt2x00 crypto specific routines.
*/

#include <linux/kernel.h>
#include <linux/module.h>

#include "rt2x00.h"
#include "rt2x00lib.h"

enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
{
switch (key->alg) {
case ALG_WEP:
if (key->keylen == LEN_WEP40)
return CIPHER_WEP64;
else
return CIPHER_WEP128;
case ALG_TKIP:
return CIPHER_TKIP;
case ALG_CCMP:
return CIPHER_AES;
default:
return CIPHER_NONE;
}
}

unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
{
struct ieee80211_key_conf *key = tx_info->control.hw_key;
unsigned int overhead = 0;

/*
* Extend frame length to include IV/EIV/ICV/MMIC,
* note that these lengths should only be added when
* mac80211 does not generate it.
*/
overhead += tx_info->control.icv_len;

if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
overhead += tx_info->control.iv_len;

if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
if (key->alg == ALG_TKIP)
overhead += 8;
}

return overhead;
}

void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);

if (unlikely(!iv_len))
return;

/* Copy IV/EIV data */
if (iv_len >= 4)
memcpy(&skbdesc->iv, skb->data + header_length, 4);
if (iv_len >= 8)
memcpy(&skbdesc->eiv, skb->data + header_length + 4, 4);

/* Move ieee80211 header */
memmove(skb->data + iv_len, skb->data, header_length);

/* Pull buffer to correct size */
skb_pull(skb, iv_len);

/* IV/EIV data has officially be stripped */
skbdesc->flags |= FRAME_DESC_IV_STRIPPED;
}

void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
const unsigned int iv_len =
((!!(skbdesc->iv)) * 4) + ((!!(skbdesc->eiv)) * 4);

if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED))
return;

skb_push(skb, iv_len);

/* Move ieee80211 header */
memmove(skb->data, skb->data + iv_len, header_length);

/* Copy IV/EIV data */
if (iv_len >= 4)
memcpy(skb->data + header_length, &skbdesc->iv, 4);
if (iv_len >= 8)
memcpy(skb->data + header_length + 4, &skbdesc->eiv, 4);

/* IV/EIV data has returned into the frame */
skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED;
}

void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
unsigned int header_length,
struct rxdone_entry_desc *rxdesc)
{
unsigned int payload_len = rxdesc->size - header_length;
unsigned int iv_len;
unsigned int icv_len;
unsigned int transfer = 0;

/*
* WEP64/WEP128: Provides IV & ICV
* TKIP: Provides IV/EIV & ICV
* AES: Provies IV/EIV & ICV
*/
switch (rxdesc->cipher) {
case CIPHER_WEP64:
case CIPHER_WEP128:
iv_len = 4;
icv_len = 4;
break;
case CIPHER_TKIP:
iv_len = 8;
icv_len = 4;
break;
case CIPHER_AES:
iv_len = 8;
icv_len = 8;
break;
default:
/* Unsupport type */
return;
}

/*
* Make room for new data, note that we increase both
* headsize and tailsize when required. The tailsize is
* only needed when ICV data needs to be inserted and
* the padding is smaller then the ICV data.
* When alignment requirements is greater then the
* ICV data we must trim the skb to the correct size
* because we need to remove the extra bytes.
*/
skb_push(skb, iv_len + align);
if (align < icv_len)
skb_put(skb, icv_len - align);
else if (align > icv_len)
skb_trim(skb, rxdesc->size + iv_len + icv_len);

/* Move ieee80211 header */
memmove(skb->data + transfer,
skb->data + transfer + iv_len + align,
header_length);
transfer += header_length;

/* Copy IV data */
if (iv_len >= 4) {
memcpy(skb->data + transfer, &rxdesc->iv, 4);
transfer += 4;
}

/* Copy EIV data */
if (iv_len >= 8) {
memcpy(skb->data + transfer, &rxdesc->eiv, 4);
transfer += 4;
}

/* Move payload */
if (align) {
memmove(skb->data + transfer,
skb->data + transfer + align,
payload_len);
}

/*
* NOTE: Always count the payload as transfered,
* even when alignment was set to zero. This is required
* for determining the correct offset for the ICV data.
*/
transfer += payload_len;

/* Copy ICV data */
if (icv_len >= 4) {
memcpy(skb->data + transfer, &rxdesc->icv, 4);
/*
* AES appends 8 bytes, we can't fill the upper
* 4 bytes, but mac80211 doesn't care about what
* we provide here anyway and strips it immediately.
*/
transfer += icv_len;
}

/* IV/EIV/ICV has been inserted into frame */
rxdesc->size = transfer;
rxdesc->flags &= ~RX_FLAG_IV_STRIPPED;
}
Loading

0 comments on commit 149b002

Please sign in to comment.