Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / wpa.c
index 943f7606527e25b4cad0bfea2a38755f1f7f69d9..feb547dc8643ab286fa0c64f19b01e2b4766898e 100644 (file)
@@ -516,31 +516,34 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
                        return RX_DROP_UNUSABLE;
        }
 
-       ccmp_hdr2pn(pn, skb->data + hdrlen);
+       if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
+               ccmp_hdr2pn(pn, skb->data + hdrlen);
 
-       queue = rx->security_idx;
+               queue = rx->security_idx;
 
-       if (memcmp(pn, key->u.ccmp.rx_pn[queue], IEEE80211_CCMP_PN_LEN) <= 0) {
-               key->u.ccmp.replays++;
-               return RX_DROP_UNUSABLE;
-       }
+               if (memcmp(pn, key->u.ccmp.rx_pn[queue],
+                          IEEE80211_CCMP_PN_LEN) <= 0) {
+                       key->u.ccmp.replays++;
+                       return RX_DROP_UNUSABLE;
+               }
 
-       if (!(status->flag & RX_FLAG_DECRYPTED)) {
-               u8 aad[2 * AES_BLOCK_SIZE];
-               u8 b_0[AES_BLOCK_SIZE];
-               /* hardware didn't decrypt/verify MIC */
-               ccmp_special_blocks(skb, pn, b_0, aad);
+               if (!(status->flag & RX_FLAG_DECRYPTED)) {
+                       u8 aad[2 * AES_BLOCK_SIZE];
+                       u8 b_0[AES_BLOCK_SIZE];
+                       /* hardware didn't decrypt/verify MIC */
+                       ccmp_special_blocks(skb, pn, b_0, aad);
+
+                       if (ieee80211_aes_ccm_decrypt(
+                                   key->u.ccmp.tfm, b_0, aad,
+                                   skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
+                                   data_len,
+                                   skb->data + skb->len - mic_len, mic_len))
+                               return RX_DROP_UNUSABLE;
+               }
 
-               if (ieee80211_aes_ccm_decrypt(
-                           key->u.ccmp.tfm, b_0, aad,
-                           skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
-                           data_len,
-                           skb->data + skb->len - mic_len, mic_len))
-                       return RX_DROP_UNUSABLE;
+               memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
        }
 
-       memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
-
        /* Remove CCMP header and MIC */
        if (pskb_trim(skb, skb->len - mic_len))
                return RX_DROP_UNUSABLE;
@@ -739,31 +742,35 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
                        return RX_DROP_UNUSABLE;
        }
 
-       gcmp_hdr2pn(pn, skb->data + hdrlen);
+       if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
+               gcmp_hdr2pn(pn, skb->data + hdrlen);
 
-       queue = rx->security_idx;
+               queue = rx->security_idx;
 
-       if (memcmp(pn, key->u.gcmp.rx_pn[queue], IEEE80211_GCMP_PN_LEN) <= 0) {
-               key->u.gcmp.replays++;
-               return RX_DROP_UNUSABLE;
-       }
+               if (memcmp(pn, key->u.gcmp.rx_pn[queue],
+                          IEEE80211_GCMP_PN_LEN) <= 0) {
+                       key->u.gcmp.replays++;
+                       return RX_DROP_UNUSABLE;
+               }
 
-       if (!(status->flag & RX_FLAG_DECRYPTED)) {
-               u8 aad[2 * AES_BLOCK_SIZE];
-               u8 j_0[AES_BLOCK_SIZE];
-               /* hardware didn't decrypt/verify MIC */
-               gcmp_special_blocks(skb, pn, j_0, aad);
+               if (!(status->flag & RX_FLAG_DECRYPTED)) {
+                       u8 aad[2 * AES_BLOCK_SIZE];
+                       u8 j_0[AES_BLOCK_SIZE];
+                       /* hardware didn't decrypt/verify MIC */
+                       gcmp_special_blocks(skb, pn, j_0, aad);
+
+                       if (ieee80211_aes_gcm_decrypt(
+                                   key->u.gcmp.tfm, j_0, aad,
+                                   skb->data + hdrlen + IEEE80211_GCMP_HDR_LEN,
+                                   data_len,
+                                   skb->data + skb->len -
+                                   IEEE80211_GCMP_MIC_LEN))
+                               return RX_DROP_UNUSABLE;
+               }
 
-               if (ieee80211_aes_gcm_decrypt(
-                           key->u.gcmp.tfm, j_0, aad,
-                           skb->data + hdrlen + IEEE80211_GCMP_HDR_LEN,
-                           data_len,
-                           skb->data + skb->len - IEEE80211_GCMP_MIC_LEN))
-                       return RX_DROP_UNUSABLE;
+               memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN);
        }
 
-       memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN);
-
        /* Remove GCMP header and MIC */
        if (pskb_trim(skb, skb->len - IEEE80211_GCMP_MIC_LEN))
                return RX_DROP_UNUSABLE;