0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015
0016 #include "rt2x00.h"
0017 #include "rt2x00lib.h"
0018
0019 enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
0020 {
0021 switch (key->cipher) {
0022 case WLAN_CIPHER_SUITE_WEP40:
0023 return CIPHER_WEP64;
0024 case WLAN_CIPHER_SUITE_WEP104:
0025 return CIPHER_WEP128;
0026 case WLAN_CIPHER_SUITE_TKIP:
0027 return CIPHER_TKIP;
0028 case WLAN_CIPHER_SUITE_CCMP:
0029 return CIPHER_AES;
0030 default:
0031 return CIPHER_NONE;
0032 }
0033 }
0034
0035 void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
0036 struct sk_buff *skb,
0037 struct txentry_desc *txdesc)
0038 {
0039 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
0040 struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
0041
0042 if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !hw_key)
0043 return;
0044
0045 __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
0046
0047 txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key);
0048
0049 if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
0050 __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
0051
0052 txdesc->key_idx = hw_key->hw_key_idx;
0053 txdesc->iv_offset = txdesc->header_length;
0054 txdesc->iv_len = hw_key->iv_len;
0055
0056 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
0057 __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);
0058
0059 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
0060 __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags);
0061 }
0062
0063 unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
0064 struct sk_buff *skb)
0065 {
0066 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
0067 struct ieee80211_key_conf *key = tx_info->control.hw_key;
0068 unsigned int overhead = 0;
0069
0070 if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !key)
0071 return overhead;
0072
0073
0074
0075
0076
0077
0078 overhead += key->icv_len;
0079
0080 if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
0081 overhead += key->iv_len;
0082
0083 if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
0084 if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
0085 overhead += 8;
0086 }
0087
0088 return overhead;
0089 }
0090
0091 void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
0092 {
0093 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
0094
0095 if (unlikely(!txdesc->iv_len))
0096 return;
0097
0098
0099 memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
0100 }
0101
0102 void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
0103 {
0104 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
0105
0106 if (unlikely(!txdesc->iv_len))
0107 return;
0108
0109
0110 memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
0111
0112
0113 memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset);
0114
0115
0116 skb_pull(skb, txdesc->iv_len);
0117 txdesc->length -= txdesc->iv_len;
0118
0119
0120 skbdesc->flags |= SKBDESC_IV_STRIPPED;
0121 }
0122
0123 void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
0124 {
0125 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
0126 const unsigned int iv_len =
0127 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
0128
0129 if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
0130 return;
0131
0132 skb_push(skb, iv_len);
0133
0134
0135 memmove(skb->data, skb->data + iv_len, header_length);
0136
0137
0138 memcpy(skb->data + header_length, skbdesc->iv, iv_len);
0139
0140
0141 skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
0142 }
0143
0144 void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
0145 unsigned int header_length,
0146 struct rxdone_entry_desc *rxdesc)
0147 {
0148 unsigned int payload_len = rxdesc->size - header_length;
0149 unsigned int align = ALIGN_SIZE(skb, header_length);
0150 unsigned int iv_len;
0151 unsigned int icv_len;
0152 unsigned int transfer = 0;
0153
0154
0155
0156
0157
0158
0159 switch (rxdesc->cipher) {
0160 case CIPHER_WEP64:
0161 case CIPHER_WEP128:
0162 iv_len = 4;
0163 icv_len = 4;
0164 break;
0165 case CIPHER_TKIP:
0166 iv_len = 8;
0167 icv_len = 4;
0168 break;
0169 case CIPHER_AES:
0170 iv_len = 8;
0171 icv_len = 8;
0172 break;
0173 default:
0174
0175 return;
0176 }
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189 if (rxdesc->dev_flags & RXDONE_L2PAD) {
0190 skb_push(skb, iv_len - align);
0191 skb_put(skb, icv_len);
0192
0193
0194 memmove(skb->data + transfer,
0195 skb->data + transfer + (iv_len - align),
0196 header_length);
0197 transfer += header_length;
0198 } else {
0199 skb_push(skb, iv_len + align);
0200 if (align < icv_len)
0201 skb_put(skb, icv_len - align);
0202 else if (align > icv_len)
0203 skb_trim(skb, rxdesc->size + iv_len + icv_len);
0204
0205
0206 memmove(skb->data + transfer,
0207 skb->data + transfer + iv_len + align,
0208 header_length);
0209 transfer += header_length;
0210 }
0211
0212
0213 memcpy(skb->data + transfer, rxdesc->iv, iv_len);
0214 transfer += iv_len;
0215
0216
0217
0218
0219
0220 if (!(rxdesc->dev_flags & RXDONE_L2PAD)) {
0221 memmove(skb->data + transfer,
0222 skb->data + transfer + align,
0223 payload_len);
0224 }
0225
0226
0227
0228
0229
0230
0231 transfer += payload_len;
0232
0233
0234
0235
0236
0237
0238
0239 memcpy(skb->data + transfer, &rxdesc->icv, 4);
0240 transfer += icv_len;
0241
0242
0243 rxdesc->size = transfer;
0244 rxdesc->flags &= ~RX_FLAG_IV_STRIPPED;
0245 }