diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2010-01-16 19:47:58 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-19 16:25:19 -0500 |
commit | 813d76694043d00b59475baa1fbfaf54a2eb7fad (patch) | |
tree | daad130ca0a9e90f7616d88e5433654df89af14a | |
parent | a6bae9e7ab19876a157c91019852395539e4f20e (diff) |
mac80211: move control.hw_key assignment
When mac80211 asks a driver to encrypt a frame, it
must assign the control.hw_key pointer for it to
know which key to use etc. Currently, mac80211 does
this whenever it would software-encrypt a frame.
Change the logic of this code to assign the hw_key
pointer when selecting the key, and later check it
when deciding whether to encrypt the frame or let
it be encrypted by the hardware. This allows us to
later simply skip the encryption function since it
no longer modifies the TX control.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/mac80211/tkip.c | 11 | ||||
-rw-r--r-- | net/mac80211/tx.c | 9 | ||||
-rw-r--r-- | net/mac80211/wep.c | 18 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 57 |
4 files changed, 46 insertions, 49 deletions
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index b73454a507f9..14fe49332c02 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -195,11 +195,13 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
195 | } | 195 | } |
196 | EXPORT_SYMBOL(ieee80211_get_tkip_key); | 196 | EXPORT_SYMBOL(ieee80211_get_tkip_key); |
197 | 197 | ||
198 | /* Encrypt packet payload with TKIP using @key. @pos is a pointer to the | 198 | /* |
199 | * Encrypt packet payload with TKIP using @key. @pos is a pointer to the | ||
199 | * beginning of the buffer containing payload. This payload must include | 200 | * beginning of the buffer containing payload. This payload must include |
200 | * headroom of eight octets for IV and Ext. IV and taildroom of four octets | 201 | * the IV/Ext.IV and space for (taildroom) four octets for ICV. |
201 | * for ICV. @payload_len is the length of payload (_not_ including extra | 202 | * @payload_len is the length of payload (_not_ including IV/ICV length). |
202 | * headroom and tailroom). @ta is the transmitter addresses. */ | 203 | * @ta is the transmitter addresses. |
204 | */ | ||
203 | void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | 205 | void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, |
204 | struct ieee80211_key *key, | 206 | struct ieee80211_key *key, |
205 | u8 *pos, size_t payload_len, u8 *ta) | 207 | u8 *pos, size_t payload_len, u8 *ta) |
@@ -214,7 +216,6 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | |||
214 | 216 | ||
215 | tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); | 217 | tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); |
216 | 218 | ||
217 | pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); | ||
218 | ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); | 219 | ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); |
219 | } | 220 | } |
220 | 221 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9afbee0d53c0..e3d8ff533ee6 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -529,6 +529,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
529 | tx->key = NULL; | 529 | tx->key = NULL; |
530 | 530 | ||
531 | if (tx->key) { | 531 | if (tx->key) { |
532 | bool skip_hw = false; | ||
533 | |||
532 | tx->key->tx_rx_count++; | 534 | tx->key->tx_rx_count++; |
533 | /* TODO: add threshold stuff again */ | 535 | /* TODO: add threshold stuff again */ |
534 | 536 | ||
@@ -545,12 +547,19 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
545 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, | 547 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, |
546 | tx->skb)) | 548 | tx->skb)) |
547 | tx->key = NULL; | 549 | tx->key = NULL; |
550 | skip_hw = (tx->key->conf.flags & | ||
551 | IEEE80211_KEY_FLAG_SW_MGMT) && | ||
552 | ieee80211_is_mgmt(hdr->frame_control); | ||
548 | break; | 553 | break; |
549 | case ALG_AES_CMAC: | 554 | case ALG_AES_CMAC: |
550 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 555 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
551 | tx->key = NULL; | 556 | tx->key = NULL; |
552 | break; | 557 | break; |
553 | } | 558 | } |
559 | |||
560 | if (!skip_hw && | ||
561 | tx->key->conf.flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | ||
562 | info->control.hw_key = &tx->key->conf; | ||
554 | } | 563 | } |
555 | 564 | ||
556 | return TX_CONTINUE; | 565 | return TX_CONTINUE; |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 247123fe1a7a..0a4c641c9605 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -305,20 +305,20 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
305 | { | 305 | { |
306 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 306 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
307 | 307 | ||
308 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { | 308 | if (!info->control.hw_key) { |
309 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, | 309 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, |
310 | tx->key->conf.keylen, | 310 | tx->key->conf.keylen, |
311 | tx->key->conf.keyidx)) | 311 | tx->key->conf.keyidx)) |
312 | return -1; | 312 | return -1; |
313 | } else { | ||
314 | info->control.hw_key = &tx->key->conf; | ||
315 | if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) { | ||
316 | if (!ieee80211_wep_add_iv(tx->local, skb, | ||
317 | tx->key->conf.keylen, | ||
318 | tx->key->conf.keyidx)) | ||
319 | return -1; | ||
320 | } | ||
321 | } | 313 | } |
314 | |||
315 | if (info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) { | ||
316 | if (!ieee80211_wep_add_iv(tx->local, skb, | ||
317 | tx->key->conf.keylen, | ||
318 | tx->key->conf.keyidx)) | ||
319 | return -1; | ||
320 | } | ||
321 | |||
322 | return 0; | 322 | return 0; |
323 | } | 323 | } |
324 | 324 | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 5332014cb229..f4971cd45c64 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -31,8 +31,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
31 | unsigned int hdrlen; | 31 | unsigned int hdrlen; |
32 | struct ieee80211_hdr *hdr; | 32 | struct ieee80211_hdr *hdr; |
33 | struct sk_buff *skb = tx->skb; | 33 | struct sk_buff *skb = tx->skb; |
34 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
34 | int authenticator; | 35 | int authenticator; |
35 | int wpa_test = 0; | ||
36 | int tail; | 36 | int tail; |
37 | 37 | ||
38 | hdr = (struct ieee80211_hdr *)skb->data; | 38 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -47,16 +47,15 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
47 | data = skb->data + hdrlen; | 47 | data = skb->data + hdrlen; |
48 | data_len = skb->len - hdrlen; | 48 | data_len = skb->len - hdrlen; |
49 | 49 | ||
50 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 50 | if (info->control.hw_key && |
51 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && | 51 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && |
52 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && | 52 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
53 | !wpa_test) { | 53 | /* hwaccel - with no need for SW-generated MMIC */ |
54 | /* hwaccel - with no need for preallocated room for MMIC */ | ||
55 | return TX_CONTINUE; | 54 | return TX_CONTINUE; |
56 | } | 55 | } |
57 | 56 | ||
58 | tail = MICHAEL_MIC_LEN; | 57 | tail = MICHAEL_MIC_LEN; |
59 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 58 | if (!info->control.hw_key) |
60 | tail += TKIP_ICV_LEN; | 59 | tail += TKIP_ICV_LEN; |
61 | 60 | ||
62 | if (WARN_ON(skb_tailroom(skb) < tail || | 61 | if (WARN_ON(skb_tailroom(skb) < tail || |
@@ -147,17 +146,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
147 | int len, tail; | 146 | int len, tail; |
148 | u8 *pos; | 147 | u8 *pos; |
149 | 148 | ||
150 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 149 | if (info->control.hw_key && |
151 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 150 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
152 | /* hwaccel - with no need for preallocated room for IV/ICV */ | 151 | /* hwaccel - with no need for software-generated IV */ |
153 | info->control.hw_key = &tx->key->conf; | ||
154 | return 0; | 152 | return 0; |
155 | } | 153 | } |
156 | 154 | ||
157 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 155 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
158 | len = skb->len - hdrlen; | 156 | len = skb->len - hdrlen; |
159 | 157 | ||
160 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 158 | if (info->control.hw_key) |
161 | tail = 0; | 159 | tail = 0; |
162 | else | 160 | else |
163 | tail = TKIP_ICV_LEN; | 161 | tail = TKIP_ICV_LEN; |
@@ -175,13 +173,11 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
175 | if (key->u.tkip.tx.iv16 == 0) | 173 | if (key->u.tkip.tx.iv16 == 0) |
176 | key->u.tkip.tx.iv32++; | 174 | key->u.tkip.tx.iv32++; |
177 | 175 | ||
178 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 176 | pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); |
179 | /* hwaccel - with preallocated room for IV */ | ||
180 | ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); | ||
181 | 177 | ||
182 | info->control.hw_key = &tx->key->conf; | 178 | /* hwaccel - with software IV */ |
179 | if (info->control.hw_key) | ||
183 | return 0; | 180 | return 0; |
184 | } | ||
185 | 181 | ||
186 | /* Add room for ICV */ | 182 | /* Add room for ICV */ |
187 | skb_put(skb, TKIP_ICV_LEN); | 183 | skb_put(skb, TKIP_ICV_LEN); |
@@ -363,24 +359,20 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
363 | int hdrlen, len, tail; | 359 | int hdrlen, len, tail; |
364 | u8 *pos, *pn; | 360 | u8 *pos, *pn; |
365 | int i; | 361 | int i; |
366 | bool skip_hw; | ||
367 | |||
368 | skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) && | ||
369 | ieee80211_is_mgmt(hdr->frame_control); | ||
370 | 362 | ||
371 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 363 | if (info->control.hw_key && |
372 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && | 364 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
373 | !skip_hw) { | 365 | /* |
374 | /* hwaccel - with no need for preallocated room for CCMP | 366 | * hwaccel has no need for preallocated room for CCMP |
375 | * header or MIC fields */ | 367 | * header or MIC fields |
376 | info->control.hw_key = &tx->key->conf; | 368 | */ |
377 | return 0; | 369 | return 0; |
378 | } | 370 | } |
379 | 371 | ||
380 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 372 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
381 | len = skb->len - hdrlen; | 373 | len = skb->len - hdrlen; |
382 | 374 | ||
383 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 375 | if (info->control.hw_key) |
384 | tail = 0; | 376 | tail = 0; |
385 | else | 377 | else |
386 | tail = CCMP_MIC_LEN; | 378 | tail = CCMP_MIC_LEN; |
@@ -405,11 +397,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
405 | 397 | ||
406 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); | 398 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
407 | 399 | ||
408 | if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) { | 400 | /* hwaccel - with software CCMP header */ |
409 | /* hwaccel - with preallocated room for CCMP header */ | 401 | if (info->control.hw_key) |
410 | info->control.hw_key = &tx->key->conf; | ||
411 | return 0; | 402 | return 0; |
412 | } | ||
413 | 403 | ||
414 | pos += CCMP_HDR_LEN; | 404 | pos += CCMP_HDR_LEN; |
415 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); | 405 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); |
@@ -525,11 +515,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | |||
525 | u8 *pn, aad[20]; | 515 | u8 *pn, aad[20]; |
526 | int i; | 516 | int i; |
527 | 517 | ||
528 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 518 | if (info->control.hw_key) |
529 | /* hwaccel */ | ||
530 | info->control.hw_key = &tx->key->conf; | ||
531 | return 0; | 519 | return 0; |
532 | } | ||
533 | 520 | ||
534 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) | 521 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) |
535 | return TX_DROP; | 522 | return TX_DROP; |