From 4117d7a59c3df8babac9a57eaf54875e358780da Mon Sep 17 00:00:00 2001 From: "Padma, Santhosh Kumar" Date: Wed, 20 Dec 2017 17:39:33 +0530 Subject: [PATCH] qcacld-3.0: Add support for GMAC cipher suite Add changes to support GMAC group management cipher suite Change-Id: Ic4855b77268464a1ed61efcf213f76a2d99ff0c4 CRs-Fixed: 2164828 --- core/hdd/src/wlan_hdd_cfg80211.c | 12 ++ core/mac/inc/ani_system_defs.h | 4 +- .../src/pe/lim/lim_process_mlm_req_messages.c | 2 + .../src/pe/lim/lim_process_sme_req_messages.c | 5 +- core/sme/inc/csr_api.h | 8 +- core/sme/src/csr/csr_api_roam.c | 35 +++++- core/sme/src/csr/csr_api_scan.c | 26 ++++- core/sme/src/csr/csr_util.c | 106 ++++++++++++++++-- core/wma/src/wma_mgmt.c | 11 +- 9 files changed, 186 insertions(+), 23 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 9fae1ad087e1..95916337716a 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -199,6 +199,10 @@ static const u32 hdd_cipher_suites[] = { #endif #ifdef WLAN_FEATURE_11W WLAN_CIPHER_SUITE_AES_CMAC, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + WLAN_CIPHER_SUITE_BIP_GMAC_128, + WLAN_CIPHER_SUITE_BIP_GMAC_256, +#endif #endif WLAN_CIPHER_SUITE_GCMP, WLAN_CIPHER_SUITE_GCMP_256, @@ -15121,6 +15125,14 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy, case WLAN_CIPHER_SUITE_AES_CMAC: setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC; break; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_128; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_256; + break; +#endif #endif case WLAN_CIPHER_SUITE_GCMP: setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP; diff --git a/core/mac/inc/ani_system_defs.h b/core/mac/inc/ani_system_defs.h index 860828e2a27a..3d0ca6158e8c 100644 --- a/core/mac/inc/ani_system_defs.h +++ b/core/mac/inc/ani_system_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -96,6 +96,8 @@ typedef enum eAniEdType { /* Firmware uses key length to find GCMP 128 or 256 */ eSIR_ED_GCMP, eSIR_ED_GCMP_256, + eSIR_ED_AES_GMAC_128, + eSIR_ED_AES_GMAC_256, eSIR_ED_NOT_IMPLEMENTED = SIR_MAX_ENUM_SIZE } tAniEdType; diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 34c07a319acf..ef31e11d38cc 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1999,6 +1999,8 @@ lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) case eSIR_ED_GCMP_256: #ifdef WLAN_FEATURE_11W case eSIR_ED_AES_128_CMAC: + case eSIR_ED_AES_GMAC_128: + case eSIR_ED_AES_GMAC_256: #endif sta_idx = session->staId; break; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 1f414798182c..bd18c76fab0d 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1766,7 +1766,10 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) /* Record if management frames need to be protected */ #ifdef WLAN_FEATURE_11W - if (eSIR_ED_AES_128_CMAC == sme_join_req->MgmtEncryptionType) + if ((eSIR_ED_AES_128_CMAC == + sme_join_req->MgmtEncryptionType) || + (eSIR_ED_AES_GMAC_128 == sme_join_req->MgmtEncryptionType) || + (eSIR_ED_AES_GMAC_256 == sme_join_req->MgmtEncryptionType)) session->limRmfEnabled = 1; else session->limRmfEnabled = 0; diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index a312d7f794c5..ffb667b1bb8c 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -94,10 +94,9 @@ typedef enum { #endif /* FEATURE_WLAN_WAPI */ eCSR_ENCRYPT_TYPE_KRK, eCSR_ENCRYPT_TYPE_BTK, -#ifdef WLAN_FEATURE_11W - /* 11w BIP */ eCSR_ENCRYPT_TYPE_AES_CMAC, -#endif + eCSR_ENCRYPT_TYPE_AES_GMAC_128, + eCSR_ENCRYPT_TYPE_AES_GMAC_256, eCSR_ENCRYPT_TYPE_AES_GCMP, eCSR_ENCRYPT_TYPE_AES_GCMP_256, eCSR_ENCRYPT_TYPE_ANY, @@ -228,6 +227,8 @@ typedef enum { #define CSR_AES_KEY_LEN 16 #define CSR_AES_GCMP_KEY_LEN 16 #define CSR_AES_GCMP_256_KEY_LEN 32 +#define CSR_AES_GMAC_128_KEY_LEN 16 +#define CSR_AES_GMAC_256_KEY_LEN 32 #define CSR_MAX_TX_POWER (WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMAX) #define CSR_MAX_RSC_LEN 16 #ifdef FEATURE_WLAN_WAPI @@ -931,6 +932,7 @@ typedef struct csr_roam_profile { uint8_t MFPRequired; uint8_t MFPCapable; #endif + tAniEdType mgmt_encryption_type; tCsrKeys Keys; tCsrChannelInfo ChannelInfo; uint8_t operationChannel; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 41050407b15d..4704a366cb44 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10616,6 +10616,33 @@ csr_update_key_cmd(tpAniSirGlobal mac_ctx, struct csr_roam_session *session, CSR_AES_KEY_LEN); *is_key_valid = true; break; + + case eCSR_ENCRYPT_TYPE_AES_GMAC_128: + if (set_key->keyLength < CSR_AES_GMAC_128_KEY_LEN) { + sme_warn("Invalid AES GMAC 128 keylength [= %d]", + set_key->keyLength); + *is_key_valid = false; + return QDF_STATUS_E_INVAL; + } + set_key_cmd->keyLength = CSR_AES_GMAC_128_KEY_LEN; + qdf_mem_copy(set_key_cmd->Key, set_key->Key, + CSR_AES_GMAC_128_KEY_LEN); + *is_key_valid = true; + break; + + case eCSR_ENCRYPT_TYPE_AES_GMAC_256: + if (set_key->keyLength < CSR_AES_GMAC_256_KEY_LEN) { + sme_warn("Invalid AES GMAC 256 keylength [= %d]", + set_key->keyLength); + *is_key_valid = false; + return QDF_STATUS_E_INVAL; + } + set_key_cmd->keyLength = CSR_AES_GMAC_256_KEY_LEN; + qdf_mem_copy(set_key_cmd->Key, set_key->Key, + CSR_AES_GMAC_256_KEY_LEN); + *is_key_valid = true; + break; + #endif /* WLAN_FEATURE_11W */ default: /* for open security also we want to enqueue command */ @@ -14736,10 +14763,16 @@ bool csr_is_mfpc_capable(struct sDot11fIERSN *rsn) static void csr_set_mgmt_enc_type(tCsrRoamProfile *profile, tDot11fBeaconIEs *ies, tSirSmeJoinReq *csr_join_req) { + sme_debug("mgmt encryption type %d MFPe %d MFPr %d", + profile->mgmt_encryption_type, + profile->MFPEnabled, profile->MFPRequired); + if (profile->MFPEnabled) - csr_join_req->MgmtEncryptionType = eSIR_ED_AES_128_CMAC; + csr_join_req->MgmtEncryptionType = + profile->mgmt_encryption_type; else csr_join_req->MgmtEncryptionType = eSIR_ED_NONE; + if (profile->MFPEnabled && !(profile->MFPRequired) && !csr_is_mfpc_capable(&ies->RSN)) diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index f71d9b92ab78..fcfa39958da7 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -5246,6 +5246,27 @@ static eCsrEncryptionType csr_covert_enc_type_old(enum wlan_enc_type enc) } } +#ifdef WLAN_FEATURE_11W +/** + * csr_update_pmf_cap: Updates PMF cap + * @src_filter: Source filter + * @dst_filter: Destination filter + * + * Return: None + */ +static void csr_update_pmf_cap(tCsrScanResultFilter *src_filter, + struct scan_filter *dst_filter) { + + if (src_filter->MFPCapable || src_filter->MFPEnabled) + dst_filter->pmf_cap = WLAN_PMF_CAPABLE; + if (src_filter->MFPRequired) + dst_filter->pmf_cap = WLAN_PMF_REQUIRED; +} +#else +static inline void csr_update_pmf_cap(tCsrScanResultFilter *src_filter, + struct scan_filter *dst_filter) +{} +#endif static QDF_STATUS csr_prepare_scan_filter(tpAniSirGlobal mac_ctx, tCsrScanResultFilter *pFilter, struct scan_filter *filter) @@ -5324,10 +5345,7 @@ static QDF_STATUS csr_prepare_scan_filter(tpAniSirGlobal mac_ctx, filter->p2p_results = pFilter->p2pResult; - if (pFilter->MFPCapable || pFilter->MFPEnabled) - filter->pmf_cap = WLAN_PMF_CAPABLE; - if (pFilter->MFPRequired) - filter->pmf_cap = WLAN_PMF_REQUIRED; + csr_update_pmf_cap(pFilter, filter); if (pFilter->BSSType == eCSR_BSS_TYPE_INFRASTRUCTURE) filter->bss_type = WLAN_TYPE_BSS; diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index ea8fd058e276..ee1a655778ec 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -139,6 +139,16 @@ uint8_t csr_wapi_oui[][CSR_WAPI_OUI_SIZE] = { uint8_t csr_wme_info_oui[CSR_WME_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x02 }; uint8_t csr_wme_parm_oui[CSR_WME_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x02 }; +uint8_t csr_group_mgmt_oui[][CSR_RSN_OUI_SIZE] = { +#define ENUM_CMAC 0 + {0x00, 0x0F, 0xAC, 0x06}, +#define ENUM_GMAC_128 1 + {0x00, 0x0F, 0xAC, 0x0B}, +#define ENUM_GMAC_256 2 + {0x00, 0x0F, 0xAC, 0x0C}, +}; + + /* ////////////////////////////////////////////////////////////////////// */ /** @@ -3240,7 +3250,7 @@ static bool csr_is_auth_dpp_rsn(tpAniSirGlobal mac, * @suite_count: all supported akm suites count * @oui: Oui needs to be matched * - * Return: True if OUI is SAE, false otherwise + * Return: True if OUI is OWE, false otherwise */ static bool csr_is_auth_wpa_owe(tpAniSirGlobal mac, uint8_t all_suites[][CSR_RSN_OUI_SIZE], @@ -3301,6 +3311,40 @@ static bool csr_is_auth_wpa_psk(tpAniSirGlobal pMac, (pMac, AllSuites, cAllSuites, csr_wpa_oui[02], Oui); } +/* + * csr_is_group_mgmt_gmac_128() - check whether oui is GMAC_128 + * @mac: Global MAC context + * @all_suites: pointer to all supported akm suites + * @suite_count: all supported akm suites count + * @oui: Oui needs to be matched + * + * Return: True if OUI is GMAC_128, false otherwise + */ +static bool csr_is_group_mgmt_gmac_128(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match(pMac, AllSuites, cAllSuites, + csr_group_mgmt_oui[ENUM_GMAC_128], Oui); +} + +/* + * csr_is_group_mgmt_gmac_256() - check whether oui is GMAC_256 + * @mac: Global MAC context + * @all_suites: pointer to all supported akm suites + * @suite_count: all supported akm suites count + * @oui: Oui needs to be matched + * + * Return: True if OUI is GMAC_256, false otherwise + */ +static bool csr_is_group_mgmt_gmac_256(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match(pMac, AllSuites, cAllSuites, + csr_group_mgmt_oui[ENUM_GMAC_256], Oui); +} + static uint8_t csr_get_oui_index_from_cipher(eCsrEncryptionType enType) { uint8_t OUIIndex; @@ -3414,6 +3458,8 @@ static void csr_is_fils_auth(tpAniSirGlobal mac_ctx, * @capabilities: RSN capabilities * @negotiated_authtype: Negotiated auth type * @negotiated_mccipher: negotiated multicast cipher + * @gp_mgmt_cipher: group management cipher + * @mgmt_encryption_type: group management encryption type * * This routine will get all RSN information * @@ -3426,18 +3472,24 @@ static bool csr_get_rsn_information(tHalHandle hal, tCsrAuthList *auth_type, uint8_t *mcast_cipher, uint8_t *auth_suite, tCsrRSNCapabilities *capabilities, eCsrAuthType *negotiated_authtype, - eCsrEncryptionType *negotiated_mccipher) + eCsrEncryptionType *negotiated_mccipher, + uint8_t *gp_mgmt_cipher, + tAniEdType *mgmt_encryption_type) { tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); bool acceptable_cipher = false; + bool group_mgmt_acceptable_cipher = false; uint8_t c_ucast_cipher = 0; uint8_t c_mcast_cipher = 0; + uint8_t c_group_mgmt_cipher = 0; uint8_t c_auth_suites = 0, i; uint8_t unicast[CSR_RSN_OUI_SIZE]; uint8_t multicast[CSR_RSN_OUI_SIZE]; + uint8_t group_mgmt[CSR_RSN_OUI_SIZE]; uint8_t authsuites[CSR_RSN_MAX_AUTH_SUITES][CSR_RSN_OUI_SIZE]; uint8_t authentication[CSR_RSN_OUI_SIZE]; uint8_t mccipher_arr[CSR_RSN_MAX_MULTICAST_CYPHERS][CSR_RSN_OUI_SIZE]; + uint8_t group_mgmt_arr[CSR_RSN_MAX_MULTICAST_CYPHERS][CSR_RSN_OUI_SIZE]; eCsrAuthType neg_authtype = eCSR_AUTH_TYPE_UNKNOWN; if (!rsn_ie->present) @@ -3479,6 +3531,28 @@ static bool csr_get_rsn_information(tHalHandle hal, tCsrAuthList *auth_type, if (negotiated_mccipher) *negotiated_mccipher = mc_encryption->encryptionType[i]; + /* Group Management Cipher only for 11w */ + if (mgmt_encryption_type) { + c_group_mgmt_cipher++; + qdf_mem_copy(group_mgmt_arr, rsn_ie->gp_mgmt_cipher_suite, + CSR_RSN_OUI_SIZE); + if (csr_is_group_mgmt_gmac_128(mac_ctx, group_mgmt_arr, + c_group_mgmt_cipher, group_mgmt)) { + group_mgmt_acceptable_cipher = true; + *mgmt_encryption_type = eSIR_ED_AES_GMAC_128; + } else if (csr_is_group_mgmt_gmac_256(mac_ctx, group_mgmt_arr, + c_group_mgmt_cipher, group_mgmt)) { + group_mgmt_acceptable_cipher = true; + *mgmt_encryption_type = eSIR_ED_AES_GMAC_256; + } else { + /* Default is CMAC */ + group_mgmt_acceptable_cipher = true; + *mgmt_encryption_type = eSIR_ED_AES_128_CMAC; + qdf_mem_copy(group_mgmt, csr_group_mgmt_oui[ENUM_CMAC], + CSR_RSN_OUI_SIZE); + } + } + /* Initializing with false as it has true value already */ acceptable_cipher = false; for (i = 0; i < auth_type->numEntries; i++) { @@ -3587,6 +3661,10 @@ end: if (ucast_cipher) qdf_mem_copy(ucast_cipher, unicast, CSR_RSN_OUI_SIZE); + if (gp_mgmt_cipher && group_mgmt_acceptable_cipher) + qdf_mem_copy(gp_mgmt_cipher, group_mgmt, + CSR_RSN_OUI_SIZE); + if (auth_suite) qdf_mem_copy(auth_suite, authentication, CSR_RSN_OUI_SIZE); @@ -3715,7 +3793,7 @@ static bool csr_is_rsn_match(tHalHandle hHal, tCsrAuthList *pAuthType, pEnMcType, &pIes->RSN, NULL, NULL, NULL, NULL, pNegotiatedAuthType, - pNegotiatedMCCipher); + pNegotiatedMCCipher, NULL, NULL); #ifdef WLAN_FEATURE_11W /* If all the filter matches then finally checks for PMF capabilities */ if (fRSNMatch) @@ -3933,6 +4011,7 @@ uint8_t csr_construct_rsn_ie(tHalHandle hHal, uint32_t sessionId, uint8_t cbRSNIe = 0; uint8_t UnicastCypher[CSR_RSN_OUI_SIZE]; uint8_t MulticastCypher[CSR_RSN_OUI_SIZE]; + uint8_t gp_mgmt_cipher_suite[CSR_RSN_OUI_SIZE]; uint8_t AuthSuite[CSR_RSN_OUI_SIZE]; tCsrRSNAuthIe *pAuthSuite; tCsrRSNCapabilities RSNCapabilities; @@ -3975,10 +4054,12 @@ uint8_t csr_construct_rsn_ie(tHalHandle hHal, uint32_t sessionId, */ fRSNMatch = csr_get_rsn_information(hHal, &pProfile->AuthType, pProfile->negotiatedUCEncryptionType, - &pProfile->mcEncryptionType, - &pIesLocal->RSN, UnicastCypher, - MulticastCypher, AuthSuite, - &RSNCapabilities, &negAuthType, NULL); + &pProfile->mcEncryptionType, + &pIesLocal->RSN, UnicastCypher, + MulticastCypher, AuthSuite, + &RSNCapabilities, &negAuthType, NULL, + gp_mgmt_cipher_suite, + &pProfile->mgmt_encryption_type); if (!fRSNMatch) break; @@ -4055,8 +4136,8 @@ uint8_t csr_construct_rsn_ie(tHalHandle hHal, uint32_t sessionId, pGroupMgmtCipherSuite = (uint8_t *) pPMK + sizeof(uint16_t) + (pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE); - qdf_mem_copy(pGroupMgmtCipherSuite, csr_rsn_oui[07], - CSR_WPA_OUI_SIZE); + qdf_mem_copy(pGroupMgmtCipherSuite, + gp_mgmt_cipher_suite, CSR_RSN_OUI_SIZE); } #endif @@ -4860,7 +4941,12 @@ tAniEdType csr_translate_encrypt_type_to_ed_type(eCsrEncryptionType EncryptType) case eCSR_ENCRYPT_TYPE_AES_GCMP_256: edType = eSIR_ED_GCMP_256; break; - + case eCSR_ENCRYPT_TYPE_AES_GMAC_128: + edType = eSIR_ED_AES_GMAC_128; + break; + case eCSR_ENCRYPT_TYPE_AES_GMAC_256: + edType = eSIR_ED_AES_GMAC_256; + break; #endif } diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index c0a51263e5bd..ac57170bae66 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -1625,9 +1625,8 @@ static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle, { struct set_key_params params; QDF_STATUS status = QDF_STATUS_SUCCESS; -#ifdef WLAN_FEATURE_11W struct wma_txrx_node *iface = NULL; -#endif /* WLAN_FEATURE_11W */ + if ((key_params->key_type == eSIR_ED_NONE && key_params->key_len) || (key_params->key_type != eSIR_ED_NONE && !key_params->key_len)) { @@ -1734,6 +1733,10 @@ static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle, case eSIR_ED_AES_128_CMAC: params.key_cipher = WMI_CIPHER_AES_CMAC; break; + case eSIR_ED_AES_GMAC_128: + case eSIR_ED_AES_GMAC_256: + params.key_cipher = WMI_CIPHER_AES_GMAC; + break; #endif /* WLAN_FEATURE_11W */ /* Firmware uses length to detect GCMP 128/256*/ case eSIR_ED_GCMP: @@ -1776,7 +1779,9 @@ static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle, params.key_len = key_params->key_len; #ifdef WLAN_FEATURE_11W - if (key_params->key_type == eSIR_ED_AES_128_CMAC) { + if ((key_params->key_type == eSIR_ED_AES_128_CMAC) || + (key_params->key_type == eSIR_ED_AES_GMAC_128) || + (key_params->key_type == eSIR_ED_AES_GMAC_256)) { iface = &wma_handle->interfaces[key_params->vdev_id]; if (iface) { iface->key.key_length = key_params->key_len;