qcacmn: Add support for pmksa handling
Added support for pmksa handling in crypto to support add_pmksa, del_pmksa and flush_pmksa function calls from cfg80211. Added support for adding pmkid in rsnie. Change-Id: Ic8add9635c2e7fd73da21b1305467e6500f6d73c CRs-Fixed: 2363632
This commit is contained in:
@@ -300,13 +300,15 @@ uint8_t *wlan_crypto_build_wpaie(struct wlan_objmgr_vdev *vdev,
|
||||
* wlan_crypto_build_rsnie - called by mlme to build rsnie
|
||||
* @vdev: vdev
|
||||
* @iebuf: ie buffer
|
||||
* @bssid: bssid mac address to add pmkid in rsnie
|
||||
*
|
||||
* This function gets called by mlme to build rsnie from given vdev
|
||||
*
|
||||
* Return: end of buffer
|
||||
*/
|
||||
uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev,
|
||||
uint8_t *iebuf);
|
||||
uint8_t *iebuf,
|
||||
struct qdf_mac_addr *bssid);
|
||||
|
||||
/**
|
||||
* wlan_crypto_wapiie_check - called by mlme to check the wapiie
|
||||
@@ -799,5 +801,29 @@ static inline QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif /* CRYPTO_SET_KEY_CONVERGED */
|
||||
/**
|
||||
* wlan_crypto_pmksa_flush - called to flush saved pmksa
|
||||
* @crypto_params: crypto_params
|
||||
*
|
||||
* This function flush saved pmksa from crypto params.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
QDF_STATUS wlan_crypto_pmksa_flush(struct wlan_crypto_params *crypto_params);
|
||||
|
||||
/**
|
||||
* wlan_crypto_set_vdev_param - called by ucfg to set crypto param
|
||||
* @vdev: vdev
|
||||
* @pmksa: pmksa to be set/del.
|
||||
* @set: set(set=1) or del(set=0) pmksa from the list.
|
||||
*
|
||||
* This function gets called from ucfg to set or del pmksa.
|
||||
* when given pmksa is NULL and set is 0, it is for flush all entries.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
QDF_STATUS wlan_crypto_set_del_pmksa(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_crypto_pmksa *pmksa,
|
||||
bool set);
|
||||
|
||||
#endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */
|
||||
|
@@ -48,6 +48,7 @@
|
||||
#define WLAN_CRYPTO_KEYIX_NONE ((uint16_t)-1)
|
||||
#define WLAN_CRYPTO_MAXKEYIDX (4)
|
||||
#define WLAN_CRYPTO_MAXIGTKKEYIDX (2)
|
||||
#define WLAN_CRYPTO_MAX_PMKID (3)
|
||||
|
||||
/* 40 bit wep key len */
|
||||
#define WLAN_CRYPTO_KEY_WEP40_LEN (5)
|
||||
@@ -205,6 +206,17 @@ enum wlan_crypto_key_type {
|
||||
WLAN_CRYPTO_KEY_TYPE_GROUP,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_crypto_pmksa - structure of crypto to contain pmkid
|
||||
* @bssid: bssid for which pmkid is saved
|
||||
* @pmkid: pmkid
|
||||
*/
|
||||
|
||||
struct wlan_crypto_pmksa {
|
||||
struct qdf_mac_addr bssid;
|
||||
uint8_t pmkid[PMKID_LEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_crypto_params - holds crypto params
|
||||
* @authmodeset: authentication mode
|
||||
@@ -212,8 +224,9 @@ enum wlan_crypto_key_type {
|
||||
* @mcastcipherset: multicast cipher
|
||||
* @mgmtcipherset: mgmt cipher
|
||||
* @cipher_caps: cipher capability
|
||||
* @rsn_caps: rsn_capability
|
||||
* @key_mgmt: key mgmt
|
||||
* @pmksa: pmksa
|
||||
* @rsn_caps: rsn_capability
|
||||
*
|
||||
* This structure holds crypto params for peer or vdev
|
||||
*/
|
||||
@@ -224,6 +237,7 @@ struct wlan_crypto_params {
|
||||
uint32_t mgmtcipherset;
|
||||
uint32_t cipher_caps;
|
||||
uint32_t key_mgmt;
|
||||
struct wlan_crypto_pmksa *pmksa[WLAN_CRYPTO_MAX_PMKID];
|
||||
uint16_t rsn_caps;
|
||||
};
|
||||
|
||||
@@ -235,6 +249,7 @@ typedef enum wlan_crypto_param_type {
|
||||
WLAN_CRYPTO_PARAM_CIPHER_CAP,
|
||||
WLAN_CRYPTO_PARAM_RSN_CAP,
|
||||
WLAN_CRYPTO_PARAM_KEY_MGMT,
|
||||
WLAN_CRYPTO_PARAM_PMKSA,
|
||||
} wlan_crypto_param_type;
|
||||
|
||||
/**
|
||||
|
@@ -311,6 +311,156 @@ int32_t wlan_crypto_get_peer_param(struct wlan_objmgr_peer *peer,
|
||||
return value;
|
||||
}
|
||||
qdf_export_symbol(wlan_crypto_get_peer_param);
|
||||
|
||||
static
|
||||
QDF_STATUS wlan_crypto_set_pmksa(struct wlan_crypto_params *crypto_params,
|
||||
struct wlan_crypto_pmksa *pmksa)
|
||||
{
|
||||
uint8_t i, first_available_slot;
|
||||
uint8_t slot_found = 0;
|
||||
|
||||
/* find the empty slot or slot with same bssid */
|
||||
for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) {
|
||||
if (!crypto_params->pmksa[i]) {
|
||||
if (!slot_found) {
|
||||
slot_found = 1;
|
||||
first_available_slot = i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (qdf_is_macaddr_equal(&pmksa->bssid,
|
||||
&crypto_params->pmksa[i]->bssid)) {
|
||||
/* free the current pmksa and use this slot */
|
||||
qdf_mem_free(crypto_params->pmksa[i]);
|
||||
crypto_params->pmksa[i] = pmksa;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == WLAN_CRYPTO_MAX_PMKID && !slot_found) {
|
||||
crypto_err("no entry available for pmksa");
|
||||
qdf_mem_free(pmksa);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
crypto_params->pmksa[first_available_slot] = pmksa;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params,
|
||||
struct wlan_crypto_pmksa *pmksa)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/* find slot with same bssid */
|
||||
for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) {
|
||||
if (!crypto_params->pmksa[i])
|
||||
continue;
|
||||
if (qdf_is_macaddr_equal(&pmksa->bssid,
|
||||
&crypto_params->pmksa[i]->bssid)) {
|
||||
qdf_mem_free(crypto_params->pmksa[i]);
|
||||
crypto_params->pmksa[i] = NULL;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_crypto_pmksa_flush(struct wlan_crypto_params *crypto_params)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) {
|
||||
if (!crypto_params->pmksa[i])
|
||||
continue;
|
||||
qdf_mem_free(crypto_params->pmksa[i]);
|
||||
crypto_params->pmksa[i] = NULL;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_crypto_set_del_pmksa(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_crypto_pmksa *pmksa,
|
||||
bool set)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_E_INVAL;
|
||||
struct wlan_crypto_comp_priv *crypto_priv;
|
||||
struct wlan_crypto_params *crypto_params;
|
||||
|
||||
if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
|
||||
if (!pmksa && set) {
|
||||
crypto_err("pmksa is NULL for set operation");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
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_INVAL;
|
||||
}
|
||||
|
||||
crypto_params = &crypto_priv->crypto_params;
|
||||
if (set) {
|
||||
status = wlan_crypto_set_pmksa(crypto_params, pmksa);
|
||||
/* Set pmksa */
|
||||
} else {
|
||||
/* del pmksa */
|
||||
if (!pmksa)
|
||||
status = wlan_crypto_pmksa_flush(crypto_params);
|
||||
else
|
||||
status = wlan_crypto_del_pmksa(crypto_params, pmksa);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_crypto_get_pmksa - called to get pmksa of bssid passed.
|
||||
* @vdev: vdev
|
||||
* @bssid: bssid
|
||||
*
|
||||
* This function gets called from to get pmksa for the bssid.
|
||||
*
|
||||
* Return: wlan_crypto_pmksa when match found else NULL.
|
||||
*/
|
||||
static struct wlan_crypto_pmksa *
|
||||
wlan_crypto_get_pmksa(struct wlan_objmgr_vdev *vdev, struct qdf_mac_addr *bssid)
|
||||
{
|
||||
struct wlan_crypto_comp_priv *crypto_priv;
|
||||
struct wlan_crypto_params *crypto_params;
|
||||
uint8_t i;
|
||||
|
||||
if (!bssid) {
|
||||
crypto_err("bssid is NULL");
|
||||
return NULL;
|
||||
}
|
||||
crypto_priv = (struct wlan_crypto_comp_priv *)
|
||||
wlan_get_vdev_crypto_obj(vdev);
|
||||
|
||||
if (!crypto_priv) {
|
||||
crypto_err("crypto_priv NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
crypto_params = &crypto_priv->crypto_params;
|
||||
|
||||
for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) {
|
||||
if (!crypto_params->pmksa[i])
|
||||
continue;
|
||||
if (qdf_is_macaddr_equal(bssid,
|
||||
&crypto_params->pmksa[i]->bssid)) {
|
||||
return crypto_params->pmksa[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/**
|
||||
* wlan_crypto_is_htallowed - called to check is HT allowed for cipher
|
||||
* @vdev: vdev
|
||||
@@ -2412,13 +2562,16 @@ uint8_t *wlan_crypto_build_wpaie(struct wlan_objmgr_vdev *vdev,
|
||||
* wlan_crypto_build_rsnie - called by mlme to build rsnie
|
||||
* @vdev: vdev
|
||||
* @iebuf: ie buffer
|
||||
* @bssid: bssid mac address to add pmkid in rsnie
|
||||
*
|
||||
* This function gets called by mlme to build rsnie from given vdev
|
||||
*
|
||||
* Return: end of buffer
|
||||
*/
|
||||
uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev,
|
||||
uint8_t *iebuf){
|
||||
uint8_t *iebuf,
|
||||
struct qdf_mac_addr *bssid)
|
||||
{
|
||||
uint8_t *frm = iebuf;
|
||||
uint8_t *selcnt;
|
||||
struct wlan_crypto_comp_priv *crypto_priv;
|
||||
@@ -2569,7 +2722,21 @@ add_rsn_caps:
|
||||
/* optional capabilities */
|
||||
if (crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) {
|
||||
/* PMK list */
|
||||
WLAN_CRYPTO_ADDSHORT(frm, 0);
|
||||
if (bssid) {
|
||||
struct wlan_crypto_pmksa *pmksa;
|
||||
|
||||
pmksa = wlan_crypto_get_pmksa(vdev, bssid);
|
||||
|
||||
if (pmksa) {
|
||||
WLAN_CRYPTO_ADDSHORT(frm, 1);
|
||||
qdf_mem_copy(frm, pmksa->pmkid, PMKID_LEN);
|
||||
frm += PMKID_LEN;
|
||||
} else {
|
||||
WLAN_CRYPTO_ADDSHORT(frm, 0);
|
||||
}
|
||||
} else
|
||||
WLAN_CRYPTO_ADDSHORT(frm, 0);
|
||||
|
||||
if (HAS_MGMT_CIPHER(crypto_params,
|
||||
WLAN_CRYPTO_CIPHER_AES_CMAC)) {
|
||||
RSN_ADD_CIPHER_TO_SUITE(frm,
|
||||
@@ -2593,6 +2760,20 @@ add_rsn_caps:
|
||||
WLAN_CRYPTO_CIPHER_AES_GMAC_256
|
||||
);
|
||||
}
|
||||
} else {
|
||||
/* PMK list */
|
||||
if (bssid) {
|
||||
struct wlan_crypto_pmksa *pmksa;
|
||||
|
||||
pmksa = wlan_crypto_get_pmksa(vdev, bssid);
|
||||
if (pmksa) {
|
||||
WLAN_CRYPTO_ADDSHORT(frm, 1);
|
||||
qdf_mem_copy(frm, pmksa->pmkid, PMKID_LEN);
|
||||
frm += PMKID_LEN;
|
||||
} else {
|
||||
WLAN_CRYPTO_ADDSHORT(frm, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate element length */
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2019 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
|
||||
@@ -214,9 +214,12 @@ static QDF_STATUS wlan_crypto_vdev_obj_destroy_handler(
|
||||
crypto_err("crypto_priv NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
wlan_objmgr_vdev_component_obj_detach(vdev,
|
||||
WLAN_UMAC_COMP_CRYPTO,
|
||||
(void *)crypto_priv);
|
||||
|
||||
wlan_crypto_pmksa_flush(&crypto_priv->crypto_params);
|
||||
wlan_crypto_free_key(crypto_priv);
|
||||
qdf_mem_free(crypto_priv);
|
||||
|
||||
|
Reference in New Issue
Block a user