diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2008-04-17 19:03:36 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-07 15:02:11 -0400 |
commit | 3ec47732a0be038f15a0b8d852a4e4ff9c5b0196 (patch) | |
tree | 2cb45a6582df77a571554850152256df611ce094 /drivers/net/wireless/iwlwifi/iwl-4965.c | |
parent | c6adbd2158fee972adcc6232de5e2ef375f1f782 (diff) |
iwlwifi: HW crypto acceleration fixes
This patch fixes several issues in security:
1) the uCode doesn't know about TKIP-MMIC failure, if uCode set
RX_RES_STATUS_BAD_ICV_MIC, it means ICV failure: drop the packet silently.
2) do not allocate room in the key table of the uCode is the set_key call
is a replacement of an old key
3) check the keyidx of the key in the uCode before removing it upon
disable_key call
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 69a355bbb97a..ddcd1b232549 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2871,6 +2871,53 @@ static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) | |||
2871 | priv->rx_stats[idx].bytes += len; | 2871 | priv->rx_stats[idx].bytes += len; |
2872 | } | 2872 | } |
2873 | 2873 | ||
2874 | /* | ||
2875 | * returns non-zero if packet should be dropped | ||
2876 | */ | ||
2877 | static int iwl4965_set_decrypted_flag(struct iwl_priv *priv, | ||
2878 | struct ieee80211_hdr *hdr, | ||
2879 | u32 decrypt_res, | ||
2880 | struct ieee80211_rx_status *stats) | ||
2881 | { | ||
2882 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
2883 | |||
2884 | if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) | ||
2885 | return 0; | ||
2886 | |||
2887 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
2888 | return 0; | ||
2889 | |||
2890 | IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); | ||
2891 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
2892 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
2893 | /* The uCode has got a bad phase 1 Key, pushes the packet. | ||
2894 | * Decryption will be done in SW. */ | ||
2895 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2896 | RX_RES_STATUS_BAD_KEY_TTAK) | ||
2897 | break; | ||
2898 | |||
2899 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2900 | RX_RES_STATUS_BAD_ICV_MIC) { | ||
2901 | /* bad ICV, the packet is destroyed since the | ||
2902 | * decryption is inplace, drop it */ | ||
2903 | IWL_DEBUG_RX("Packet destroyed\n"); | ||
2904 | return -1; | ||
2905 | } | ||
2906 | case RX_RES_STATUS_SEC_TYPE_WEP: | ||
2907 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
2908 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2909 | RX_RES_STATUS_DECRYPT_OK) { | ||
2910 | IWL_DEBUG_RX("hw decrypt successfully!!!\n"); | ||
2911 | stats->flag |= RX_FLAG_DECRYPTED; | ||
2912 | } | ||
2913 | break; | ||
2914 | |||
2915 | default: | ||
2916 | break; | ||
2917 | } | ||
2918 | return 0; | ||
2919 | } | ||
2920 | |||
2874 | static u32 iwl4965_translate_rx_status(u32 decrypt_in) | 2921 | static u32 iwl4965_translate_rx_status(u32 decrypt_in) |
2875 | { | 2922 | { |
2876 | u32 decrypt_out = 0; | 2923 | u32 decrypt_out = 0; |
@@ -3000,8 +3047,10 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | |||
3000 | stats->flag = 0; | 3047 | stats->flag = 0; |
3001 | hdr = (struct ieee80211_hdr *)rxb->skb->data; | 3048 | hdr = (struct ieee80211_hdr *)rxb->skb->data; |
3002 | 3049 | ||
3003 | if (!priv->cfg->mod_params->sw_crypto) | 3050 | /* in case of HW accelerated crypto and bad decryption, drop */ |
3004 | iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); | 3051 | if (!priv->cfg->mod_params->sw_crypto && |
3052 | iwl4965_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
3053 | return; | ||
3005 | 3054 | ||
3006 | if (priv->add_radiotap) | 3055 | if (priv->add_radiotap) |
3007 | iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); | 3056 | iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); |