Просмотр исходного кода

qcacmn: Add new crypto serivce apis for security checks

Add new crypto component service apis to check the security
match.

Change-Id: I66336c4924b2a2c203d6ba197ab649725f960ef8
CRs-Fixed: 2337195
Kiran Kumar Lokere 6 лет назад
Родитель
Сommit
605e7a710b

+ 67 - 0
umac/cmn_services/crypto/inc/wlan_crypto_global_api.h

@@ -589,4 +589,71 @@ uint16_t wlan_crypto_get_keyid(uint8_t *data, int hdrlen);
  * Return: void
  */
 void wlan_crypto_restore_keys(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_crypto_check_open_none - called by ucfg to check for open security
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ *
+ * This function gets called from ucfg to check open security.
+ *
+ * Return: true or false
+ */
+bool wlan_crypto_check_open_none(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vedv_id);
+
+/**
+ * wlan_crypto_check_wep - called by ucfg to check for WEP security
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ *
+ * This function gets called from ucfg to check WEP security.
+ *
+ * Return: true or false
+ */
+bool wlan_crypto_check_wep(struct wlan_objmgr_psoc *psoc, uint8_t vedv_id);
+
+/**
+ * wlan_crypto_check_rsn_match - called by ucfg to check for RSN match
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ * @ie_ptr: pointer to IEs
+ * @ie_len: IE length
+ *
+ * This function gets called from ucfg to check RSN match.
+ *
+ * Return: true or false
+ */
+bool wlan_crypto_check_rsn_match(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vedv_id, uint8_t *ie_ptr,
+				 uint16_t ie_len);
+
+/**
+ * wlan_crypto_check_rsn_match - called by ucfg to check for WPA match
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ * @ie_ptr: pointer to IEs
+ * @ie_len: IE length
+ *
+ * This function gets called from ucfg to check WPA match.
+ *
+ * Return: true or false
+ */
+bool wlan_crypto_check_wpa_match(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vedv_id, uint8_t *ie_ptr,
+				 uint16_t ie_len);
+
+/**
+ * wlan_set_vdev_crypto_prarams_from_ie - Sets vdev crypto params from IE info
+ * @vdev: vdev pointer
+ * @ie_ptr: pointer to IE
+ * @ie_len: IE length
+ *
+ * This function gets called from ucfg to set crypto params from IE data.
+ *
+ * Return: QDF_STATUS_SUCCESS or error code
+ */
+QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev,
+						uint8_t *ie_ptr,
+						uint16_t ie_len);
 #endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */

+ 346 - 4
umac/cmn_services/crypto/src/wlan_crypto_global_api.c

@@ -19,6 +19,7 @@
  /**
  * DOC: Public APIs for crypto service
  */
+
 #include <qdf_types.h>
 #include <wlan_cmn.h>
 #include <wlan_objmgr_cmn.h>
@@ -27,6 +28,7 @@
 #include <wlan_objmgr_pdev_obj.h>
 #include <wlan_objmgr_vdev_obj.h>
 #include <wlan_objmgr_peer_obj.h>
+#include <wlan_utility.h>
 
 #include "wlan_crypto_global_def.h"
 #include "wlan_crypto_global_api.h"
@@ -118,6 +120,7 @@ static QDF_STATUS wlan_crypto_set_param(struct wlan_crypto_params *crypto_params
 					uint32_t value){
 	QDF_STATUS status = QDF_STATUS_E_INVAL;
 
+	crypto_debug("param %d, value %d", param, value);
 	switch (param) {
 	case WLAN_CRYPTO_PARAM_AUTH_MODE:
 		status = wlan_crypto_set_authmode(crypto_params, value);
@@ -2570,24 +2573,42 @@ bool wlan_crypto_rsn_info(struct wlan_objmgr_vdev *vdev,
 	struct wlan_crypto_params *my_crypto_params;
 	my_crypto_params = wlan_crypto_vdev_get_crypto_params(vdev);
 
-	if (!my_crypto_params)
+	if (!my_crypto_params) {
+		crypto_debug("vdev crypto params is NULL");
 		return false;
+	}
 	/*
 	 * Check peer's pairwise ciphers.
 	 * At least one must match with our unicast cipher
 	 */
-	if (!UCAST_CIPHER_MATCH(crypto_params, my_crypto_params))
+	if (!UCAST_CIPHER_MATCH(crypto_params, my_crypto_params)) {
+		crypto_debug("Unicast cipher match failed");
 		return false;
+	}
 	/*
 	 * Check peer's group cipher is our enabled multicast cipher.
 	 */
-	if (!MCAST_CIPHER_MATCH(crypto_params, my_crypto_params))
+	if (!MCAST_CIPHER_MATCH(crypto_params, my_crypto_params)) {
+		crypto_debug("Multicast cipher match failed");
 		return false;
+	}
 	/*
 	 * Check peer's key management class set (PSK or UNSPEC)
 	 */
-	if (!KEY_MGMTSET_MATCH(crypto_params, my_crypto_params))
+	if (!KEY_MGMTSET_MATCH(crypto_params, my_crypto_params)) {
+		crypto_debug("Key mgmt match failed");
+		return false;
+	}
+	if (wlan_crypto_vdev_is_pmf_enabled(vdev) &&
+	    !(crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) {
+		crypto_debug("Peer is not PMF capable");
+		return false;
+	}
+	if (!wlan_crypto_vdev_is_pmf_enabled(vdev) &&
+	    (crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) {
+		crypto_debug("Peer needs PMF, but vdev is not capable");
 		return false;
+	}
 
 	return true;
 }
@@ -3329,3 +3350,324 @@ void wlan_crypto_restore_keys(struct wlan_objmgr_vdev *vdev)
 						 WLAN_CRYPTO_ID);
 	}
 }
+
+/**
+ * wlan_crypto_check_open_none - called by ucfg to check for open security
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ *
+ * This function gets called from ucfg to check open security.
+ *
+ * Return: true or false
+ */
+bool wlan_crypto_check_open_none(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	struct wlan_crypto_comp_priv *crypto_priv;
+	struct wlan_crypto_params *crypto_params;
+	struct wlan_objmgr_vdev *vdev;
+	bool match = true;
+
+	if (!psoc) {
+		crypto_err("PSOC is NULL");
+		return false;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_CRYPTO_ID);
+	if (!vdev) {
+		crypto_err("vdev is NULL");
+		return false;
+	}
+
+	crypto_priv = (struct wlan_crypto_comp_priv *)
+		       wlan_get_vdev_crypto_obj(vdev);
+
+	if (!crypto_priv) {
+		crypto_err("crypto_priv NULL");
+		match = false;
+		goto send_res;
+	}
+
+	crypto_params = &crypto_priv->crypto_params;
+
+	if (crypto_params->mcastcipherset != WLAN_CRYPTO_CIPHER_NONE) {
+		match = false;
+		goto send_res;
+	}
+
+	if ((crypto_params->authmodeset != WLAN_CRYPTO_AUTH_AUTO) &&
+	    (crypto_params->authmodeset != WLAN_CRYPTO_AUTH_NONE))
+		match = false;
+
+send_res:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
+
+	return match;
+}
+
+/**
+ * wlan_crypto_check_wep - called by ucfg to check for WEP security
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ *
+ * This function gets called from ucfg to check WEP security.
+ *
+ * Return: true or false
+ */
+bool wlan_crypto_check_wep(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	struct wlan_crypto_comp_priv *crypto_priv;
+	struct wlan_crypto_params *crypto_params;
+	struct wlan_objmgr_vdev *vdev;
+	bool match = true;
+
+	if (!psoc) {
+		crypto_err("PSOC is NULL");
+		return false;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_CRYPTO_ID);
+	if (!vdev) {
+		crypto_err("vdev is NULL");
+		return false;
+	}
+
+	crypto_priv = (struct wlan_crypto_comp_priv *)
+		       wlan_get_vdev_crypto_obj(vdev);
+
+	if (!crypto_priv) {
+		crypto_err("crypto_priv NULL");
+		match = false;
+		goto send_res;
+	}
+
+	crypto_params = &crypto_priv->crypto_params;
+
+	if ((crypto_params->ucastcipherset != WLAN_CRYPTO_CIPHER_WEP) &&
+	    (crypto_params->ucastcipherset != WLAN_CRYPTO_CIPHER_WEP_40) &&
+	    (crypto_params->ucastcipherset != WLAN_CRYPTO_CIPHER_WEP_104)) {
+		match = false;
+		goto send_res;
+	}
+	if ((crypto_params->mcastcipherset != WLAN_CRYPTO_CIPHER_WEP) &&
+	    (crypto_params->mcastcipherset != WLAN_CRYPTO_CIPHER_WEP_40) &&
+	    (crypto_params->mcastcipherset != WLAN_CRYPTO_CIPHER_WEP_104)) {
+		match = false;
+		goto send_res;
+	}
+	if (crypto_params->ucastcipherset != crypto_params->mcastcipherset) {
+		match = false;
+		goto send_res;
+	}
+	if ((crypto_params->authmodeset != WLAN_CRYPTO_AUTH_AUTO) &&
+	    (crypto_params->authmodeset != WLAN_CRYPTO_AUTH_OPEN) &&
+	    (crypto_params->authmodeset != WLAN_CRYPTO_AUTH_SHARED)) {
+		match = false;
+	}
+send_res:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
+
+	return match;
+}
+
+static QDF_STATUS
+wlan_get_crypto_params_from_rsn_ie(struct wlan_crypto_params *crypto_params,
+				   uint8_t *ie_ptr, uint16_t ie_len)
+{
+	const uint8_t *rsn_ie = NULL;
+	QDF_STATUS status;
+
+	qdf_mem_zero(crypto_params, sizeof(struct wlan_crypto_params));
+	rsn_ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSN, ie_ptr, ie_len);
+	if (!rsn_ie) {
+		crypto_err("RSN IE NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = wlan_crypto_rsnie_check(crypto_params, (uint8_t *)rsn_ie);
+	if (QDF_STATUS_SUCCESS != status) {
+		crypto_err("RSN IE check failed");
+		return status;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS
+wlan_get_crypto_params_from_wpa_ie(struct wlan_crypto_params *crypto_params,
+				   uint8_t *ie_ptr, uint16_t ie_len)
+{
+	const uint8_t *wpa_ie = NULL;
+	uint32_t wpa_oui;
+	QDF_STATUS status;
+
+	qdf_mem_zero(crypto_params, sizeof(struct wlan_crypto_params));
+
+	wpa_oui = WLAN_WPA_SEL(WLAN_WPA_OUI_TYPE);
+	wpa_ie = wlan_get_vendor_ie_ptr_from_oui((uint8_t *)&wpa_oui,
+						 WLAN_OUI_SIZE, ie_ptr, ie_len);
+	if (!wpa_ie) {
+		crypto_err("WPA IE NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = wlan_crypto_wpaie_check(crypto_params, (uint8_t *)wpa_ie);
+	if (QDF_STATUS_SUCCESS != status) {
+		crypto_err("WPA IE check failed");
+		return status;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+/**
+ * wlan_crypto_check_rsn_match - called by ucfg to check for RSN match
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ * @ie_ptr: pointer to IEs
+ * @ie_len: IE length
+ *
+ * This function gets called from ucfg to check RSN match.
+ *
+ * Return: true or false
+ */
+bool wlan_crypto_check_rsn_match(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vdev_id, uint8_t *ie_ptr,
+				 uint16_t ie_len)
+{
+	struct wlan_crypto_params peer_crypto_params;
+	struct wlan_objmgr_vdev *vdev;
+	bool match = true;
+	QDF_STATUS status;
+
+	if (!psoc) {
+		crypto_err("PSOC is NULL");
+		return false;
+	}
+	status = wlan_get_crypto_params_from_rsn_ie(&peer_crypto_params,
+						    ie_ptr, ie_len);
+	if (QDF_STATUS_SUCCESS != status) {
+		crypto_err("get crypto prarams from RSN IE failed");
+		return false;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_CRYPTO_ID);
+	if (!vdev) {
+		crypto_err("vdev is NULL");
+		return false;
+	}
+
+	match = wlan_crypto_rsn_info(vdev, &peer_crypto_params);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
+
+	return match;
+}
+
+/**
+ * wlan_crypto_check_wpa_match - called by ucfg to check for WPA match
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ * @ie_ptr: pointer to IEs
+ * @ie_len: IE length
+ *
+ * This function gets called from ucfg to check WPA match.
+ *
+ * Return: true or false
+ */
+bool wlan_crypto_check_wpa_match(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vdev_id, uint8_t *ie_ptr,
+				 uint16_t ie_len)
+{
+	struct wlan_crypto_params peer_crypto_params;
+	struct wlan_objmgr_vdev *vdev;
+	bool match = true;
+	QDF_STATUS status;
+
+	if (!psoc) {
+		crypto_err("PSOC is NULL");
+		return false;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_CRYPTO_ID);
+	if (!vdev) {
+		crypto_err("vdev is NULL");
+		return false;
+	}
+
+	status = wlan_get_crypto_params_from_wpa_ie(&peer_crypto_params,
+						    ie_ptr, ie_len);
+	if (QDF_STATUS_SUCCESS != status) {
+		crypto_err("get crypto prarams from WPA IE failed");
+		match = false;
+		goto send_res;
+	}
+	match = wlan_crypto_rsn_info(vdev, &peer_crypto_params);
+send_res:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
+
+	return match;
+}
+
+
+static void
+wlan_crypto_merge_prarams(struct wlan_crypto_params *dst_params,
+			  struct wlan_crypto_params *src_params)
+{
+	dst_params->authmodeset |= src_params->authmodeset;
+	dst_params->ucastcipherset |= src_params->ucastcipherset;
+	dst_params->mcastcipherset |= src_params->mcastcipherset;
+	dst_params->mgmtcipherset |= src_params->mgmtcipherset;
+	dst_params->cipher_caps |= src_params->cipher_caps;
+	dst_params->key_mgmt |= src_params->key_mgmt;
+	dst_params->rsn_caps |= src_params->rsn_caps;
+}
+
+QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev,
+						uint8_t *ie_ptr,
+						uint16_t ie_len)
+{
+	struct wlan_crypto_params crypto_params;
+	QDF_STATUS status;
+	struct wlan_crypto_params *vdev_crypto_params;
+	struct wlan_crypto_comp_priv *crypto_priv;
+	bool send_fail = false;
+
+	if (!vdev) {
+		crypto_err("VDEV is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!ie_ptr) {
+		crypto_err("IE ptr is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	crypto_priv = (struct wlan_crypto_comp_priv *)
+		       wlan_get_vdev_crypto_obj(vdev);
+
+	if (!crypto_priv) {
+		crypto_err("crypto_priv NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	vdev_crypto_params = &crypto_priv->crypto_params;
+
+	qdf_mem_zero(vdev_crypto_params, sizeof(struct wlan_crypto_params));
+	status = wlan_get_crypto_params_from_rsn_ie(&crypto_params,
+						    ie_ptr, ie_len);
+	if (QDF_STATUS_SUCCESS == status) {
+		wlan_crypto_merge_prarams(vdev_crypto_params, &crypto_params);
+	} else {
+		crypto_err("get crypto prarams from RSN IE failed");
+		send_fail = true;
+	}
+
+	status = wlan_get_crypto_params_from_wpa_ie(&crypto_params,
+						    ie_ptr, ie_len);
+	if (QDF_STATUS_SUCCESS == status) {
+		wlan_crypto_merge_prarams(vdev_crypto_params, &crypto_params);
+		send_fail = false;
+	} else {
+		crypto_err("get crypto prarams from WPA IE failed");
+	}
+
+	return send_fail ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
+}