فهرست منبع

qcacmn: Save and set the FILS key on connection completion

Save and set the FILS key on connection completion in connection
manager.

Change-Id: I7c092ae3d4e866766cdee7e56641b488627199de
CRs-Fixed: 2805749
gaurank kathpalia 4 سال پیش
والد
کامیت
ae7ee6c65e

+ 78 - 2
umac/mlme/connection_mgr/core/src/wlan_cm_connect.c

@@ -26,7 +26,6 @@
 #include "wlan_policy_mgr_api.h"
 #endif
 #include <wlan_serialization_api.h>
-#include "wlan_crypto_global_api.h"
 #ifdef CONN_MGR_ADV_FEATURE
 #include "wlan_blm_api.h"
 #include "wlan_cm_roam_api.h"
@@ -455,10 +454,61 @@ static void cm_update_fils_scan_filter(struct scan_filter *filter,
 		     REALM_HASH_LEN);
 }
 
+static inline bool cm_is_fils_connection(struct cnx_mgr *cm_ctx,
+					 struct wlan_cm_connect_rsp *resp)
+{
+	int32_t key_mgmt;
+
+	key_mgmt = wlan_crypto_get_param(cm_ctx->vdev,
+					 WLAN_CRYPTO_PARAM_KEY_MGMT);
+
+	if (!(key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA256 |
+			  1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA384 |
+			  1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256 |
+			  1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)))
+		return false;
+
+	resp->is_fils_connection = true;
+
+	return true;
+}
+
+static QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx,
+				  struct wlan_cm_connect_rsp *resp)
+{
+	struct fils_connect_rsp_params *fils_ie;
+
+	fils_ie = resp->connect_ies.fils_ie;
+
+	if (!fils_ie)
+		return QDF_STATUS_E_INVAL;
+
+	cm_store_fils_key(cm_ctx, true, 0, fils_ie->tk_len, fils_ie->tk,
+			  &resp->bssid, resp->cm_id);
+	cm_store_fils_key(cm_ctx, false, 2, fils_ie->gtk_len, fils_ie->gtk,
+			  &resp->bssid, resp->cm_id);
+	cm_set_key(cm_ctx, true, 0, &resp->bssid);
+	cm_set_key(cm_ctx, false, 2, &resp->bssid);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 #else
 static inline void cm_update_fils_scan_filter(struct scan_filter *filter,
 					      struct cm_connect_req *cm_req)
 { }
+
+static inline bool cm_is_fils_connection(struct cnx_mgr *cm_ctx,
+					 struct wlan_cm_connect_rsp *resp)
+{
+	return false;
+}
+
+static inline QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx,
+					 struct wlan_cm_connect_rsp *resp)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif /* WLAN_FEATURE_FILS_SK */
 
 static inline void
@@ -608,6 +658,24 @@ static void cm_update_security_filter(struct scan_filter *filter,
 	cm_set_pmf_caps(req, filter);
 }
 
+/**
+ * cm_set_fils_wep_key() - check and set wep or fils keys if required
+ * @cm_ctx: connection manager context
+ * @resp: connect resp
+ *
+ * Context: Can be called from any context and to be used only after posting a
+ * msg to SM (ie holding the SM lock) i.e. on successful connection.
+ */
+static void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx,
+				struct wlan_cm_connect_rsp *resp)
+{
+	if (cm_is_fils_connection(cm_ctx, resp)) {
+		cm_set_fils_key(cm_ctx, resp);
+		return;
+	}
+
+	/* set WEP keys */
+}
 #else
 static inline QDF_STATUS
 cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
@@ -647,6 +715,11 @@ static void cm_update_security_filter(struct scan_filter *filter,
 	filter->mgmtcipherset = req->crypto.mgmt_ciphers;
 	cm_set_pmf_caps(req, filter);
 }
+
+static inline void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx,
+				       struct wlan_cm_connect_rsp *resp)
+{}
+
 #endif /* CONN_MGR_ADV_FEATURE */
 
 static void cm_connect_prepare_scan_filter(struct wlan_objmgr_pdev *pdev,
@@ -1333,8 +1406,11 @@ QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx,
 
 	sm_state = cm_get_state(cm_ctx);
 	if (QDF_IS_STATUS_SUCCESS(resp->connect_status) &&
-	    sm_state == WLAN_CM_S_CONNECTED)
+	    sm_state == WLAN_CM_S_CONNECTED) {
 		cm_update_scan_db_on_connect_success(cm_ctx, resp);
+		/* set WEP and FILS key on success */
+		cm_set_fils_wep_key(cm_ctx, resp);
+	}
 
 	mlme_cm_connect_complete_ind(cm_ctx->vdev, resp);
 	mlme_cm_osif_connect_complete(cm_ctx->vdev, resp);

+ 2 - 2
umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c

@@ -22,6 +22,7 @@
 #include <wlan_serialization_api.h>
 #include "wlan_utility.h"
 #include "wlan_scan_api.h"
+#include "wlan_crypto_global_api.h"
 #ifdef CONN_MGR_ADV_FEATURE
 #include "wlan_blm_api.h"
 #endif
@@ -379,9 +380,8 @@ QDF_STATUS cm_disconnect_complete(struct cnx_mgr *cm_ctx,
 
 	mlme_cm_disconnect_complete_ind(cm_ctx->vdev, resp);
 	mlme_cm_osif_disconnect_complete(cm_ctx->vdev, resp);
-
+	wlan_crypto_free_vdev_key(cm_ctx->vdev);
 	cm_inform_if_mgr_disconnect_complete(cm_ctx->vdev);
-
 	cm_inform_blm_disconnect_complete(cm_ctx->vdev, resp);
 
 	/*

+ 34 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h

@@ -26,6 +26,7 @@
 #include "wlan_cm_main.h"
 #include "wlan_cm_sm.h"
 #include <include/wlan_mlme_cmn.h>
+#include <wlan_crypto_global_api.h>
 #ifdef WLAN_FEATURE_INTERFACE_MGR
 #include <wlan_if_mgr_api.h>
 #endif
@@ -482,6 +483,39 @@ struct cnx_mgr *cm_get_cm_ctx_fl(struct wlan_objmgr_vdev *vdev,
  */
 void cm_reset_active_cm_id(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id);
 
+#ifdef CRYPTO_SET_KEY_CONVERGED
+/**
+ * cm_set_key() - set wep or fils key on connection completion
+ * @cm_ctx: connection manager context
+ * @unicast: if key is unicast
+ * @key_idx: Key index
+ * @bssid: bssid of the connected AP
+ *
+ * Return: void
+ */
+QDF_STATUS cm_set_key(struct cnx_mgr *cm_ctx, bool unicast,
+		      uint8_t key_idx, struct qdf_mac_addr *bssid);
+#endif
+
+#ifdef WLAN_FEATURE_FILS_SK
+/**
+ * cm_store_fils_key() - store fils keys in crypto on connection complete
+ * @cm_ctx: connection manager context
+ * @unicast: if key is unicast
+ * @key_id: Key index
+ * @key_length: key length
+ * @key: key data
+ * @bssid: bssid of the connected AP
+ * @cm_id: cm_id of the connection
+ *
+ * Return: void
+ */
+void cm_store_fils_key(struct cnx_mgr *cm_ctx, bool unicast,
+		       uint8_t key_id, uint16_t key_length,
+		       uint8_t *key, struct qdf_mac_addr *bssid,
+		       wlan_cm_id cm_id);
+#endif
+
 /**
  * cm_check_cmid_match_list_head() - check if list head command matches the
  * given cm_id

+ 66 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_util.c

@@ -116,6 +116,72 @@ static inline void cm_req_lock_release(struct cnx_mgr *cm_ctx)
 }
 #endif /* WLAN_CM_USE_SPINLOCK */
 
+#ifdef CRYPTO_SET_KEY_CONVERGED
+QDF_STATUS cm_set_key(struct cnx_mgr *cm_ctx, bool unicast,
+		      uint8_t key_idx, struct qdf_mac_addr *bssid)
+{
+	struct wlan_crypto_key *crypto_key;
+
+	crypto_key = wlan_crypto_get_key(cm_ctx->vdev, key_idx);
+
+	return wlan_crypto_set_key_req(cm_ctx->vdev, crypto_key, (unicast ?
+				       WLAN_CRYPTO_KEY_TYPE_UNICAST :
+				       WLAN_CRYPTO_KEY_TYPE_GROUP));
+}
+#endif
+
+#ifdef WLAN_FEATURE_FILS_SK
+void cm_store_fils_key(struct cnx_mgr *cm_ctx, bool unicast,
+		       uint8_t key_id, uint16_t key_length,
+		       uint8_t *key, struct qdf_mac_addr *bssid,
+		       wlan_cm_id cm_id)
+{
+	struct wlan_crypto_key *crypto_key = NULL;
+	QDF_STATUS status;
+	uint8_t i;
+	int32_t cipher;
+	enum wlan_crypto_cipher_type cipher_type = WLAN_CRYPTO_CIPHER_NONE;
+
+	if (unicast)
+		cipher = wlan_crypto_get_param(cm_ctx->vdev,
+					       WLAN_CRYPTO_PARAM_UCAST_CIPHER);
+	else
+		cipher = wlan_crypto_get_param(cm_ctx->vdev,
+					       WLAN_CRYPTO_PARAM_MCAST_CIPHER);
+
+	for (i = 0; i <= WLAN_CRYPTO_CIPHER_MAX; i++) {
+		if (QDF_HAS_PARAM(cipher, i)) {
+			cipher_type = i;
+			break;
+		}
+	}
+	crypto_key = wlan_crypto_get_key(cm_ctx->vdev, key_id);
+	if (!crypto_key) {
+		crypto_key = qdf_mem_malloc(sizeof(*crypto_key));
+		if (!crypto_key)
+			return;
+		status = wlan_crypto_save_key(cm_ctx->vdev, key_id, crypto_key);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			mlme_err(CM_PREFIX_FMT "Failed to save key",
+				 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
+					       cm_id));
+			qdf_mem_free(crypto_key);
+			return;
+		}
+	}
+	qdf_mem_zero(crypto_key, sizeof(*crypto_key));
+	crypto_key->cipher_type = cipher_type;
+	crypto_key->keylen = key_length;
+	crypto_key->keyix = key_id;
+	qdf_mem_copy(&crypto_key->keyval[0], key, key_length);
+	qdf_mem_copy(crypto_key->macaddr, bssid->bytes, QDF_MAC_ADDR_SIZE);
+	mlme_debug(CM_PREFIX_FMT "cipher_type %d key_len %d, key_id %d mac:" QDF_MAC_ADDR_FMT,
+		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
+		   crypto_key->cipher_type, crypto_key->keylen,
+		   crypto_key->keyix, QDF_MAC_ADDR_REF(crypto_key->macaddr));
+}
+#endif
+
 bool cm_check_cmid_match_list_head(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
 {
 	qdf_list_node_t *cur_node = NULL;