qcacld-3.0: Add support for sae roaming with single PMK

Requirement is to allow station to just keeps only one
PMK1 and PMKID1 which gets derived while first connection
and re-use it for roaming to other AP which has some
specific VSIE.

To support this feature, STA should:
1. Set new flag in 11i params during RSO start/update when
initial connection is completed based on the VSIE in AP
beacon/probe response frame. This flag will allow fw to roam
to AP(s) which has VSIE with single PMK.
2. STA should dynamically enable this feature if below
vendor specific IE on AP’s Beacon or Probe Response at
the first connection:
Category 	Data
Type 		0xDD
Length 		0x05
OUI 		0x00 40 96
Type 		0x03
Data 		Don’t care
		(EX, 0x05)

Maintain a separate pmk information structure to support sae
roaming using single pmk.

Change-Id: I0aac7659cecd4d8aaff86c9715e512cf46f22615
CRs-Fixed: 2616035
This commit is contained in:
Abhinav Kumar 2020-02-21 14:23:07 +05:30 committed by nshrivas
parent 1589373241
commit c71e678b18
12 changed files with 251 additions and 13 deletions

View File

@ -112,10 +112,14 @@ struct wlan_mlme_roaming_config {
* roam config info
* @roam_sm: Structure containing roaming state related details
* @roam_config: Roaming configurations structure
* @sae_single_pmk: Details for sae roaming using single pmk
*/
struct wlan_mlme_roam {
struct wlan_mlme_roam_state_info roam_sm;
struct wlan_mlme_roaming_config roam_cfg;
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
struct wlan_mlme_sae_single_pmk sae_single_pmk;
#endif
};
/**

View File

@ -1432,7 +1432,7 @@ mlme_init_adaptive_11r_cfg(struct wlan_objmgr_psoc *psoc,
}
#endif
#ifdef WLAN_SAE_SINGLE_PMK
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
/**
* mlme_init_sae_single_pmk_cfg() - initialize sae_same_pmk_config
* flag
@ -1445,7 +1445,7 @@ static void
mlme_init_sae_single_pmk_cfg(struct wlan_objmgr_psoc *psoc,
struct wlan_mlme_lfr_cfg *lfr)
{
lfr->sae_same_pmk_feature_enabled = cfg_get(psoc, CFG_SAE_SINGLE_PMK);
lfr->sae_single_pmk_feature_enabled = cfg_get(psoc, CFG_SAE_SINGLE_PMK);
}
#else
@ -1475,6 +1475,7 @@ static void mlme_init_roam_offload_cfg(struct wlan_objmgr_psoc *psoc,
cfg_get(psoc, CFG_LFR_IDLE_ROAM_PACKET_COUNT);
lfr->idle_roam_min_rssi = cfg_get(psoc, CFG_LFR_IDLE_ROAM_MIN_RSSI);
lfr->idle_roam_band = cfg_get(psoc, CFG_LFR_IDLE_ROAM_BAND);
mlme_init_sae_single_pmk_cfg(psoc, lfr);
}
#else
@ -1708,7 +1709,6 @@ static void mlme_init_lfr_cfg(struct wlan_objmgr_psoc *psoc,
mlme_init_bss_load_trigger_params(psoc, &lfr->bss_load_trig);
mlme_init_adaptive_11r_cfg(psoc, lfr);
mlme_init_subnet_detection(psoc, lfr);
mlme_init_sae_single_pmk_cfg(psoc, lfr);
}
static uint32_t

View File

@ -2414,13 +2414,13 @@
#define LFR_SUBNET_DETECTION_ALL
#endif
#ifdef WLAN_SAE_SINGLE_PMK
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
/*
* <ini>
* sae_same_pmk_feature_enabled - Enable/disable sae single pmk feature.
* sae_single_pmk_feature_enabled - Enable/disable sae single pmk feature.
* @Min: 0
* @Max: 1
* @Default: 1
* @Default: 0
*
* This INI is to enable/disable SAE Roaming with same PMK/PMKID feature support
*
@ -2433,9 +2433,9 @@
* </ini>
*/
#define CFG_SAE_SINGLE_PMK CFG_INI_BOOL( \
"sae_same_pmk_feature_enabled", \
true, \
"Enable/disable SAE Roaming with same PMK/PMKID")
"sae_single_pmk_feature_enabled", \
false, \
"Enable/disable SAE Roaming with single PMK/PMKID")
#define SAE_SINGLE_PMK_ALL CFG(CFG_SAE_SINGLE_PMK)
#else

View File

@ -2302,6 +2302,41 @@ char *mlme_get_roam_trigger_str(uint32_t roam_scan_trigger);
*/
void mlme_get_converted_timestamp(uint32_t timestamp, char *time);
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
/**
* wlan_mlme_set_sae_single_pmk_bss_cap - API to set WPA3 single pmk AP IE
* @psoc: Pointer to psoc object
* @vdev_id: vdev id
* @val: value to be set
*
* Return : None
*/
void wlan_mlme_set_sae_single_pmk_bss_cap(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, bool val);
/**
* wlan_mlme_update_sae_single_pmk - API to update mlme_pmkid_info
* @vdev: vdev object
* @sae_single_pmk: pointer to sae_single_pmk_info struct
*
* Return : None
*/
void
wlan_mlme_update_sae_single_pmk(struct wlan_objmgr_vdev *vdev,
struct mlme_pmk_info *sae_single_pmk);
#else
static inline void
wlan_mlme_set_sae_single_pmk_bss_cap(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, bool val)
{
}
static inline void
wlan_mlme_update_sae_single_pmk(struct wlan_objmgr_vdev *vdev,
struct mlme_pmk_info *sae_single_pmk)
{
}
#endif
/**
* mlme_get_roam_fail_reason_str() - Get fail string from enum
* WMI_ROAM_FAIL_REASON_ID

View File

@ -67,6 +67,8 @@
#define CFG_MAX_STR_LEN 256
#define MAX_VENDOR_IES_LEN 1532
#define CFG_MAX_PMK_LEN 64
#define CFG_VALID_CHANNEL_LIST_STRING_LEN (CFG_VALID_CHANNEL_LIST_LEN * 4)
#define DEFAULT_ROAM_TRIGGER_BITMAP 0xFFFFFFFF
@ -1521,8 +1523,8 @@ struct bss_load_trigger {
* @fw_akm_bitmap: Supported Akm suites of firmware
* @roam_full_scan_period: Idle period in seconds between two successive
* full channel roam scans
* @sae_same_pmk_feature_enabled: Contains value of ini
* sae_same_pmk_feature_enabled
* @sae_single_pmk_feature_enabled: Contains value of ini
* sae_single_pmk_feature_enabled
*/
struct wlan_mlme_lfr_cfg {
bool mawc_roam_enabled;
@ -1626,8 +1628,8 @@ struct wlan_mlme_lfr_cfg {
uint32_t roam_scan_period_after_inactivity;
uint32_t fw_akm_bitmap;
uint32_t roam_full_scan_period;
#ifdef WLAN_SAE_SINGLE_PMK
bool sae_same_pmk_feature_enabled;
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
bool sae_single_pmk_feature_enabled;
#endif
};
@ -2321,6 +2323,27 @@ enum pkt_origin {
HOST
};
/**
* struct mlme_pmk_info - SAE Roaming using single pmk info
* @pmk: pmk
* @pmk_len: pmk length
*/
struct mlme_pmk_info {
uint8_t pmk[CFG_MAX_PMK_LEN];
uint8_t pmk_len;
};
/**
* struct wlan_mlme_sae_single_pmk - SAE Roaming using single pmk configuration
* structure
* @sae_single_pmk_ap: Current connected AP has VSIE or not
* @pmk_info: pmk information
*/
struct wlan_mlme_sae_single_pmk {
bool sae_single_pmk_ap;
struct mlme_pmk_info pmk_info;
};
/**
* struct mlme_roam_debug_info - Roam debug information storage structure.
* @trigger: Roam trigger related data

View File

@ -1206,6 +1206,26 @@ ucfg_mlme_get_delay_before_vdev_stop(struct wlan_objmgr_psoc *psoc,
QDF_STATUS
ucfg_mlme_get_roam_bmiss_final_bcnt(struct wlan_objmgr_psoc *psoc,
uint8_t *val);
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
/**
* ucfg_mlme_update_sae_single_pmk_info() - Update sae_single_pmk_info
* @vdev: pointer to VDEV common object
* @pmk_info: Pointer mlme pmkid info
*
* Return: None
*/
void
ucfg_mlme_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev,
struct mlme_pmk_info *pmk_info);
#else
static inline void
ucfg_mlme_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev,
struct mlme_pmk_info *pmk_info)
{
}
#endif
/**
* ucfg_mlme_get_roam_bmiss_first_bcnt() - Get roam bmiss final count
* @psoc: pointer to psoc object

View File

@ -3589,6 +3589,57 @@ void mlme_get_converted_timestamp(uint32_t timestamp, char *time)
(timestamp % 1000) * 1000);
}
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
void wlan_mlme_set_sae_single_pmk_bss_cap(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, bool val)
{
struct mlme_legacy_priv *mlme_priv;
struct wlan_objmgr_vdev *vdev;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
WLAN_MLME_OBJMGR_ID);
if (!vdev) {
mlme_err("get vdev failed");
return;
}
mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
if (!mlme_priv) {
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
mlme_legacy_err("vdev legacy private object is NULL");
return;
}
mlme_priv->mlme_roam.sae_single_pmk.sae_single_pmk_ap = val;
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
}
void wlan_mlme_update_sae_single_pmk(struct wlan_objmgr_vdev *vdev,
struct mlme_pmk_info *sae_single_pmk)
{
struct mlme_legacy_priv *mlme_priv;
uint32_t keymgmt;
bool is_sae_connection = false;
mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
if (!mlme_priv) {
mlme_legacy_err("vdev legacy private object is NULL");
return;
}
keymgmt = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
if (keymgmt & (1 << WLAN_CRYPTO_KEY_MGMT_SAE))
is_sae_connection = true;
if (mlme_priv->mlme_roam.sae_single_pmk.sae_single_pmk_ap &&
is_sae_connection)
mlme_priv->mlme_roam.sae_single_pmk.pmk_info = *sae_single_pmk;
}
#endif
char *mlme_get_roam_fail_reason_str(uint32_t result)
{
switch (result) {

View File

@ -963,6 +963,14 @@ ucfg_mlme_get_delay_before_vdev_stop(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_SUCCESS;
}
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
void ucfg_mlme_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev,
struct mlme_pmk_info *sae_single_pmk)
{
wlan_mlme_update_sae_single_pmk(vdev, sae_single_pmk);
}
#endif
QDF_STATUS
ucfg_mlme_get_roam_bmiss_final_bcnt(struct wlan_objmgr_psoc *psoc,
uint8_t *val)

View File

@ -21212,6 +21212,39 @@ static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
return errno;
}
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
/**
* wlan_update_sae_single_pmk_info() - Update a separate pmk information
* structure to support sae roaming using same pmk
* @vdev: vdev common object
* @pmk_cache: Pointer to pmk cache info
*
* Return: None
*/
static void wlan_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev,
tPmkidCacheInfo *pmk_cache)
{
struct mlme_pmk_info *pmk_info;
pmk_info = qdf_mem_malloc(sizeof(*pmk_info));
if (!pmk_info)
return;
qdf_mem_copy(pmk_info->pmk, pmk_cache->pmk, pmk_cache->pmk_len);
pmk_info->pmk_len = pmk_cache->pmk_len;
ucfg_mlme_update_sae_single_pmk_info(vdev, pmk_info);
qdf_mem_zero(pmk_info, sizeof(*pmk_info));
qdf_mem_free(pmk_info);
}
#else
static void wlan_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev,
tPmkidCacheInfo *pmk_cache)
{
}
#endif
static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
tPmkidCacheInfo *pmk_cache)
{
@ -21238,6 +21271,9 @@ static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
qdf_mem_zero(pmksa, sizeof(*pmksa));
qdf_mem_free(pmksa);
}
wlan_update_sae_single_pmk_info(vdev, pmk_cache);
hdd_objmgr_put_vdev(vdev);
return result;

View File

@ -710,6 +710,9 @@ struct bss_description {
#endif
uint32_t assoc_disallowed;
uint32_t adaptive_11r_ap;
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
uint32_t is_single_pmk;
#endif
/* Please keep the structure 4 bytes aligned above the ieFields */
uint32_t ieFields[1];
};

View File

@ -15262,6 +15262,35 @@ static void csr_handle_iot_ap_no_common_he_rates(struct mac_context *mac,
}
#endif
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
/**
* csr_update_sae_single_pmk_ap_cap() - Function to update sae single pmk ap ie
* @mac: pointer to mac context
* @bss_desc: BSS Descriptor
* @vdev_id: Vdev id
* @akm: Akm type
*
* Return: true if sae single pmk feature is enabled
*/
static void
csr_update_sae_single_pmk_ap_cap(struct mac_context *mac,
struct bss_description *bss_desc,
uint8_t vdev_id, enum csr_akm_type akm)
{
if (akm == eCSR_AUTH_TYPE_SAE &&
mac->mlme_cfg->lfr.sae_single_pmk_feature_enabled)
wlan_mlme_set_sae_single_pmk_bss_cap(mac->psoc, vdev_id,
bss_desc->is_single_pmk);
}
#else
static inline void
csr_update_sae_single_pmk_ap_cap(struct mac_context *mac,
struct bss_description *bss_desc,
uint8_t vdev_id, enum csr_akm_type akm)
{
}
#endif
/**
* The communication between HDD and LIM is thru mailbox (MB).
* Both sides will access the data structure "struct join_req".
@ -15414,6 +15443,9 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId,
akm = pProfile->negotiatedAuthType;
csr_join_req->akm = csr_convert_csr_to_ani_akm_type(akm);
csr_update_sae_single_pmk_ap_cap(mac, pBssDescription,
sessionId, akm);
if (bss_freq <= 2484 &&
!mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band &&
dot11mode == MLME_DOT11_MODE_11AC) {

View File

@ -2338,6 +2338,29 @@ static bool csr_is_assoc_disallowed(struct mac_context *mac_ctx,
return mbo_ie.assoc_disallowed.present;
}
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
/**
* csr_fill_single_pmk_ap_cap_from_scan_entry() - WAP3_SPMK VSIE from scan
* entry
* @bss_desc: BSS Descriptor
* @scan_entry: scan entry
*
* Return: None
*/
static void
csr_fill_single_pmk_ap_cap_from_scan_entry(struct bss_description *bss_desc,
struct scan_cache_entry *scan_entry)
{
bss_desc->is_single_pmk = util_scan_entry_single_pmk(scan_entry);
}
#else
static inline void
csr_fill_single_pmk_ap_cap_from_scan_entry(struct bss_description *bss_desc,
struct scan_cache_entry *scan_entry)
{
}
#endif
static QDF_STATUS csr_fill_bss_from_scan_entry(struct mac_context *mac_ctx,
struct scan_cache_entry *scan_entry,
struct tag_csrscan_result **p_result)
@ -2435,6 +2458,9 @@ static QDF_STATUS csr_fill_bss_from_scan_entry(struct mac_context *mac_ctx,
bss_desc->assoc_disallowed = csr_is_assoc_disallowed(mac_ctx,
scan_entry);
bss_desc->adaptive_11r_ap = scan_entry->adaptive_11r_ap;
csr_fill_single_pmk_ap_cap_from_scan_entry(bss_desc, scan_entry);
qdf_mem_copy(&bss_desc->mbssid_info, &scan_entry->mbssid_info,
sizeof(struct scan_mbssid_info));