qcacmn: Add support WPA2 security improvements
Add support for WPA security improvements where if length and data mismatch are present in the IE's then driver need to gracefully return error rather than accessing out of bounds data. Change-Id: Idd56e5b987fed4d7bddad6d5ada927e97f92a1aa Crs-Fixed: 2243109
This commit is contained in:
@@ -342,7 +342,7 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val)
|
||||
HAS_MCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_WAPI_SMS4)
|
||||
|
||||
#define RESET_MGMT_CIPHERS(_param) ((_param)->mgmtcipherset = 0)
|
||||
#define SET_MGMT_CIPHER(_param, _c) ((_param)->mgmtcipherset = (1<<(_c)))
|
||||
#define SET_MGMT_CIPHER(_param, _c) ((_param)->mgmtcipherset |= (1 << (_c)))
|
||||
#define HAS_MGMT_CIPHER(_param, _c) ((_param)->mgmtcipherset & (1 << (_c)))
|
||||
#define IS_MGMT_CIPHER(_c) ((_c == WLAN_CRYPTO_CIPHER_AES_CMAC) || \
|
||||
(_c == WLAN_CRYPTO_CIPHER_AES_CMAC_256) || \
|
||||
@@ -361,8 +361,8 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val)
|
||||
HAS_MGMT_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_GMAC_256)
|
||||
|
||||
#define RESET_KEY_MGMT(_param) ((_param)->key_mgmt = 0)
|
||||
#define SET_KEY_MGMT(_param, _c) ((_param)->key_mgmt |= (1<<(_c)))
|
||||
#define HAS_KEY_MGMT(_param, _c) ((_param)->key_mgmt & (1<<(_c)))
|
||||
#define SET_KEY_MGMT(_param, _c) ((_param)->key_mgmt |= (1 << (_c + 1)))
|
||||
#define HAS_KEY_MGMT(_param, _c) ((_param)->key_mgmt & (1 << (_c + 1)))
|
||||
|
||||
#define UCAST_CIPHER_MATCH(_param1, _param2) \
|
||||
(((_param1)->ucastcipherset & (_param2)->ucastcipherset) != 0)
|
||||
|
@@ -2109,17 +2109,15 @@ QDF_STATUS wlan_crypto_rsnie_check(struct wlan_crypto_params *crypto_params,
|
||||
int32_t w;
|
||||
int n;
|
||||
|
||||
/*
|
||||
* Check the length once for fixed parts: OUI, type,
|
||||
* version, mcast cipher, and 2 selector counts.
|
||||
* Other, variable-length data, must be checked separately.
|
||||
*/
|
||||
RESET_AUTHMODE(crypto_params);
|
||||
SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_RSNA);
|
||||
|
||||
if (len < 14)
|
||||
/* Check the length once for fixed parts: OUI, type & version */
|
||||
if (len < 2)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
/* initialize crypto params */
|
||||
qdf_mem_zero(crypto_params, sizeof(struct wlan_crypto_params));
|
||||
|
||||
SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_RSNA);
|
||||
|
||||
frm += 2;
|
||||
/* NB: iswapoui already validated the OUI and type */
|
||||
w = LE_READ_2(frm);
|
||||
@@ -2128,21 +2126,48 @@ QDF_STATUS wlan_crypto_rsnie_check(struct wlan_crypto_params *crypto_params,
|
||||
|
||||
frm += 2, len -= 2;
|
||||
|
||||
if (!len) {
|
||||
/* set defaults */
|
||||
/* default group cipher CCMP-128 */
|
||||
SET_MCAST_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CCM);
|
||||
/* default ucast cipher CCMP-128 */
|
||||
SET_UCAST_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CCM);
|
||||
/* default key mgmt 8021x */
|
||||
SET_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
} else if (len < 4) {
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
/* multicast/group cipher */
|
||||
RESET_MCAST_CIPHERS(crypto_params);
|
||||
w = wlan_crypto_rsn_suite_to_cipher(frm);
|
||||
if (w < 0)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
else {
|
||||
SET_MCAST_CIPHER(crypto_params, w);
|
||||
frm += 4, len -= 4;
|
||||
}
|
||||
|
||||
if (crypto_params->mcastcipherset == 0)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
if (!len) {
|
||||
/* default ucast cipher CCMP-128 */
|
||||
SET_UCAST_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CCM);
|
||||
/* default key mgmt 8021x */
|
||||
SET_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
} else if (len < 2) {
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
/* unicast ciphers */
|
||||
n = LE_READ_2(frm);
|
||||
frm += 2, len -= 2;
|
||||
if (len < n*4+2)
|
||||
if (n) {
|
||||
if (len < n * 4)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
RESET_UCAST_CIPHERS(crypto_params);
|
||||
for (; n > 0; n--) {
|
||||
w = wlan_crypto_rsn_suite_to_cipher(frm);
|
||||
if (w < 0)
|
||||
@@ -2150,30 +2175,79 @@ QDF_STATUS wlan_crypto_rsnie_check(struct wlan_crypto_params *crypto_params,
|
||||
SET_UCAST_CIPHER(crypto_params, w);
|
||||
frm += 4, len -= 4;
|
||||
}
|
||||
} else {
|
||||
/* default ucast cipher CCMP-128 */
|
||||
SET_UCAST_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CCM);
|
||||
}
|
||||
|
||||
if (crypto_params->ucastcipherset == 0)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
if (!len) {
|
||||
/* default key mgmt 8021x */
|
||||
SET_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
} else if (len < 2) {
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
/* key management algorithms */
|
||||
n = LE_READ_2(frm);
|
||||
frm += 2, len -= 2;
|
||||
|
||||
if (n) {
|
||||
if (len < n * 4)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
w = 0;
|
||||
|
||||
RESET_KEY_MGMT(crypto_params);
|
||||
for (; n > 0; n--) {
|
||||
w = wlan_crypto_rsn_suite_to_keymgmt(frm);
|
||||
if (w < 0)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
SET_KEY_MGMT(crypto_params, (1 << w));
|
||||
SET_KEY_MGMT(crypto_params, w);
|
||||
frm += 4, len -= 4;
|
||||
}
|
||||
} else {
|
||||
/* default key mgmt 8021x */
|
||||
SET_KEY_MGMT(crypto_params, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
|
||||
}
|
||||
|
||||
if (crypto_params->key_mgmt == 0)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
/* optional capabilities */
|
||||
if (len >= 2) {
|
||||
crypto_params->rsn_caps = LE_READ_2(frm);
|
||||
frm += 2, len -= 2;
|
||||
} else if (len && len < 2) {
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
|
||||
/* PMKID */
|
||||
if (len >= 2) {
|
||||
n = LE_READ_2(frm);
|
||||
frm += 2, len -= 2;
|
||||
if (n && len) {
|
||||
if (len >= n * PMKID_LEN)
|
||||
frm += (n * PMKID_LEN), len -= (n * PMKID_LEN);
|
||||
else
|
||||
return QDF_STATUS_E_INVAL;
|
||||
} else if (n && !len) {
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
/*TODO: Save pmkid in params for further reference */
|
||||
}
|
||||
|
||||
/* BIP */
|
||||
if (!len &&
|
||||
(crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) {
|
||||
/* when no BIP mentioned and MFP capable use CMAC as default*/
|
||||
SET_MGMT_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CMAC);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
} else if (len >= 4) {
|
||||
w = wlan_crypto_rsn_suite_to_cipher(frm);
|
||||
frm += 4, len -= 4;
|
||||
SET_MGMT_CIPHER(crypto_params, w);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
Reference in New Issue
Block a user