wlan: Add PMF (802.11w) support for station mode
These changes add Protected Management Frames (802.11w) support for
the device in station mode.
Change-Id: I2cdc60c4a9ed3ab40303de11ca3b679a9fe1d455
CRs-Fixed: 452422, 452831, 455139, 450564, 452558
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 668b4ae..8a7c095 100755
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -109,6 +109,9 @@
#ifdef FEATURE_WLAN_CCX
v_U8_t ccpRSNOui06[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x40, 0x96, 0x00 }; // CCKM
#endif /* FEATURE_WLAN_CCX */
+#ifdef WLAN_FEATURE_11W
+v_U8_t ccpRSNOui07[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x06 }; // RSN-PSK-SHA256
+#endif
#if defined(WLAN_FEATURE_VOWIFI_11R)
// Offset where the EID-Len-IE, start.
@@ -120,6 +123,13 @@
void hdd_ResetCountryCodeAfterDisAssoc(hdd_adapter_t *pAdapter);
+#ifdef WLAN_FEATURE_11W
+void hdd_indicateUnprotMgmtFrame(hdd_adapter_t *pAdapter,
+ tANI_U32 nFrameLength,
+ tANI_U8* pbFrames,
+ tANI_U8 frameType );
+#endif
+
v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx,
eConnectionState connState )
{
@@ -1329,7 +1339,10 @@
"Cannot register STA with TL. Failed with vosStatus = %d [%08lX]",
vosStatus, vosStatus );
}
-
+#ifdef WLAN_FEATURE_11W
+ vos_mem_zero( &pAdapter->hdd_stats.hddPmfStats,
+ sizeof(pAdapter->hdd_stats.hddPmfStats) );
+#endif
// Start the Queue
netif_tx_wake_all_queues(dev);
}
@@ -2320,6 +2333,13 @@
wlan_hdd_tdls_mgmt_completion_callback(pAdapter, pRoamInfo->reasonCode);
break;
#endif
+#ifdef WLAN_FEATURE_11W
+ case eCSR_ROAM_UNPROT_MGMT_FRAME_IND:
+ hdd_indicateUnprotMgmtFrame(pAdapter, pRoamInfo->nFrameLength,
+ pRoamInfo->pbFrames,
+ pRoamInfo->frameType);
+ break;
+#endif
default:
break;
}
@@ -2355,6 +2375,12 @@
auth_type = eCSR_AUTH_TYPE_CCKM_RSN;
} else
#endif /* FEATURE_WLAN_CCX */
+#ifdef WLAN_FEATURE_11W
+ if (memcmp(auth_suite , ccpRSNOui07, 4) == 0)
+ {
+ auth_type = eCSR_AUTH_TYPE_RSN_PSK_SHA256;
+ } else
+#endif
{
auth_type = eCSR_AUTH_TYPE_UNKNOWN;
}
@@ -2470,6 +2496,10 @@
eCsrEncryptionType *pEncryptType,
eCsrEncryptionType *mcEncryptType,
eCsrAuthType *pAuthType,
+#ifdef WLAN_FEATURE_11W
+ u_int8_t *pMfpRequired,
+ u_int8_t *pMfpCapable,
+#endif
u_int16_t gen_ie_len,
u_int8_t *gen_ie)
{
@@ -2522,6 +2552,10 @@
*pEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.pwise_cipher_suites[0]);
//dot11RSNIE.gp_cipher_suite_count
*mcEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.gp_cipher_suite);
+#ifdef WLAN_FEATURE_11W
+ *pMfpRequired = (dot11RSNIE.RSN_Cap[0] >> 6) & 0x1 ;
+ *pMfpCapable = (dot11RSNIE.RSN_Cap[0] >> 7) & 0x1 ;
+#endif
// Set the PMKSA ID Cache for this interface
for (i=0; i<dot11RSNIE.pmkid_count; i++)
{
@@ -2590,6 +2624,10 @@
v_U32_t status = 0;
eCsrEncryptionType RSNEncryptType;
eCsrEncryptionType mcRSNEncryptType;
+#ifdef WLAN_FEATURE_11W
+ u_int8_t RSNMfpRequired;
+ u_int8_t RSNMfpCapable;
+#endif
struct ether_addr bSsid; // MAC address of assoc peer
// MAC address of assoc peer
// But, this routine is only called when we are NOT associated.
@@ -2611,6 +2649,10 @@
&RSNEncryptType,
&mcRSNEncryptType,
RSNAuthType,
+#ifdef WLAN_FEATURE_11W
+ &RSNMfpRequired,
+ &RSNMfpCapable,
+#endif
pWextState->WPARSNIE[1]+2,
pWextState->WPARSNIE);
if (status == 0)
@@ -2621,6 +2663,11 @@
pWextState->roamProfile.EncryptionType.encryptionType[0] = RSNEncryptType; // Use the cipher type in the RSN IE
pWextState->roamProfile.mcEncryptionType.encryptionType[0] = mcRSNEncryptType;
+
+#ifdef WLAN_FEATURE_11W
+ pWextState->roamProfile.MFPRequired = RSNMfpRequired;
+ pWextState->roamProfile.MFPCapable = RSNMfpCapable;
+#endif
hddLog( LOG1, "%s: CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d", __func__, *RSNAuthType, RSNEncryptType, mcRSNEncryptType);
}
return 0;
@@ -2698,6 +2745,12 @@
} else
#endif
+#ifdef WLAN_FEATURE_11W
+ if (RSNAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) {
+ pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN_PSK_SHA256;
+ } else
+#endif
+
if( (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)
== IW_AUTH_KEY_MGMT_802_1X) {
pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN;
@@ -3222,6 +3275,9 @@
case eCSR_AUTH_TYPE_FT_RSN_PSK:
#endif
case eCSR_AUTH_TYPE_RSN_PSK:
+#ifdef WLAN_FEATURE_11W
+ case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
+#endif
hddLog(LOG1,"%s called with unknown auth type", __func__);
wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM;
return -EIO;
@@ -3415,3 +3471,77 @@
}
}
+#ifdef WLAN_FEATURE_11W
+/**---------------------------------------------------------------------------
+
+ \brief hdd_indicateUnprotMgmtFrame -
+ This function forwards the unprotected management frame to the supplicant
+ \param - pAdapter - Pointer to HDD adapter
+ - nFrameLength - Length of the unprotected frame being passed
+ - pbFrames - Pointer to the frame buffer
+ - frameType - 802.11 frame type
+ \return - nothing
+
+ --------------------------------------------------------------------------*/
+void hdd_indicateUnprotMgmtFrame( hdd_adapter_t *pAdapter,
+ tANI_U32 nFrameLength,
+ tANI_U8* pbFrames,
+ tANI_U8 frameType )
+{
+ tANI_U8 type = 0;
+ tANI_U8 subType = 0;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
+ __func__, frameType, nFrameLength);
+
+ /* Sanity Checks */
+ if (NULL == pAdapter)
+ {
+ hddLog( LOGE, FL("pAdapter is NULL"));
+ return;
+ }
+
+ if (NULL == pAdapter->dev)
+ {
+ hddLog( LOGE, FL("pAdapter->dev is NULL"));
+ return;
+ }
+
+ if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
+ {
+ hddLog( LOGE, FL("pAdapter has invalid magic"));
+ return;
+ }
+
+ if( !nFrameLength )
+ {
+ hddLog( LOGE, FL("Frame Length is Invalid ZERO"));
+ return;
+ }
+
+ if (NULL == pbFrames) {
+ hddLog( LOGE, FL("pbFrames is NULL"));
+ return;
+ }
+
+ type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
+ subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
+
+ /* Get pAdapter from Destination mac address of the frame */
+ if (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_DISASSOC)
+ {
+ cfg80211_send_unprot_disassoc(pAdapter->dev, pbFrames, nFrameLength);
+ pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx++;
+ }
+ else if (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_DEAUTH)
+ {
+ cfg80211_send_unprot_deauth(pAdapter->dev, pbFrames, nFrameLength);
+ pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx++;
+ }
+ else
+ {
+ hddLog( LOGE, FL("Frame type %d and subtype %d are not valid"), type, subType);
+ return;
+ }
+}
+#endif
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 5fa9cce..58fffeb 100755
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -164,6 +164,9 @@
#ifdef FEATURE_WLAN_WAPI
WLAN_CIPHER_SUITE_SMS4,
#endif
+#ifdef WLAN_FEATURE_11W
+ WLAN_CIPHER_SUITE_AES_CMAC,
+#endif
};
static inline int is_broadcast_ether_addr(const u8 *addr)
@@ -704,6 +707,13 @@
sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
(v_U8_t*)P2P_ACTION_FRAME,
P2P_ACTION_FRAME_SIZE );
+
+#ifdef WLAN_FEATURE_11W
+ /* SA Query Response Action Frame */
+ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)SA_QUERY_FRAME_RSP,
+ SA_QUERY_FRAME_RSP_SIZE );
+#endif /* WLAN_FEATURE_11W */
}
void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
@@ -743,6 +753,13 @@
sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
(v_U8_t*)P2P_ACTION_FRAME,
P2P_ACTION_FRAME_SIZE );
+
+#ifdef WLAN_FEATURE_11W
+ /* SA Query Response Action Frame */
+ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
+ (v_U8_t*)SA_QUERY_FRAME_RSP,
+ SA_QUERY_FRAME_RSP_SIZE );
+#endif /* WLAN_FEATURE_11W */
}
#ifdef FEATURE_WLAN_WAPI
@@ -3111,11 +3128,23 @@
return 0;
}
#endif
+
#ifdef FEATURE_WLAN_CCX
case WLAN_CIPHER_SUITE_KRK:
setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
break;
#endif
+
+#ifdef WLAN_FEATURE_11W
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
+ /* Temporarily we will ignore the setting of the IGTK. Once the Riva
+ firmware is modified to handle the IGTK, then we will proceeed normally.
+ For now, we just return success. */
+ return 0;
+ /* break; */
+#endif
+
default:
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
__func__, params->cipher);
@@ -4811,6 +4840,11 @@
pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
pRoamProfile->ChannelInfo.numOfChannels = 1;
}
+ else
+ {
+ pRoamProfile->ChannelInfo.ChannelList = NULL;
+ pRoamProfile->ChannelInfo.numOfChannels = 0;
+ }
/* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
* has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
@@ -5365,6 +5399,10 @@
return status;
}
+#ifdef WLAN_FEATURE_11W
+ pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
+#endif
+
/*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
if (req->ie_len)
{
diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c
index 806c716..0b751c7 100644
--- a/CORE/HDD/src/wlan_hdd_p2p.c
+++ b/CORE/HDD/src/wlan_hdd_p2p.c
@@ -554,6 +554,9 @@
tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
tActionFrmType actionFrmType;
bool noack = 0;
+#ifdef WLAN_FEATURE_11W
+ tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
hdd_adapter_t *goAdapter;
@@ -785,7 +788,17 @@
hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__);
}
}
-
+#ifdef WLAN_FEATURE_11W
+ if ((type == SIR_MAC_MGMT_FRAME) &&
+ (subType == SIR_MAC_MGMT_ACTION) &&
+ (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query");
+ // Since this is an SA Query Action Frame, we have to protect it
+ WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]);
+ }
+#endif
if (eHAL_STATUS_SUCCESS !=
sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
sessionId, buf, len, extendedWait, noack))
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 74b4bcc..50ce53c 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -208,6 +208,9 @@
#ifdef FEATURE_WLAN_TDLS
#define WE_GET_TDLS_PEERS 8
#endif
+#ifdef WLAN_FEATURE_11W
+#define WE_GET_11W_INFO 9
+#endif
/* Private ioctls and their sub-ioctls */
#define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6)
@@ -533,6 +536,9 @@
case eCSR_AUTH_TYPE_FT_RSN_PSK:
#endif
case eCSR_AUTH_TYPE_RSN_PSK:
+#ifdef WLAN_FEATURE_11W
+ case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
+#endif
rsnType = eANI_BOOLEAN_TRUE;
break;
//case eCSR_AUTH_TYPE_FAILED:
@@ -904,6 +910,11 @@
pWextState->roamProfile.nRSNReqIELength = 0;
pWextState->roamProfile.pRSNReqIE = (tANI_U8 *)NULL;
+#ifdef FEATURE_WLAN_WAPI
+ pWextState->roamProfile.nWAPIReqIELength = 0;
+ pWextState->roamProfile.pWAPIReqIE = (tANI_U8 *)NULL;
+#endif
+
pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
pWextState->roamProfile.pAddIEScan = (tANI_U8 *)NULL;
pWextState->roamProfile.nAddIEScanLength = 0;
@@ -921,6 +932,12 @@
pWextState->roamProfile.AuthType.numEntries = 1;
pWextState->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+#ifdef WLAN_FEATURE_11W
+ pWextState->roamProfile.MFPEnabled = eANI_BOOLEAN_FALSE;
+ pWextState->roamProfile.MFPRequired = 0;
+ pWextState->roamProfile.MFPCapable = 0;
+#endif
+
pWextState->authKeyMgmt = 0;
for (i=0; i < CSR_MAX_NUM_KEY; i++)
@@ -4043,6 +4060,9 @@
{
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
int sub_cmd = wrqu->data.flags;
+#ifdef WLAN_FEATURE_11W
+ hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
+#endif
if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
{
@@ -4255,6 +4275,25 @@
break;
}
#endif
+#ifdef WLAN_FEATURE_11W
+ case WE_GET_11W_INFO:
+ {
+ hddLog(LOGE, "WE_GET_11W_ENABLED = %d", pWextState->roamProfile.MFPEnabled );
+
+ snprintf(extra, WE_MAX_STR_LEN,
+ "\n BSSID %02X:%02X:%02X:%02X:%02X:%02X, Is PMF Assoc? %d"
+ "\n Number of Unprotected Disassocs %d"
+ "\n Number of Unprotected Deauths %d",
+ (*pWextState->roamProfile.BSSIDs.bssid)[0], (*pWextState->roamProfile.BSSIDs.bssid)[1],
+ (*pWextState->roamProfile.BSSIDs.bssid)[2], (*pWextState->roamProfile.BSSIDs.bssid)[3],
+ (*pWextState->roamProfile.BSSIDs.bssid)[4], (*pWextState->roamProfile.BSSIDs.bssid)[5],
+ pWextState->roamProfile.MFPEnabled, pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx,
+ pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx);
+
+ wrqu->data.length = strlen(extra)+1;
+ break;
+ }
+#endif
default:
{
hddLog(LOGE, "Invalid IOCTL command %d \n", sub_cmd );
@@ -6623,6 +6662,13 @@
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getTdlsPeers" },
#endif
+#ifdef WLAN_FEATURE_11W
+ {
+ WE_GET_11W_INFO,
+ 0,
+ IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
+ "getPMFInfo" },
+#endif
/* handlers for main ioctl */
{ WLAN_PRIV_SET_NONE_GET_NONE,
0,