summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyeh <syeh@qca.qualcomm.com>2014-05-27 00:54:46 +0800
committerPitani Venkata Rajesh Kumar <c_vpitan@qti.qualcomm.com>2014-06-15 00:39:52 +0530
commit71f2e2ed3c1e304df96e4b83d2d4f13374900400 (patch)
tree3c3f17bdbb87b0dce22ad258445a99504d9c3bd9
parent00ba15581e8af4a617bbe6508d0d80f47c04cd12 (diff)
qcacld: Enable Protected Management Frames (802.11w).
Modify cld host driver to support PMF (802.11W) for ROME USB and SDIO device. Change-Id: I9ee63a4695011f0980e2c229301d2c41f2f3a0e0 CRs-Fixed: 670051
-rw-r--r--CORE/VOSS/inc/wcnss_api.h39
-rw-r--r--CORE/VOSS/src/vos_utils.c192
-rw-r--r--Kbuild7
3 files changed, 195 insertions, 43 deletions
diff --git a/CORE/VOSS/inc/wcnss_api.h b/CORE/VOSS/inc/wcnss_api.h
index 7dd304bacb6f..9add2c7fa5d5 100644
--- a/CORE/VOSS/inc/wcnss_api.h
+++ b/CORE/VOSS/inc/wcnss_api.h
@@ -88,45 +88,6 @@ static inline unsigned int wcnss_get_serial_number(void)
return 0;
}
-#if !defined(CONFIG_CNSS)
-static inline void *wcnss_wlan_crypto_alloc_ahash(const char *alg_name,
- unsigned int type,
- unsigned int mask)
-{
- return NULL;
-}
-
-static inline int wcnss_wlan_crypto_ahash_digest(void *req)
-{
- return 0;
-}
-
-static inline void wcnss_wlan_crypto_free_ahash(void *tfm)
-{
-}
-
-static inline int wcnss_wlan_crypto_ahash_setkey(void *tfm,
- const u8 *key,
- unsigned int keylen)
-{
- return 0;
-}
-
-static inline void *wcnss_wlan_crypto_alloc_ablkcipher(const char *alg_name,
- u32 type, u32 mask)
-{
- return NULL;
-}
-
-static inline void wcnss_wlan_ablkcipher_request_free(void *req)
-{
-}
-
-static inline void wcnss_wlan_crypto_free_ablkcipher(void *tfm)
-{
-}
-#endif /* !CONFIG_CNSS */
-
static inline int req_riva_power_on_lock(char *driver_name)
{
return 0;
diff --git a/CORE/VOSS/src/vos_utils.c b/CORE/VOSS/src/vos_utils.c
index 2beabf8bf27b..6786f8884bb3 100644
--- a/CORE/VOSS/src/vos_utils.c
+++ b/CORE/VOSS/src/vos_utils.c
@@ -95,6 +95,111 @@
/*----------------------------------------------------------------------------
Function Definitions and Documentation
* -------------------------------------------------------------------------*/
+#ifndef CONFIG_CNSS
+#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
+
+static inline void xor_128(const u8 *a, const u8 *b, u8 *out)
+{
+ u8 i;
+
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ out[i] = a[i] ^ b[i];
+}
+
+static inline void leftshift_onebit(const u8 *input, u8 *output)
+{
+ int i, overflow = 0;
+
+ for (i = (AES_BLOCK_SIZE - 1); i >= 0; i--) {
+ output[i] = input[i] << 1;
+ output[i] |= overflow;
+ overflow = (input[i] & 0x80) ? 1 : 0;
+ }
+ return;
+}
+
+static void generate_subkey(struct crypto_cipher *tfm, u8 *k1, u8 *k2)
+{
+ u8 l[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
+ u8 const_rb[AES_BLOCK_SIZE] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87};
+ u8 const_zero[AES_BLOCK_SIZE] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ crypto_cipher_encrypt_one(tfm, l, const_zero);
+
+ if ((l[0] & 0x80) == 0) { /* If MSB(l) = 0, then k1 = l << 1 */
+ leftshift_onebit(l, k1);
+ } else { /* Else k1 = ( l << 1 ) (+) Rb */
+ leftshift_onebit(l, tmp);
+ xor_128(tmp, const_rb, k1);
+ }
+
+ if ((k1[0] & 0x80) == 0) {
+ leftshift_onebit(k1, k2);
+ } else {
+ leftshift_onebit(k1, tmp);
+ xor_128(tmp, const_rb, k2);
+ }
+}
+
+static inline void padding(u8 *lastb, u8 *pad, u16 length)
+{
+ u8 j;
+
+ /* original last block */
+ for (j = 0; j < AES_BLOCK_SIZE; j++) {
+ if (j < length)
+ pad[j] = lastb[j];
+ else if (j == length)
+ pad[j] = 0x80;
+ else
+ pad[j] = 0x00;
+ }
+}
+
+void cmac_calc_mic(struct crypto_cipher *tfm, u8 *m,
+ u16 length, u8 *mac)
+{
+ u8 x[AES_BLOCK_SIZE], y[AES_BLOCK_SIZE];
+ u8 m_last[AES_BLOCK_SIZE], padded[AES_BLOCK_SIZE];
+ u8 k1[AES_KEYSIZE_128], k2[AES_KEYSIZE_128];
+ int cmpBlk;
+ int i, nBlocks = (length + 15)/AES_BLOCK_SIZE;
+
+ generate_subkey(tfm, k1, k2);
+
+ if (nBlocks == 0) {
+ nBlocks = 1;
+ cmpBlk = 0;
+ } else {
+ cmpBlk = ((length % AES_BLOCK_SIZE) == 0) ? 1 : 0;
+ }
+
+ if (cmpBlk) { /* Last block is complete block */
+ xor_128(&m[AES_BLOCK_SIZE * (nBlocks - 1)], k1, m_last);
+ } else { /* Last block is not complete block */
+ padding(&m[AES_BLOCK_SIZE * (nBlocks - 1)], padded,
+ length % AES_BLOCK_SIZE);
+ xor_128(padded, k2, m_last);
+ }
+
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ x[i] = 0;
+
+ for (i = 0; i < (nBlocks - 1); i++) {
+ xor_128(x, &m[AES_BLOCK_SIZE * i], y); /* y = Mi (+) x */
+ crypto_cipher_encrypt_one(tfm, x, y); /* x = AES-128(KEY, y) */
+ }
+
+ xor_128(x, m_last, y);
+ crypto_cipher_encrypt_one(tfm, x, y);
+
+ memcpy(mac, x, CMAC_TLEN);
+}
+#endif
/*--------------------------------------------------------------------------
@@ -291,7 +396,11 @@ vos_attach_mmie(v_U8_t *igtk, v_U8_t *ipn, u_int16_t key_id,
/*
* Calculate MIC and then copy
*/
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ tfm = crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
+#else
tfm = wcnss_wlan_crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
+#endif
if (IS_ERR(tfm))
{
ret = PTR_ERR(tfm);
@@ -342,7 +451,11 @@ vos_attach_mmie(v_U8_t *igtk, v_U8_t *ipn, u_int16_t key_id,
(v_U8_t*)(efrm-(frmLen-sizeof(struct ieee80211_frame))),
nBytes - AAD_LEN - CMAC_TLEN);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ cmac_calc_mic(tfm, input, nBytes, mic);
+#else
wcnss_wlan_cmac_calc_mic(tfm, input, nBytes, mic);
+#endif
vos_mem_free(input);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
@@ -359,8 +472,11 @@ err_tfm:
}
if (tfm)
- wcnss_wlan_crypto_free_cipher(tfm);
-
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ crypto_free_cipher(tfm);
+#else
+ wcnss_wlan_crypto_free_cipher(tfm);
+#endif
return !ret?VOS_TRUE:VOS_FALSE;
}
@@ -405,7 +521,11 @@ v_BOOL_t vos_is_mmie_valid(v_U8_t *igtk, v_U8_t *ipn,
return VOS_FALSE;
}
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ tfm = crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
+#else
tfm = wcnss_wlan_crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
+#endif
if (IS_ERR(tfm)) {
ret = PTR_ERR(tfm);
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,
@@ -449,7 +569,11 @@ v_BOOL_t vos_is_mmie_valid(v_U8_t *igtk, v_U8_t *ipn,
vos_mem_copy(input, aad, AAD_LEN);
vos_mem_copy(input+AAD_LEN, (v_U8_t*)(wh+1), nBytes - AAD_LEN - CMAC_TLEN);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ cmac_calc_mic(tfm, input, nBytes, mic);
+#else
wcnss_wlan_cmac_calc_mic(tfm, input, nBytes, mic);
+#endif
vos_mem_free(input);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
@@ -475,7 +599,11 @@ v_BOOL_t vos_is_mmie_valid(v_U8_t *igtk, v_U8_t *ipn,
err_tfm:
if (tfm)
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ crypto_free_cipher(tfm);
+#else
wcnss_wlan_crypto_free_cipher(tfm);
+#endif
return !ret?VOS_TRUE:VOS_FALSE;
}
@@ -535,8 +663,13 @@ int hmac_sha1(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize,
init_completion(&tresult.completion);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ tfm = crypto_alloc_ahash("hmac(sha1)", CRYPTO_ALG_TYPE_AHASH,
+ CRYPTO_ALG_TYPE_AHASH_MASK);
+#else
tfm = wcnss_wlan_crypto_alloc_ahash("hmac(sha1)", CRYPTO_ALG_TYPE_AHASH,
CRYPTO_ALG_TYPE_AHASH_MASK);
+#endif
if (IS_ERR(tfm)) {
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ahash failed");
ret = PTR_ERR(tfm);
@@ -566,7 +699,11 @@ int hmac_sha1(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize,
if (ksize) {
crypto_ahash_clear_flags(tfm, ~0);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ ret = crypto_ahash_setkey(tfm, key, ksize);
+#else
ret = wcnss_wlan_crypto_ahash_setkey(tfm, key, ksize);
+#endif
if (ret) {
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_ahash_setkey failed");
@@ -575,8 +712,11 @@ int hmac_sha1(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize,
}
ahash_request_set_crypt(req, &sg, hash_result, psize);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ ret = crypto_ahash_digest(req);
+#else
ret = wcnss_wlan_crypto_ahash_digest(req);
-
+#endif
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret);
switch (ret) {
@@ -606,7 +746,11 @@ err_setkey:
err_hash_buf:
ahash_request_free(req);
err_req:
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ crypto_free_ahash(tfm);
+#else
wcnss_wlan_crypto_free_ahash(tfm);
+#endif
err_tfm:
return ret;
}
@@ -690,8 +834,13 @@ int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize,
init_completion(&tresult.completion);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ tfm = crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH,
+ CRYPTO_ALG_TYPE_AHASH_MASK);
+#else
tfm = wcnss_wlan_crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH,
CRYPTO_ALG_TYPE_AHASH_MASK);
+#endif
if (IS_ERR(tfm)) {
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ahash failed");
ret = PTR_ERR(tfm);
@@ -721,8 +870,11 @@ int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize,
if (ksize) {
crypto_ahash_clear_flags(tfm, ~0);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ ret = crypto_ahash_setkey(tfm, key, ksize);
+#else
ret = wcnss_wlan_crypto_ahash_setkey(tfm, key, ksize);
-
+#endif
if (ret) {
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_ahash_setkey failed");
goto err_setkey;
@@ -730,7 +882,11 @@ int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize,
}
ahash_request_set_crypt(req, &sg, hash_result, psize);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ ret = crypto_ahash_digest(req);
+#else
ret = wcnss_wlan_crypto_ahash_digest(req);
+#endif
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret);
@@ -761,7 +917,11 @@ err_setkey:
err_hash_buf:
ahash_request_free(req);
err_req:
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ crypto_free_ahash(tfm);
+#else
wcnss_wlan_crypto_free_ahash(tfm);
+#endif
err_tfm:
return ret;
}
@@ -850,7 +1010,11 @@ VOS_STATUS vos_encrypt_AES(v_U32_t cryptHandle, /* Handle */
init_completion(&result.completion);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ tfm = crypto_alloc_ablkcipher( "cbc(aes)", 0, 0);
+#else
tfm = wcnss_wlan_crypto_alloc_ablkcipher( "cbc(aes)", 0, 0);
+#endif
if (IS_ERR(tfm)) {
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ablkcipher failed");
ret = PTR_ERR(tfm);
@@ -890,9 +1054,17 @@ VOS_STATUS vos_encrypt_AES(v_U32_t cryptHandle, /* Handle */
// -------------------------------------
err_setkey:
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ ablkcipher_request_free(req);
+#else
wcnss_wlan_ablkcipher_request_free(req);
+#endif
err_req:
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ crypto_free_ablkcipher(tfm);
+#else
wcnss_wlan_crypto_free_ablkcipher(tfm);
+#endif
err_tfm:
//return ret;
if (ret != 0) {
@@ -946,7 +1118,11 @@ VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, /* Handle */
init_completion(&result.completion);
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ tfm = crypto_alloc_ablkcipher( "cbc(aes)", 0, 0);
+#else
tfm = wcnss_wlan_crypto_alloc_ablkcipher( "cbc(aes)", 0, 0);
+#endif
if (IS_ERR(tfm)) {
VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ablkcipher failed");
ret = PTR_ERR(tfm);
@@ -986,9 +1162,17 @@ VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, /* Handle */
// -------------------------------------
err_setkey:
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ ablkcipher_request_free(req);
+#else
wcnss_wlan_ablkcipher_request_free(req);
+#endif
err_req:
+#if !defined(QCA_WIFI_ISOC) && !defined(CONFIG_CNSS)
+ crypto_free_ablkcipher(tfm);
+#else
wcnss_wlan_crypto_free_ablkcipher(tfm);
+#endif
err_tfm:
//return ret;
if (ret != 0) {
diff --git a/Kbuild b/Kbuild
index 96778ab927cc..9c3b4b67a4c2 100644
--- a/Kbuild
+++ b/Kbuild
@@ -68,6 +68,13 @@ ifeq ($(KERNEL_BUILD), 0)
#Flag to enable new Linux Regulatory implementation
CONFIG_ENABLE_LINUX_REG := y
+ #Flag to enable Protected Managment Frames (11w) feature
+ ifeq ($(CONFIG_ROME_IF),usb)
+ CONFIG_WLAN_FEATURE_11W := y
+ endif
+ ifeq ($(CONFIG_ROME_IF),sdio)
+ CONFIG_WLAN_FEATURE_11W := y
+ endif
endif
# To enable ESE upload, dependent config