qcacld-3.0: Add force rsne override and use the RSNE passed by user

Adds support for INI "force_rsne_override" and vendor interface to
enable test mode to force rsne override. Once force rsne override
is set the driver will use the RSN IE's as-is from the connect
request. Exclusively used for the scenarios where the device is used as
a cert test bed and not recommended for production.
With force_rsne_override enabled in INI and once enabled from vendor
command driver will not validate the RSN IE's passed from user space
and thus induce improper IE as it is to test the peer.
Once the force_rsne_override is set, it will be active until its
disabled by vendor interface or driver unload.

If INI force_rsne_override is disabled, the force rsne override mode
cannot be enabled by vendor command.

Change-Id: Ic58474e7a18e6c1f944c61783f630af3953011c0
CRs-Fixed: 2263275
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index f452a82..0884b71 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -3224,7 +3224,29 @@
 #define CFG_ENABLE_POWERSAVE_OFFLOAD_MAX        (2)
 #define CFG_ENABLE_POWERSAVE_OFFLOAD_DEFAULT    (1)
 
-
+/*
+ * <ini>
+ * force_rsne_override - force rsnie override from user
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable/disable test mode to force rsne override used in
+ * security enhancement test cases to pass the RSNIE sent by user in
+ * assoc request.
+ *
+ * Related: None
+ *
+ * Supported Feature: STA
+ *
+ * Usage: internal
+ *
+ * </ini>
+ */
+#define CFG_FORCE_RSNE_OVERRIDE_NAME    "force_rsne_override"
+#define CFG_FORCE_RSNE_OVERRIDE_MIN     (0)
+#define CFG_FORCE_RSNE_OVERRIDE_MAX     (1)
+#define CFG_FORCE_RSNE_OVERRIDE_DEFAULT (0)
 
 /*--------------------------------------------------------------------------- 
   Type declarations
@@ -3841,6 +3863,7 @@
    uint32_t                    btc_dyn_bt_ext_len;
    uint32_t                    btc_dyn_num_bt_ext;
    bool                        indoor_channel_support;
+   bool                        force_rsne_override;
 
 } hdd_config_t;
 
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h
index a0e0daa..a6f5a35 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -1427,6 +1427,19 @@
     QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24 = 37,
     /* 8-bit unsigned value to set the beacon miss threshold in 5 GHz */
     QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5 = 38,
+
+    /*8-bit unsigned value indicating the driver to use the RSNE as-is from
+     * the connect interface. Exclusively used for the scenarios where the
+     * device is used as a test bed device with special functionality and
+     * not recommended for production. This helps driver to not validate the
+     * RSNE passed from user space and thus allow arbitrary IE data to be
+     * used for testing purposes.
+     * 1-enable, 0-disable.
+     * Applications set/reset this configuration. If not reset, this
+     * parameter remains in use until the driver is unloaded.
+     */
+    QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE = 39,
+
     /* keep last */
     QCA_WLAN_VENDOR_ATTR_CONFIG_LAST,
     QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index ec893f2..3e473cf 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1861,6 +1861,7 @@
 
     struct hdd_cache_channels *original_channels;
     struct mutex cache_channel_lock;
+    bool force_rsne_override;
 };
 
 /* Use to notify the TDLS or BTCOEX is mode enable */
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 22418a7..9f00164 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -4638,14 +4638,11 @@
         RSNIeLen = gen_ie_len - (2 + 4);
         // Unpack the WPA IE
         status = dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
-                            pRsnIe,
-                            RSNIeLen,
-                            &dot11WPAIE);
-        if (DOT11F_FAILED(status))
+                               pRsnIe, RSNIeLen, &dot11WPAIE);
+        if (!DOT11F_SUCCEEDED(status))
         {
             hddLog(LOGE,
-                   FL("Parse failure in hdd_ProcessGENIE (0x%08x)"),
-                   status);
+                   FL("Invalid RSN IE: parse status %d"), status);
             return -EINVAL;
         }
 
@@ -4669,12 +4666,44 @@
     }
     return 0;
 }
+
+/**
+ * hdd_set_def_rsne_override() - set default encryption type and auth type
+ * in profile.
+ * @roam_profile: pointer to adapter
+ * @auth_type: pointer to auth type
+ *
+ * Set default value of encryption type and auth type in profile to
+ * search the AP using filter, as in force_rsne_override the RSNIE can be
+ * currupt and we might not get the proper encryption type and auth type
+ * while parsing the RSNIE.
+ *
+ * Return: void
+ */
+static void hdd_set_def_rsne_override(
+                tCsrRoamProfile *roam_profile, eCsrAuthType *auth_type)
+{
+       hddLog( LOG1, FL("Set def values in roam profile"));
+       roam_profile->MFPCapable = roam_profile->MFPEnabled;
+       roam_profile->EncryptionType.numEntries = 2;
+       roam_profile->mcEncryptionType.numEntries = 2;
+       /* Use the cipher type in the RSN IE */
+       roam_profile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_AES;
+       roam_profile->EncryptionType.encryptionType[1] = eCSR_ENCRYPT_TYPE_TKIP;
+       roam_profile->mcEncryptionType.encryptionType[0] =
+              eCSR_ENCRYPT_TYPE_AES;
+       roam_profile->mcEncryptionType.encryptionType[1] =
+              eCSR_ENCRYPT_TYPE_TKIP;
+       *auth_type = eCSR_AUTH_TYPE_RSN_PSK;
+}
+
 int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType)
 {
     hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
     v_U32_t status = 0;
     eCsrEncryptionType RSNEncryptType;
     eCsrEncryptionType mcRSNEncryptType;
+    hdd_context_t *hdd_ctx;
 #ifdef WLAN_FEATURE_11W
     u_int8_t RSNMfpRequired = 0;
     u_int8_t RSNMfpCapable = 0;
@@ -4693,6 +4722,7 @@
     {
         return 0;
     }
+
     // The actual processing may eventually be more extensive than this.
     // Right now, just consume any PMKIDs that are  sent in by the app.
     status = hdd_ProcessGENIE(pAdapter,
@@ -4706,6 +4736,7 @@
 #endif
             pWextState->WPARSNIE[1]+2,
             pWextState->WPARSNIE);
+
     if (status == 0)
     {
         // Now copy over all the security attributes you have parsed out
@@ -4739,6 +4770,35 @@
           FL("CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d"),
           *RSNAuthType, RSNEncryptType, mcRSNEncryptType);
     }
+
+    hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
+    if (hdd_ctx->force_rsne_override &&
+        (pWextState->WPARSNIE[0] == DOT11F_EID_RSN)) {
+            hddLog(LOG1,
+              FL("Test mode enabled set def Auth and enc type. RSN IE passed in connect req:"));
+            vos_trace_hex_dump(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+                               pWextState->roamProfile.pRSNReqIE,
+                               pWextState->roamProfile.nRSNReqIELength);
+
+            pWextState->roamProfile.force_rsne_override = true;
+            hddLog(LOG1,
+                   FL("MFPEnabled %d"), pWextState->roamProfile.MFPEnabled);
+            /*
+             * Reset MFPEnabled if testmode RSNE passed doesnt have MFPR
+             * or MFPC bit set
+             */
+            if (pWextState->roamProfile.MFPEnabled &&
+                !(pWextState->roamProfile.MFPRequired ||
+                  pWextState->roamProfile.MFPCapable)) {
+                    hddLog( LOG1,FL("Reset MFPEnabled"));
+                    pWextState->roamProfile.MFPEnabled = 0;
+            }
+
+            /* If parsing failed set the def value for the roam profile */
+            if (status)
+                hdd_set_def_rsne_override(&pWextState->roamProfile,
+                                          RSNAuthType);
+    }
     return 0;
 }
 int hdd_set_csr_auth_type ( hdd_adapter_t  *pAdapter, eCsrAuthType RSNAuthType)
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index c399b20..6a2e23a 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -4028,6 +4028,13 @@
                 CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MIN,
                 CFG_BTC_2M_DYN_LONG_NUM_BT_EXT_MAX),
 
+  REG_VARIABLE(CFG_FORCE_RSNE_OVERRIDE_NAME, WLAN_PARAM_Integer,
+                hdd_config_t, force_rsne_override,
+                VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+                CFG_FORCE_RSNE_OVERRIDE_DEFAULT,
+                CFG_FORCE_RSNE_OVERRIDE_MIN,
+                CFG_FORCE_RSNE_OVERRIDE_MAX),
+
 };
 
 /*
@@ -4696,6 +4703,11 @@
             "Name = [%s] Value = [%u] ",
             CFG_ENABLE_POWERSAVE_OFFLOAD_NAME,
             pHddCtx->cfg_ini->enable_power_save_offload);
+
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+            "Name = [%s] Value = [%u] ",
+            CFG_FORCE_RSNE_OVERRIDE_NAME,
+            pHddCtx->cfg_ini->force_rsne_override);
 }
 
 
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 93619ae..4c615d2 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -7819,7 +7819,8 @@
 #define PARAM_GUARD_TIME QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME
 #define PARAM_BCNMISS_PENALTY_PARAM_COUNT \
         QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS
-
+#define PARAM_FORCE_RSN_IE \
+        QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE
 /*
  * hdd_set_qpower() - Process the qpower command and invoke the SME api
  * @hdd_ctx: hdd context
@@ -7876,6 +7877,7 @@
                                              { .type = NLA_U32},
                         [BEACON_MISS_THRESH_2_4] = { .type = NLA_U8 },
                         [BEACON_MISS_THRESH_5_0] = { .type = NLA_U8 },
+                        [PARAM_FORCE_RSN_IE] = {.type = NLA_U8 },
     };
 
     ENTER();
@@ -8057,6 +8059,21 @@
        hdd_set_qpower(pHddCtx, qpower);
     }
 
+    if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] &&
+        pHddCtx->cfg_ini->force_rsne_override) {
+        uint8_t force_rsne_override;
+
+        force_rsne_override =
+            nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE]);
+        if (force_rsne_override > 1) {
+            hddLog(LOGE, "Invalid test_mode %d", force_rsne_override);
+            ret_val = -EINVAL;
+        }
+        pHddCtx->force_rsne_override = force_rsne_override;
+        hddLog(LOG1, "force_rsne_override - %d",
+                             pHddCtx->force_rsne_override);
+    }
+
     EXIT();
     return ret_val;
 }
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index df64327..03f9bfd 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -1801,7 +1801,7 @@
                             pRsnIe,
                             RSNIeLen,
                             &dot11RSNIE);
-        if (DOT11F_FAILED(status))
+        if (!DOT11F_SUCCEEDED(status))
         {
              hddLog(LOGE,
                         FL("unpack failed for RSN IE status:(0x%08x)"),
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 87be3fc..3161471 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -1135,6 +1135,7 @@
     tSirMacPowerCapInfo powerCap;
     tSirSupChnl         supportedChannels;
     bool force_24ghz_in_ht20;
+    bool force_rsne_override;
     tSirBssDescription  bssDescription;
     /*
      * WARNING: Pls make bssDescription as last variable in struct
diff --git a/CORE/MAC/src/pe/lim/limSmeReqUtils.c b/CORE/MAC/src/pe/lim/limSmeReqUtils.c
index 33844ec..aa86ac9 100644
--- a/CORE/MAC/src/pe/lim/limSmeReqUtils.c
+++ b/CORE/MAC/src/pe/lim/limSmeReqUtils.c
@@ -702,7 +702,11 @@
     tANI_U8 valid = true;
 
 
-    if (!limIsRSNieValidInSmeReqMessage(pMac, &pJoinReq->rsnIE))
+    //If force_rsne_override is enabled that mean User has provided the
+    //test RSNIE which need to be send as it is in assoc req and thus RSNIE
+    //validity is not required.
+    if (!pJoinReq->force_rsne_override &&
+        !limIsRSNieValidInSmeReqMessage(pMac, &pJoinReq->rsnIE))
     {
         limLog(pMac, LOGE,
                FL("received SME_JOIN_REQ with invalid RSNIE"));
diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h
index 2acd939..ee17116 100644
--- a/CORE/SME/inc/csrApi.h
+++ b/CORE/SME/inc/csrApi.h
@@ -963,6 +963,7 @@
     tVOS_CON_MODE csrPersona;
     bool force_24ghz_in_ht20;
     tCsrBssid bssid_hint;
+    bool force_rsne_override;
 }tCsrRoamProfile;
 
 
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 0125f9a..ebd4cca 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -6661,6 +6661,7 @@
         pDstProfile->ieee80211d        = pSrcProfile->ieee80211d;
         pDstProfile->force_24ghz_in_ht20 =
                        pSrcProfile->force_24ghz_in_ht20;
+        pDstProfile->force_rsne_override = pSrcProfile->force_rsne_override;
         vos_mem_copy(&pDstProfile->Keys, &pSrcProfile->Keys,
                      sizeof(pDstProfile->Keys));
 #ifdef WLAN_FEATURE_VOWIFI_11R
@@ -13563,6 +13564,8 @@
             // Insert the RSN IE into the join request
             ieLen = csrRetrieveRsnIe( pMac, sessionId, pProfile, pBssDescription, pIes,
                     (tCsrRSNIe *)( wpaRsnIE ) );
+            pMsg->force_rsne_override =
+                            pProfile->force_rsne_override;
         }
 #ifdef FEATURE_WLAN_WAPI
         else if( csrIsProfileWapi( pProfile ) )
diff --git a/CORE/SME/src/csr/csrUtil.c b/CORE/SME/src/csr/csrUtil.c
index 7f63987..cb47e68 100644
--- a/CORE/SME/src/csr/csrUtil.c
+++ b/CORE/SME/src/csr/csrUtil.c
@@ -4773,8 +4773,10 @@
         }
         else 
 #endif
-        if(pProfile->nRSNReqIELength && pProfile->pRSNReqIE)
+        if(pProfile->force_rsne_override &&
+           pProfile->nRSNReqIELength && pProfile->pRSNReqIE)
         {
+            smsLog(pMac, LOGW, "force_rsne_override, copy RSN IE provided by user");
             // If you have one started away, re-use it. 
             if(SIR_MAC_WPA_IE_MAX_LENGTH >= pProfile->nRSNReqIELength)
             {
@@ -4783,7 +4785,9 @@
             }
             else
             {
-                smsLog(pMac, LOGW, "  csrRetrieveRsnIe detect invalid RSN IE length (%d) ", pProfile->nRSNReqIELength);
+                smsLog(pMac, LOGW, "csrRetrieveRsnIe detect invalid RSN IE length (%d)",
+                       pProfile->nRSNReqIELength);
+                break;
             }
         }
         else
diff --git a/CORE/SYS/legacy/src/utils/src/parserApi.c b/CORE/SYS/legacy/src/utils/src/parserApi.c
index 99833a4..03643df 100644
--- a/CORE/SYS/legacy/src/utils/src/parserApi.c
+++ b/CORE/SYS/legacy/src/utils/src/parserApi.c
@@ -1407,7 +1407,7 @@
                                     pRsnIe->rsnIEdata + idx + 2, //EID, length
                                     pRsnIe->rsnIEdata[ idx + 1 ],
                                     pDot11f );
-        if ( DOT11F_FAILED( status ) )
+        if (!DOT11F_SUCCEEDED(status))
         {
             dot11fLog( pMac, LOGE, FL("Parse failure in PopulateDot11fRS"
                                    "N (0x%08x)."),