Bläddra i källkod

qcacld-3.0: Fix issue that rx failed after WAPI usk rekey

As WAPI spec, once USK rekey, PN need reset to 0x5c37, but IWNCOM AP
will send 1st packet with old PN larger than 0x5c37 after rekey, So PN
check failed for later packets.
Fix: Don't update Last_PN  when receive the 1st packet from AP after USK
rekey, Last_PN keeps 0x5c37.

Analysis:
1.      Host installed new unicast key after rekey handshake with AP.
2.      Host Last_PN was updated to 0x5c37 as spec (expect PN of next
         packet from AP is: 0x5c39)
3.      Host received ping request from AP with old PN 0x5cb9
4.      Host PN checked passed, driver Last_PN  was updated as 0x5cb9
5.      Host received ping request from AP with new PN 0x5c39
6.      Host PN checked failed since 0x5c39 < 0x5cb9,  ping request
        dropped, no response.

Change-Id: Ifd0269193ffbe53889191269a0e985d13ea2ecf7
CRs-Fixed: 2101217
Zhu Jianmin 7 år sedan
förälder
incheckning
e9afed5e17
3 ändrade filer med 17 tillägg och 3 borttagningar
  1. 2 0
      core/dp/txrx/ol_rx.c
  2. 14 3
      core/dp/txrx/ol_rx_pn.c
  3. 1 0
      core/dp/txrx/ol_txrx_types.h

+ 2 - 0
core/dp/txrx/ol_rx.c

@@ -795,6 +795,8 @@ ol_rx_sec_ind_handler(ol_txrx_pdev_handle pdev,
 			peer->tids_last_pn[i].pn128[0] =
 				qdf_cpu_to_le64(
 					peer->tids_last_pn[i].pn128[0]);
+			if (sec_index == txrx_sec_ucast)
+				peer->tids_rekey_flag[i] = 1;
 		}
 	}
 }

+ 14 - 3
core/dp/txrx/ol_rx_pn.c

@@ -231,10 +231,21 @@ ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev,
 			 * of the PN.
 			 * This is more efficient than doing a conditional
 			 * branch to copy only the relevant portion.
+
+			 * IWNCOM AP will send 1 packet with old PN after USK
+			 * rekey, don't update last_pn when recv the packet, or
+			 * PN check failed for later packets
 			 */
-			last_pn->pn128[0] = new_pn.pn128[0];
-			last_pn->pn128[1] = new_pn.pn128[1];
-			OL_RX_PN_TRACE_ADD(pdev, peer, tid, rx_desc);
+			if ((peer->security[index].sec_type
+				== htt_sec_type_wapi) &&
+			    (peer->tids_rekey_flag[tid] == 1) &&
+			    (index == txrx_sec_ucast)) {
+				peer->tids_rekey_flag[tid] = 0;
+			} else {
+				last_pn->pn128[0] = new_pn.pn128[0];
+				last_pn->pn128[1] = new_pn.pn128[1];
+				OL_RX_PN_TRACE_ADD(pdev, peer, tid, rx_desc);
+			}
 		}
 
 		mpdu = next_mpdu;

+ 1 - 0
core/dp/txrx/ol_txrx_types.h

@@ -1212,6 +1212,7 @@ struct ol_txrx_peer_t {
 	struct ol_rx_reorder_t tids_rx_reorder[OL_TXRX_NUM_EXT_TIDS];
 	union htt_rx_pn_t tids_last_pn[OL_TXRX_NUM_EXT_TIDS];
 	uint8_t tids_last_pn_valid[OL_TXRX_NUM_EXT_TIDS];
+	uint8_t tids_rekey_flag[OL_TXRX_NUM_EXT_TIDS];
 	uint16_t tids_next_rel_idx[OL_TXRX_NUM_EXT_TIDS];
 	uint16_t tids_last_seq[OL_TXRX_NUM_EXT_TIDS];
 	uint16_t tids_mcast_last_seq[OL_TXRX_NUM_EXT_TIDS];