diff --git a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h index e4735deec1..7579533b22 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h @@ -273,14 +273,14 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val) #define RSN_CIPHER_SUITE_BIP_CMAC_256 WLAN_RSN_SEL(WLAN_CSE_BIP_CMAC_256) #define RESET_PARAM(__param) ((__param) = 0) -#define SET_PARAM(__param, __val) ((__param) |= (1<<(__val))) -#define HAS_PARAM(__param, __val) ((__param) & (1<<(__val))) +#define SET_PARAM(__param, __val) ((__param) |= (1 << (__val))) +#define HAS_PARAM(__param, __val) ((__param) & (1 << (__val))) #define CLEAR_PARAM(__param, __val) ((__param) &= ((~1) << (__val))) #define RESET_AUTHMODE(_param) ((_param)->authmodeset = 0) -#define SET_AUTHMODE(_param, _mode) ((_param)->authmodeset |= (1<<(_mode))) -#define HAS_AUTHMODE(_param, _mode) ((_param)->authmodeset & (1<<(_mode))) +#define SET_AUTHMODE(_param, _mode) ((_param)->authmodeset |= (1 << (_mode))) +#define HAS_AUTHMODE(_param, _mode) ((_param)->authmodeset & (1 << (_mode))) #define AUTH_IS_OPEN(_param) HAS_AUTHMODE((_param), WLAN_CRYPTO_AUTH_OPEN) #define AUTH_IS_SHARED_KEY(_param) \ @@ -297,8 +297,8 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val) #define RESET_UCAST_CIPHERS(_param) ((_param)->ucastcipherset = 0) -#define SET_UCAST_CIPHER(_param, _c) ((_param)->ucastcipherset |= (1<<(_c))) -#define HAS_UCAST_CIPHER(_param, _c) ((_param)->ucastcipherset & (1<<(_c))) +#define SET_UCAST_CIPHER(_param, _c) ((_param)->ucastcipherset |= (1 << (_c))) +#define HAS_UCAST_CIPHER(_param, _c) ((_param)->ucastcipherset & (1 << (_c))) #define UCIPHER_IS_CLEAR(_param) \ HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_NONE) @@ -318,8 +318,8 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val) HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_WAPI_SMS4) #define RESET_MCAST_CIPHERS(_param) ((_param)->mcastcipherset = 0) -#define SET_MCAST_CIPHER(_param, _c) ((_param)->mcastcipherset |= (1<<(_c))) -#define HAS_MCAST_CIPHER(_param, _c) ((_param)->mcastcipherset & (1<<(_c))) +#define SET_MCAST_CIPHER(_param, _c) ((_param)->mcastcipherset |= (1 << (_c))) +#define HAS_MCAST_CIPHER(_param, _c) ((_param)->mcastcipherset & (1 << (_c))) #define HAS_ANY_MCAST_CIPHER(_param) ((_param)->mcastcipherset) #define CLEAR_MCAST_CIPHER(_param, _c) \ ((_param)->mcastcipherset &= (~(1)<<(_c))) @@ -342,8 +342,8 @@ 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 HAS_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) || \ (_c == WLAN_CRYPTO_CIPHER_AES_GMAC) || \ @@ -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) @@ -378,8 +378,8 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val) (!(_param1)->key_mgmt && !(_param2)->key_mgmt)) #define RESET_CIPHER_CAP(_param) ((_param)->cipher_caps = 0) -#define SET_CIPHER_CAP(_param, _c) ((_param)->cipher_caps |= (1<<(_c))) -#define HAS_CIPHER_CAP(_param, _c) ((_param)->cipher_caps & (1<<(_c))) +#define SET_CIPHER_CAP(_param, _c) ((_param)->cipher_caps |= (1 << (_c))) +#define HAS_CIPHER_CAP(_param, _c) ((_param)->cipher_caps & (1 << (_c))) #define HAS_ANY_CIPHER_CAP(_param) ((_param)->cipher_caps) /** diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index 9b8bea8f9f..63642101e4 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -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,52 +2126,128 @@ 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; - SET_MCAST_CIPHER(crypto_params, w); - frm += 4, len -= 4; + 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) - 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) + if (n) { + if (len < n * 4) return QDF_STATUS_E_INVAL; - SET_UCAST_CIPHER(crypto_params, w); - frm += 4, len -= 4; + + for (; n > 0; n--) { + w = wlan_crypto_rsn_suite_to_cipher(frm); + if (w < 0) + return QDF_STATUS_E_INVAL; + 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 (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) + if (n) { + if (len < n * 4) return QDF_STATUS_E_INVAL; - SET_KEY_MGMT(crypto_params, (1 << w)); - frm += 4, len -= 4; + + 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, 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;