Browse Source

qcacmn: Beacon protection support

Changes to support Beacon protection. Additional key ix 6 and 7
support BIGTK. Update beacon template for Beacon protection support.

CRs-Fixed: 2632290
Change-Id: Ic37d17f5076bb28d2e1f2430da039cc8b9f759b6
Gurumoorthi Gnanasambandhan 5 năm trước cách đây
mục cha
commit
806b7c72df

+ 1 - 0
umac/cmn_services/crypto/inc/wlan_crypto_global_def.h

@@ -49,6 +49,7 @@
 #define WLAN_CRYPTO_KEYIX_NONE       ((uint16_t)-1)
 #define WLAN_CRYPTO_MAXKEYIDX        (4)
 #define WLAN_CRYPTO_MAXIGTKKEYIDX    (2)
+#define WLAN_CRYPTO_MAXBIGTKKEYIDX   (2)
 #ifndef WLAN_CRYPTO_MAX_VLANKEYIX
 #define WLAN_CRYPTO_MAX_VLANKEYIX    WLAN_CRYPTO_MAXKEYIDX
 #endif

+ 5 - 1
umac/cmn_services/crypto/src/wlan_crypto_def_i.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -427,9 +427,11 @@ struct wlan_crypto_mmie {
  * @crypto_params:    crypto params for the peer
  * @key:              key buffers for this peer
  * @igtk_key:         igtk key buffer for this peer
+ * @bigtk_key:        bigtk key buffer for this peer
  * @igtk_key_type:    igtk key type
  * @def_tx_keyid:     default key used for this peer
  * @def_igtk_tx_keyid default igtk key used for this peer
+ * @def_bigtk_tx_keyid default bigtk key used for this peer
  * @fils_aead_set     fils params for this peer
  *
  */
@@ -437,9 +439,11 @@ struct wlan_crypto_comp_priv {
 	struct wlan_crypto_params crypto_params;
 	struct wlan_crypto_key *key[WLAN_CRYPTO_MAX_VLANKEYIX];
 	struct wlan_crypto_key *igtk_key[WLAN_CRYPTO_MAXIGTKKEYIDX];
+	struct wlan_crypto_key *bigtk_key[WLAN_CRYPTO_MAXBIGTKKEYIDX];
 	uint32_t igtk_key_type;
 	uint8_t def_tx_keyid;
 	uint8_t def_igtk_tx_keyid;
+	uint8_t def_bigtk_tx_keyid;
 	uint8_t fils_aead_set;
 };
 

+ 127 - 34
umac/cmn_services/crypto/src/wlan_crypto_global_api.c

@@ -55,6 +55,36 @@ const struct wlan_crypto_cipher *wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX];
 	WLAN_CRYPTO_ADDSELECTOR(frm,\
 				wlan_crypto_rsn_keymgmt_to_suite(keymgmt))
 
+static int is_valid_keyix(uint16_t keyix)
+{
+	if (keyix >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX
+			+ WLAN_CRYPTO_MAXBIGTKKEYIDX))
+		return 0;
+	else
+		return 1;
+}
+
+static int is_igtk(uint16_t keyix)
+{
+	if (keyix < WLAN_CRYPTO_MAXKEYIDX)
+		return 0;
+	else if (keyix - WLAN_CRYPTO_MAXKEYIDX >= WLAN_CRYPTO_MAXIGTKKEYIDX)
+		return 0;
+	else
+		return 1;
+}
+
+static int is_bigtk(uint16_t keyix)
+{
+	if (keyix < (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))
+		return 0;
+	if (keyix - WLAN_CRYPTO_MAXKEYIDX - WLAN_CRYPTO_MAXIGTKKEYIDX
+						>= WLAN_CRYPTO_MAXBIGTKKEYIDX)
+		return 0;
+	else
+		return 1;
+}
+
 /**
  * wlan_crypto_vdev_get_crypto_params - called by mlme to get crypto params
  * @vdev:vdev
@@ -588,6 +618,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
 	bool isbcast;
 	enum QDF_OPMODE vdev_mode;
 	uint8_t igtk_idx = 0;
+	uint8_t bigtk_idx = 0;
 
 	if (!vdev || !req_key || req_key->keylen > (sizeof(req_key->keydata))) {
 		crypto_err("Invalid params vdev%pK, req_key%pK", vdev, req_key);
@@ -679,22 +710,40 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
 		}
 
 		if (IS_MGMT_CIPHER(req_key->type)) {
+			struct wlan_crypto_key *crypto_key = NULL;
+
 			igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX;
-			if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
-				crypto_err("igtk key invalid keyid %d",
-					   igtk_idx);
+			bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX;
+			if (is_igtk(req_key->keyix)) {
+				bigtk_idx = 0;
+			} else if (is_bigtk(req_key->keyix)) {
+				igtk_idx = 0;
+			} else {
+				crypto_err("igtk/bigtk key invalid keyid %d",
+					   req_key->keyix);
 				return QDF_STATUS_E_INVAL;
 			}
 			key = qdf_mem_malloc(sizeof(struct wlan_crypto_key));
 			if (!key)
 				return QDF_STATUS_E_NOMEM;
 
-			if (crypto_priv->igtk_key[igtk_idx])
-				qdf_mem_free(crypto_priv->igtk_key[igtk_idx]);
 
-			crypto_priv->igtk_key[igtk_idx] = key;
-			crypto_priv->igtk_key_type = req_key->type;
-			crypto_priv->def_igtk_tx_keyid = igtk_idx;
+			if (igtk_idx) {
+				crypto_key = crypto_priv->igtk_key[igtk_idx];
+				if (crypto_key)
+					qdf_mem_free(crypto_key);
+
+				crypto_priv->igtk_key[igtk_idx] = key;
+				crypto_priv->igtk_key_type = req_key->type;
+				crypto_priv->def_igtk_tx_keyid = igtk_idx;
+			} else {
+				crypto_key = crypto_priv->bigtk_key[bigtk_idx];
+				if (crypto_key)
+					qdf_mem_free(crypto_key);
+
+				crypto_priv->bigtk_key[bigtk_idx] = key;
+				crypto_priv->def_bigtk_tx_keyid = bigtk_idx;
+			}
 		} else {
 			if (IS_FILS_CIPHER(req_key->type)) {
 				crypto_err("FILS key is not for BroadCast pkt");
@@ -720,6 +769,8 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
 				crypto_err("peer NULL");
 				if (IS_MGMT_CIPHER(req_key->type)) {
 					crypto_priv->igtk_key[igtk_idx] = NULL;
+					crypto_priv->bigtk_key[bigtk_idx]
+						= NULL;
 					crypto_priv->igtk_key_type
 						= WLAN_CRYPTO_CIPHER_NONE;
 				} else
@@ -759,22 +810,39 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
 			return QDF_STATUS_E_INVAL;
 		}
 		if (IS_MGMT_CIPHER(req_key->type)) {
+			struct wlan_crypto_key *crypto_key = NULL;
+
 			igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX;
-			if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
-				crypto_err("igtk key invalid keyid %d",
-					   igtk_idx);
+			bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX;
+			if (is_igtk(req_key->keyix)) {
+				bigtk_idx = 0;
+			} else if (is_bigtk(req_key->keyix)) {
+				igtk_idx = 0;
+			} else {
+				crypto_err("igtk/bigtk key invalid keyid %d",
+					   req_key->keyix);
 				return QDF_STATUS_E_INVAL;
 			}
 			key = qdf_mem_malloc(sizeof(struct wlan_crypto_key));
 			if (!key)
 				return QDF_STATUS_E_NOMEM;
 
-			if (crypto_priv->igtk_key[igtk_idx])
-				qdf_mem_free(crypto_priv->igtk_key[igtk_idx]);
-
-			crypto_priv->igtk_key[igtk_idx] = key;
-			crypto_priv->igtk_key_type = req_key->type;
-			crypto_priv->def_igtk_tx_keyid = igtk_idx;
+			if (igtk_idx) {
+				crypto_key = crypto_priv->igtk_key[igtk_idx];
+				if (crypto_key)
+					qdf_mem_free(crypto_key);
+
+				crypto_priv->igtk_key[igtk_idx] = key;
+				crypto_priv->igtk_key_type = req_key->type;
+				crypto_priv->def_igtk_tx_keyid = igtk_idx;
+			} else {
+				crypto_key = crypto_priv->bigtk_key[bigtk_idx];
+				if (crypto_key)
+					qdf_mem_free(crypto_key);
+
+				crypto_priv->bigtk_key[bigtk_idx] = key;
+				crypto_priv->def_bigtk_tx_keyid = bigtk_idx;
+			}
 		} else {
 			uint16_t kid = req_key->keyix;
 			if (kid == WLAN_CRYPTO_KEYIX_NONE)
@@ -853,7 +921,8 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
 	key->valid = 1;
 	if ((IS_MGMT_CIPHER(req_key->type))) {
 		if (HAS_CIPHER_CAP(crypto_params,
-					WLAN_CRYPTO_CAP_PMF_OFFLOAD)) {
+					WLAN_CRYPTO_CAP_PMF_OFFLOAD) ||
+					is_bigtk(req_key->keyix)) {
 			if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
 				WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev,
 						key, macaddr, req_key->type);
@@ -928,10 +997,13 @@ struct wlan_crypto_key *wlan_crypto_vdev_getkey(struct wlan_objmgr_vdev *vdev,
 	 * we return the default key, for all other keyix we return the
 	 * key accordingly.
 	 */
-	if (keyix == WLAN_CRYPTO_KEYIX_NONE ||
-	    keyix >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))
+	if ((keyix == WLAN_CRYPTO_KEYIX_NONE) ||
+	    !is_valid_keyix(keyix))
 		key = crypto_priv->key[crypto_priv->def_tx_keyid];
-	else if (keyix >= WLAN_CRYPTO_MAXKEYIDX)
+	else if (is_bigtk(keyix))
+		key = crypto_priv->bigtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX
+						- WLAN_CRYPTO_MAXIGTKKEYIDX];
+	else if (is_igtk(keyix))
 		key = crypto_priv->igtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX];
 	else
 		key = crypto_priv->key[keyix];
@@ -970,9 +1042,12 @@ struct wlan_crypto_key *wlan_crypto_peer_getkey(struct wlan_objmgr_peer *peer,
 	 * key accordingly.
 	 */
 	if (keyix == WLAN_CRYPTO_KEYIX_NONE ||
-	    keyix >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))
+	    !is_valid_keyix(keyix))
 		key = crypto_priv->key[crypto_priv->def_tx_keyid];
-	else if (keyix >= WLAN_CRYPTO_MAXKEYIDX)
+	else if (is_bigtk(keyix))
+		key = crypto_priv->bigtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX
+						- WLAN_CRYPTO_MAXIGTKKEYIDX];
+	else if (is_igtk(keyix))
 		key = crypto_priv->igtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX];
 	else
 		key = crypto_priv->key[keyix];
@@ -1097,8 +1172,7 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev,
 	uint8_t bssid_mac[QDF_MAC_ADDR_SIZE];
 
 	if (!vdev || !macaddr ||
-		(key_idx >=
-			(WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))) {
+		!is_valid_keyix(key_idx)) {
 		crypto_err("Invalid param vdev %pK macaddr %pK keyidx %d",
 			   vdev, macaddr, key_idx);
 		return QDF_STATUS_E_INVAL;
@@ -1147,12 +1221,23 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev,
 
 	if (key_idx >= WLAN_CRYPTO_MAXKEYIDX) {
 		uint8_t igtk_idx = key_idx - WLAN_CRYPTO_MAXKEYIDX;
-		if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) {
-			crypto_err("Igtk key invalid keyid %d", igtk_idx);
+		uint8_t bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX;
+
+		if (is_igtk(key_idx)) {
+			bigtk_idx = 0;
+		} else if (is_bigtk(key_idx)) {
+			igtk_idx = 0;
+		} else {
+			crypto_err("igtk/bigtk key invalid keyid %d", key_idx);
 			return QDF_STATUS_E_INVAL;
 		}
-		key = crypto_priv->igtk_key[igtk_idx];
-		crypto_priv->igtk_key[igtk_idx] = NULL;
+		if (igtk_idx) {
+			key = crypto_priv->igtk_key[igtk_idx];
+			crypto_priv->igtk_key[igtk_idx] = NULL;
+		} else {
+			key = crypto_priv->bigtk_key[bigtk_idx];
+			crypto_priv->bigtk_key[bigtk_idx] = NULL;
+		}
 		if (key)
 			key->valid = 0;
 	} else {
@@ -4114,7 +4199,7 @@ QDF_STATUS wlan_crypto_validate_key_params(enum wlan_crypto_cipher_type cipher,
 					   uint8_t key_index, uint8_t key_len,
 					   uint8_t seq_len)
 {
-	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
+	if (!is_valid_keyix(key_index)) {
 		crypto_err("Invalid Key index %d", key_index);
 		return QDF_STATUS_E_INVAL;
 	}
@@ -4158,15 +4243,18 @@ QDF_STATUS wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev,
 		crypto_err("crypto_priv NULL");
 		return QDF_STATUS_E_FAILURE;
 	}
-	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
+	if (!is_valid_keyix(key_index)) {
 		crypto_err("Invalid Key index %d", key_index);
 		return QDF_STATUS_E_FAILURE;
 	}
 	if (key_index < WLAN_CRYPTO_MAXKEYIDX)
 		crypto_priv->key[key_index] = crypto_key;
-	else
+	else if (is_igtk(key_index))
 		crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX] =
 			crypto_key;
+	else
+		crypto_priv->bigtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX
+				- WLAN_CRYPTO_MAXIGTKKEYIDX] = crypto_key;
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -4181,14 +4269,19 @@ struct wlan_crypto_key *wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev,
 		crypto_err("crypto_priv NULL");
 		return NULL;
 	}
-	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
+	if (!is_valid_keyix(key_index)) {
 		crypto_err("Invalid Key index %d", key_index);
 		return NULL;
 	}
 	if (key_index < WLAN_CRYPTO_MAXKEYIDX)
 		return crypto_priv->key[key_index];
+	else if (is_igtk(key_index))
+		return crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX];
+	else
+		return crypto_priv->bigtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX
+						- WLAN_CRYPTO_MAXIGTKKEYIDX];
 
-	return crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX];
+	return NULL;
 }
 
 QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev,

+ 8 - 1
umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -195,6 +195,13 @@ static void wlan_crypto_free_key(struct wlan_crypto_comp_priv *crypto_priv)
 		}
 	}
 
+	for (i = 0; i < WLAN_CRYPTO_MAXBIGTKKEYIDX; i++) {
+		if (crypto_priv->bigtk_key[i]) {
+			qdf_mem_free(crypto_priv->bigtk_key[i]);
+			crypto_priv->bigtk_key[i] = NULL;
+		}
+	}
+
 }
 
 static QDF_STATUS wlan_crypto_vdev_obj_destroy_handler(

+ 3 - 0
umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h

@@ -89,6 +89,9 @@
 #define WLAN_PDEV_F_MBSS_IE_ENABLE          0x20000000
 /* VDEV Peer delete all */
 #define WLAN_PDEV_F_DELETE_ALL_PEER         0x40000000
+/* PDEV BEacon Protection */
+#define WLAN_PDEV_F_BEACON_PROTECTION       0x80000000
+
 
 /* PDEV op flags */
    /* Enable htrate for wep and tkip */

+ 2 - 0
umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h

@@ -171,6 +171,7 @@ struct tbttoffset_params {
  * @ext_csa_switch_count_offset: ECSA switch count offset in beacon frame
  * @esp_ie_offset: ESP IE offset in beacon frame
  * @mu_edca_ie_offset: Mu EDCA IE offset in beacon frame
+ * @enable_bigtk: enable bigtk or not
  * @frm: beacon template parameter
  */
 struct beacon_tmpl_params {
@@ -183,6 +184,7 @@ struct beacon_tmpl_params {
 	uint32_t ext_csa_switch_count_offset;
 	uint32_t esp_ie_offset;
 	uint32_t mu_edca_ie_offset;
+	bool enable_bigtk;
 	uint8_t *frm;
 };
 

+ 1 - 0
wmi/inc/wmi_unified_param.h

@@ -5120,6 +5120,7 @@ typedef enum {
 	wmi_service_time_sync_ftm,
 	wmi_service_nss_ratio_to_host_support,
 	wmi_roam_scan_chan_list_to_host_support,
+	wmi_beacon_protection_support,
 	wmi_services_max,
 } wmi_conv_service_ids;
 #define WMI_SERVICE_UNAVAILABLE 0xFFFF

+ 5 - 0
wmi/src/wmi_unified_tlv.c

@@ -2402,6 +2402,9 @@ static QDF_STATUS send_beacon_tmpl_send_cmd_tlv(wmi_unified_t wmi_handle,
 	cmd->esp_ie_offset = param->esp_ie_offset;
 	cmd->mu_edca_ie_offset = param->mu_edca_ie_offset;
 	cmd->buf_len = param->tmpl_len;
+
+	WMI_BEACON_PROTECTION_EN_SET(cmd->feature_enable_bitmap,
+				     param->enable_bigtk);
 	buf_ptr += sizeof(wmi_bcn_tmpl_cmd_fixed_param);
 
 	bcn_prb_info = (wmi_bcn_prb_info *) buf_ptr;
@@ -14436,6 +14439,8 @@ static void populate_tlv_service(uint32_t *wmi_service)
 			WMI_SERVICE_NSS_RATIO_TO_HOST_SUPPORT;
 	wmi_service[wmi_roam_scan_chan_list_to_host_support] =
 			WMI_SERVICE_ROAM_SCAN_CHANNEL_LIST_TO_HOST_SUPPORT;
+	wmi_service[wmi_beacon_protection_support] =
+			WMI_SERVICE_BEACON_PROTECTION_SUPPORT;
 }
 
 /**