Commit f980ebc0 authored by Sara Sharon's avatar Sara Sharon Committed by Johannes Berg

mac80211: allow not sending MIC up from driver for HW crypto

When HW crypto is used, there's no need for the CCMP/GCMP MIC to
be available to mac80211, and the hardware might have removed it
already after checking. The MIC is also useless to have when the
frame is already decrypted, so allow indicating that it's not
present.

Since we are running out of bits in mac80211_rx_flags, make
the flags field a u64.
Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 162dd6a7
...@@ -979,7 +979,7 @@ static void ath10k_process_rx(struct ath10k *ar, ...@@ -979,7 +979,7 @@ static void ath10k_process_rx(struct ath10k *ar,
*status = *rx_status; *status = *rx_status;
ath10k_dbg(ar, ATH10K_DBG_DATA, ath10k_dbg(ar, ATH10K_DBG_DATA,
"rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
skb, skb,
skb->len, skb->len,
ieee80211_get_SA(hdr), ieee80211_get_SA(hdr),
......
...@@ -57,7 +57,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) ...@@ -57,7 +57,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_STRIPPED |
RX_FLAG_DECRYPTED; RX_FLAG_DECRYPTED;
wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag); wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%llx\n", status.flag);
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
......
...@@ -1034,6 +1034,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) ...@@ -1034,6 +1034,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* on this subframe * on this subframe
* @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
* is stored in the @ampdu_delimiter_crc field) * is stored in the @ampdu_delimiter_crc field)
* @RX_FLAG_MIC_STRIPPED: The mic was stripped of this packet. Decryption was
* done by the hardware
* @RX_FLAG_LDPC: LDPC was used * @RX_FLAG_LDPC: LDPC was used
* @RX_FLAG_ONLY_MONITOR: Report frame only to monitor interfaces without * @RX_FLAG_ONLY_MONITOR: Report frame only to monitor interfaces without
* processing it in any regular way. * processing it in any regular way.
...@@ -1091,6 +1093,7 @@ enum mac80211_rx_flags { ...@@ -1091,6 +1093,7 @@ enum mac80211_rx_flags {
RX_FLAG_5MHZ = BIT(29), RX_FLAG_5MHZ = BIT(29),
RX_FLAG_AMSDU_MORE = BIT(30), RX_FLAG_AMSDU_MORE = BIT(30),
RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31), RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31),
RX_FLAG_MIC_STRIPPED = BIT_ULL(32),
}; };
#define RX_FLAG_STBC_SHIFT 26 #define RX_FLAG_STBC_SHIFT 26
...@@ -1151,7 +1154,7 @@ struct ieee80211_rx_status { ...@@ -1151,7 +1154,7 @@ struct ieee80211_rx_status {
u64 boottime_ns; u64 boottime_ns;
u32 device_timestamp; u32 device_timestamp;
u32 ampdu_reference; u32 ampdu_reference;
u32 flag; u64 flag;
u16 freq; u16 freq;
u8 vht_flag; u8 vht_flag;
u8 rate_idx; u8 rate_idx;
......
...@@ -2724,8 +2724,9 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, ...@@ -2724,8 +2724,9 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
rate = cfg80211_calculate_bitrate(&ri); rate = cfg80211_calculate_bitrate(&ri);
if (WARN_ONCE(!rate, if (WARN_ONCE(!rate,
"Invalid bitrate: flags=0x%x, idx=%d, vht_nss=%d\n", "Invalid bitrate: flags=0x%llx, idx=%d, vht_nss=%d\n",
status->flag, status->rate_idx, status->vht_nss)) (unsigned long long)status->flag, status->rate_idx,
status->vht_nss))
return 0; return 0;
/* rewind from end of MPDU */ /* rewind from end of MPDU */
......
...@@ -504,18 +504,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, ...@@ -504,18 +504,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
!ieee80211_is_robust_mgmt_frame(skb)) !ieee80211_is_robust_mgmt_frame(skb))
return RX_CONTINUE; return RX_CONTINUE;
data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len;
if (!rx->sta || data_len < 0)
return RX_DROP_UNUSABLE;
if (status->flag & RX_FLAG_DECRYPTED) { if (status->flag & RX_FLAG_DECRYPTED) {
if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN)) if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (status->flag & RX_FLAG_MIC_STRIPPED)
mic_len = 0;
} else { } else {
if (skb_linearize(rx->skb)) if (skb_linearize(rx->skb))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len;
if (!rx->sta || data_len < 0)
return RX_DROP_UNUSABLE;
if (!(status->flag & RX_FLAG_PN_VALIDATED)) { if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
ccmp_hdr2pn(pn, skb->data + hdrlen); ccmp_hdr2pn(pn, skb->data + hdrlen);
...@@ -720,8 +722,7 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -720,8 +722,7 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
struct sk_buff *skb = rx->skb; struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
u8 pn[IEEE80211_GCMP_PN_LEN]; u8 pn[IEEE80211_GCMP_PN_LEN];
int data_len; int data_len, queue, mic_len = IEEE80211_GCMP_MIC_LEN;
int queue;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
...@@ -729,19 +730,20 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -729,19 +730,20 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
!ieee80211_is_robust_mgmt_frame(skb)) !ieee80211_is_robust_mgmt_frame(skb))
return RX_CONTINUE; return RX_CONTINUE;
data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN -
IEEE80211_GCMP_MIC_LEN;
if (!rx->sta || data_len < 0)
return RX_DROP_UNUSABLE;
if (status->flag & RX_FLAG_DECRYPTED) { if (status->flag & RX_FLAG_DECRYPTED) {
if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN)) if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (status->flag & RX_FLAG_MIC_STRIPPED)
mic_len = 0;
} else { } else {
if (skb_linearize(rx->skb)) if (skb_linearize(rx->skb))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - mic_len;
if (!rx->sta || data_len < 0)
return RX_DROP_UNUSABLE;
if (!(status->flag & RX_FLAG_PN_VALIDATED)) { if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
gcmp_hdr2pn(pn, skb->data + hdrlen); gcmp_hdr2pn(pn, skb->data + hdrlen);
...@@ -772,7 +774,7 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -772,7 +774,7 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
} }
/* Remove GCMP header and MIC */ /* Remove GCMP header and MIC */
if (pskb_trim(skb, skb->len - IEEE80211_GCMP_MIC_LEN)) if (pskb_trim(skb, skb->len - mic_len))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen); memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen);
skb_pull(skb, IEEE80211_GCMP_HDR_LEN); skb_pull(skb, IEEE80211_GCMP_HDR_LEN);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment