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:
Ashok Kumar
2018-12-10 12:26:24 +05:30
committed by nshrivas
parent 5b92ee0716
commit 6f8b924d64
4 changed files with 230 additions and 5 deletions

View File

@@ -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_ */

View File

@@ -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;
/**

View File

@@ -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 */

View File

@@ -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);