Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

p54: more cryptographic accelerator fixes

If we let the firmware do the data encryption, we have to remove the ICV and
(M)MIC at the end of the frame before we can give it back to mac80211.
Or, these data frames have a few trailing bytes on cooked monitor interfaces.

Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Christian Lamparter and committed by
John W. Linville
12da401e 40ab73cc

+17 -3
+17 -3
drivers/net/wireless/p54/p54common.c
··· 745 745 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); 746 746 struct p54_hdr *entry_hdr; 747 747 struct p54_tx_data *entry_data; 748 - int pad = 0; 748 + unsigned int pad = 0, frame_len; 749 749 750 750 range = (void *)info->rate_driver_data; 751 751 if (range->start_addr != addr) { ··· 768 768 __skb_unlink(entry, &priv->tx_queue); 769 769 spin_unlock_irqrestore(&priv->tx_queue.lock, flags); 770 770 771 + frame_len = entry->len; 771 772 entry_hdr = (struct p54_hdr *) entry->data; 772 773 entry_data = (struct p54_tx_data *) entry_hdr->data; 773 774 priv->tx_stats[entry_data->hw_queue].len--; ··· 815 814 info->status.ack_signal = p54_rssi_to_dbm(dev, 816 815 (int)payload->ack_rssi); 817 816 818 - if (entry_data->key_type == P54_CRYPTO_TKIPMICHAEL) { 817 + /* Undo all changes to the frame. */ 818 + switch (entry_data->key_type) { 819 + case P54_CRYPTO_TKIPMICHAEL: { 819 820 u8 *iv = (u8 *)(entry_data->align + pad + 820 - entry_data->crypt_offset); 821 + entry_data->crypt_offset); 821 822 822 823 /* Restore the original TKIP IV. */ 823 824 iv[2] = iv[0]; 824 825 iv[0] = iv[1]; 825 826 iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */ 827 + 828 + frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */ 829 + break; 830 + } 831 + case P54_CRYPTO_AESCCMP: 832 + frame_len -= 8; /* remove CCMP_MIC */ 833 + break; 834 + case P54_CRYPTO_WEP: 835 + frame_len -= 4; /* remove WEP_ICV */ 836 + break; 826 837 } 838 + skb_trim(entry, frame_len); 827 839 skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); 828 840 ieee80211_tx_status_irqsafe(dev, entry); 829 841 goto out;