diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h index 10b7d3c3cd41..430b076d6967 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h +++ b/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_ */ diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index 392e14447cfb..fcdec767cc30 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -19,6 +19,7 @@ /** * DOC: Public APIs for crypto service */ + #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #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; +}