aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-12 08:49:14 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-03-13 14:54:17 -0400
commita8286911881948c7a2ecc63ee4224c258cce2da3 (patch)
treea35566503b81c654db55857f42fe9664d0aab3af /net
parent617bbde878604adfcd557fc2a8952f77ab4ebd95 (diff)
mac80211: linearize SKBs as needed for crypto
Not linearizing every SKB will help actually pass non-linear SKBs all the way up when on an encrypted connection. For now, linearize TKIP completely as it is lower performance and I don't quite grok all the details. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/rx.c6
-rw-r--r--net/mac80211/wep.c11
-rw-r--r--net/mac80211/wpa.c22
3 files changed, 31 insertions, 8 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b38da13e2a88..53c88d145472 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1063,10 +1063,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1063 return RX_DROP_MONITOR; 1063 return RX_DROP_MONITOR;
1064 } 1064 }
1065 1065
1066 if (skb_linearize(rx->skb))
1067 return RX_DROP_UNUSABLE;
1068 /* the hdr variable is invalid now! */
1069
1070 switch (rx->key->conf.cipher) { 1066 switch (rx->key->conf.cipher) {
1071 case WLAN_CIPHER_SUITE_WEP40: 1067 case WLAN_CIPHER_SUITE_WEP40:
1072 case WLAN_CIPHER_SUITE_WEP104: 1068 case WLAN_CIPHER_SUITE_WEP104:
@@ -1089,6 +1085,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1089 return RX_DROP_UNUSABLE; 1085 return RX_DROP_UNUSABLE;
1090 } 1086 }
1091 1087
1088 /* the hdr variable is invalid after the decrypt handlers */
1089
1092 /* either the frame has been decrypted or will be dropped */ 1090 /* either the frame has been decrypted or will be dropped */
1093 status->flag |= RX_FLAG_DECRYPTED; 1091 status->flag |= RX_FLAG_DECRYPTED;
1094 1092
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 5cd87ba11bb7..7aa31bbfaa3b 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -284,22 +284,27 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
284 struct sk_buff *skb = rx->skb; 284 struct sk_buff *skb = rx->skb;
285 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 285 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
286 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 286 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
287 __le16 fc = hdr->frame_control;
287 288
288 if (!ieee80211_is_data(hdr->frame_control) && 289 if (!ieee80211_is_data(fc) && !ieee80211_is_auth(fc))
289 !ieee80211_is_auth(hdr->frame_control))
290 return RX_CONTINUE; 290 return RX_CONTINUE;
291 291
292 if (!(status->flag & RX_FLAG_DECRYPTED)) { 292 if (!(status->flag & RX_FLAG_DECRYPTED)) {
293 if (skb_linearize(rx->skb))
294 return RX_DROP_UNUSABLE;
293 if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) 295 if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
294 rx->sta->wep_weak_iv_count++; 296 rx->sta->wep_weak_iv_count++;
295 if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) 297 if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
296 return RX_DROP_UNUSABLE; 298 return RX_DROP_UNUSABLE;
297 } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { 299 } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
300 if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN))
301 return RX_DROP_UNUSABLE;
298 if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) 302 if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
299 rx->sta->wep_weak_iv_count++; 303 rx->sta->wep_weak_iv_count++;
300 ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); 304 ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
301 /* remove ICV */ 305 /* remove ICV */
302 skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); 306 if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN))
307 return RX_DROP_UNUSABLE;
303 } 308 }
304 309
305 return RX_CONTINUE; 310 return RX_CONTINUE;
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index b758350919ff..0ae23c60968c 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -138,6 +138,10 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
138 if (skb->len < hdrlen + MICHAEL_MIC_LEN) 138 if (skb->len < hdrlen + MICHAEL_MIC_LEN)
139 return RX_DROP_UNUSABLE; 139 return RX_DROP_UNUSABLE;
140 140
141 if (skb_linearize(rx->skb))
142 return RX_DROP_UNUSABLE;
143 hdr = (void *)skb->data;
144
141 data = skb->data + hdrlen; 145 data = skb->data + hdrlen;
142 data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; 146 data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
143 key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; 147 key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
@@ -253,6 +257,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
253 if (!rx->sta || skb->len - hdrlen < 12) 257 if (!rx->sta || skb->len - hdrlen < 12)
254 return RX_DROP_UNUSABLE; 258 return RX_DROP_UNUSABLE;
255 259
260 /* it may be possible to optimize this a bit more */
261 if (skb_linearize(rx->skb))
262 return RX_DROP_UNUSABLE;
263 hdr = (void *)skb->data;
264
256 /* 265 /*
257 * Let TKIP code verify IV, but skip decryption. 266 * Let TKIP code verify IV, but skip decryption.
258 * In the case where hardware checks the IV as well, 267 * In the case where hardware checks the IV as well,
@@ -484,6 +493,14 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
484 if (!rx->sta || data_len < 0) 493 if (!rx->sta || data_len < 0)
485 return RX_DROP_UNUSABLE; 494 return RX_DROP_UNUSABLE;
486 495
496 if (status->flag & RX_FLAG_DECRYPTED) {
497 if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN))
498 return RX_DROP_UNUSABLE;
499 } else {
500 if (skb_linearize(rx->skb))
501 return RX_DROP_UNUSABLE;
502 }
503
487 ccmp_hdr2pn(pn, skb->data + hdrlen); 504 ccmp_hdr2pn(pn, skb->data + hdrlen);
488 505
489 queue = rx->security_idx; 506 queue = rx->security_idx;
@@ -509,7 +526,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
509 memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); 526 memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);
510 527
511 /* Remove CCMP header and MIC */ 528 /* Remove CCMP header and MIC */
512 skb_trim(skb, skb->len - CCMP_MIC_LEN); 529 if (pskb_trim(skb, skb->len - CCMP_MIC_LEN))
530 return RX_DROP_UNUSABLE;
513 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen); 531 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
514 skb_pull(skb, CCMP_HDR_LEN); 532 skb_pull(skb, CCMP_HDR_LEN);
515 533
@@ -609,6 +627,8 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
609 if (!ieee80211_is_mgmt(hdr->frame_control)) 627 if (!ieee80211_is_mgmt(hdr->frame_control))
610 return RX_CONTINUE; 628 return RX_CONTINUE;
611 629
630 /* management frames are already linear */
631
612 if (skb->len < 24 + sizeof(*mmie)) 632 if (skb->len < 24 + sizeof(*mmie))
613 return RX_DROP_UNUSABLE; 633 return RX_DROP_UNUSABLE;
614 634