From 2a3df50deaf3555d4b55da36c88b4ea32bc8cd17 Mon Sep 17 00:00:00 2001 From: Ashok Ponnaiah Date: Fri, 7 Jul 2017 17:01:41 +0530 Subject: [PATCH] qcacmn: Fix PMF in crypto convergence changed the parameters in qdf_mem_zero fixed issues in MMIE calculation. CRs-fixed: 2073813 Change-Id: I01baa30fa1f51bb50116458d7c563c894ed44ec5 --- .../crypto/inc/wlan_crypto_global_api.h | 36 ++++ .../crypto/src/wlan_crypto_aes_ccm.c | 2 +- .../crypto/src/wlan_crypto_aes_gcm.c | 6 +- .../crypto/src/wlan_crypto_aes_i.h | 20 +- .../crypto/src/wlan_crypto_aes_internal_dec.c | 2 +- .../crypto/src/wlan_crypto_aes_internal_enc.c | 2 +- .../crypto/src/wlan_crypto_aes_omac1.c | 8 +- .../crypto/src/wlan_crypto_ccmp.c | 5 +- .../crypto/src/wlan_crypto_def_i.h | 38 +++- .../crypto/src/wlan_crypto_global_api.c | 190 +++++++++++++----- 10 files changed, 238 insertions(+), 71 deletions(-) diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h index 01719d51890d..6cfd45f8d2af 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h @@ -200,6 +200,17 @@ QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev, uint8_t *macaddr, uint8_t tid); +/** + * wlan_crypto_vdev_is_pmf_enabled - called to check is pmf enabled in vdev + * + * @vdev: vdev + * + * This function gets called to check is pmf enabled or not in vdev. + * + * Return: true or false + */ +bool wlan_crypto_vdev_is_pmf_enabled(struct wlan_objmgr_vdev *vdev); + /** * wlan_crypto_is_pmf_enabled - called by mgmt txrx to check is pmf enabled * @@ -378,4 +389,29 @@ QDF_STATUS wlan_crypto_register_crypto_rx_ops( */ struct wlan_lmac_if_crypto_rx_ops *wlan_crypto_get_crypto_rx_ops( struct wlan_objmgr_psoc *psoc); +/** + * wlan_crypto_vdev_has_auth_mode - check authmode for vdev + * + * @vdev: vdev + * @authvalue: authvalue to be checked + * + * This function check is authvalue passed is set in vdev or not + * + * Return: true or false + */ +bool wlan_crypto_vdev_has_auth_mode(struct wlan_objmgr_vdev *vdev, + wlan_crypto_auth_mode authmode); + +/** + * wlan_crypto_peer_has_auth_mode - check authmode for peer + * + * @peer: peer + * @authvalue: authvalue to be checked + * + * This function check is authvalue passed is set in peer or not + * + * Return: true or false + */ +bool wlan_crypto_peer_has_auth_mode(struct wlan_objmgr_peer *peer, + wlan_crypto_auth_mode authvalue); #endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */ diff --git a/umac/cmn_services/crypto/src/wlan_crypto_aes_ccm.c b/umac/cmn_services/crypto/src/wlan_crypto_aes_ccm.c index 2dc71352ec9d..9f046c5167bc 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_aes_ccm.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_aes_ccm.c @@ -52,7 +52,7 @@ static void aes_ccm_auth_start(void *aes, size_t M, size_t L, wlan_crypto_put_be16(aad_buf, aad_len); qdf_mem_copy(aad_buf + 2, aad, aad_len); - qdf_mem_set(aad_buf + 2 + aad_len, 0, sizeof(aad_buf) - 2 - aad_len); + qdf_mem_set(aad_buf + 2 + aad_len, sizeof(aad_buf) - 2 - aad_len, 0); xor_aes_block(aad_buf, x); wlan_crypto_aes_encrypt(aes, aad_buf, x); /* X_2 = E(K, X_1 XOR B_1) */ diff --git a/umac/cmn_services/crypto/src/wlan_crypto_aes_gcm.c b/umac/cmn_services/crypto/src/wlan_crypto_aes_gcm.c index 8072c69cacf8..9402c63f30a4 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_aes_gcm.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_aes_gcm.c @@ -70,7 +70,7 @@ static void gf_mult(const uint8_t *x, const uint8_t *y, uint8_t *z) uint8_t v[16]; int i, j; - qdf_mem_set(z, 0, 16); /* Z_0 = 0^128 */ + qdf_mem_set(z, 16, 0); /* Z_0 = 0^128 */ qdf_mem_copy(v, y, 16); /* V_0 = Y */ for (i = 0; i < 16; i++) { @@ -99,7 +99,7 @@ static void gf_mult(const uint8_t *x, const uint8_t *y, uint8_t *z) static void ghash_start(uint8_t *y) { /* Y_0 = 0^128 */ - qdf_mem_set(y, 0, 16); + qdf_mem_set(y, 16, 0); } @@ -127,7 +127,7 @@ static void ghash(const uint8_t *h, const uint8_t *x, size_t xlen, uint8_t *y) /* Add zero padded last block */ size_t last = x + xlen - xpos; qdf_mem_copy(tmp, xpos, last); - qdf_mem_set(tmp + last, 0, sizeof(tmp) - last); + qdf_mem_set(tmp + last, sizeof(tmp) - last, 0); /* Y_i = (Y^(i-1) XOR X_i) dot H */ xor_block(y, tmp); diff --git a/umac/cmn_services/crypto/src/wlan_crypto_aes_i.h b/umac/cmn_services/crypto/src/wlan_crypto_aes_i.h index 032a85898c5b..a309edfb1d37 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_aes_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_aes_i.h @@ -50,6 +50,10 @@ extern const uint8_t rcons[10]; #ifndef AES_SMALL_TABLES #define RCON(i) rcon[(i)] +static inline uint32_t rotr(uint32_t val, int bits) +{ + return (val >> bits) | (val << (32 - bits)); +} #define TE0(i) Te0[((i) >> 24) & 0xff] #define TE1(i) Te1[((i) >> 16) & 0xff] @@ -129,16 +133,16 @@ static inline uint32_t rotr(uint32_t val, int bits) #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) #define GETU32(p) SWAP(*((uint32_t *)(p))) #define PUTU32(ct, st) { *((uint32_t *)(ct)) = SWAP((st)); } - #else +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ -((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) - -#define PUTU32(ct, st) { \ -(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ -(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } - +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^\ + ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) {\ + (ct)[0] = (u8)((st) >> 24);\ + (ct)[1] = (u8)((st) >> 16);\ + (ct)[2] = (u8)((st) >> 8);\ + (ct)[3] = (u8)(st); } #endif #define AES_PRIV_SIZE (4 * 4 * 15 + 4) diff --git a/umac/cmn_services/crypto/src/wlan_crypto_aes_internal_dec.c b/umac/cmn_services/crypto/src/wlan_crypto_aes_internal_dec.c index 808705cef6d8..fdf1d1e513b2 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_aes_internal_dec.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_aes_internal_dec.c @@ -157,6 +157,6 @@ void wlan_crypto_aes_decrypt(void *ctx, const uint8_t *crypt, uint8_t *plain) void wlan_crypto_aes_decrypt_deinit(void *ctx) { - qdf_mem_set(ctx, 0, AES_PRIV_SIZE); + qdf_mem_set(ctx, AES_PRIV_SIZE, 0); qdf_mem_free(ctx); } diff --git a/umac/cmn_services/crypto/src/wlan_crypto_aes_internal_enc.c b/umac/cmn_services/crypto/src/wlan_crypto_aes_internal_enc.c index ea0498da2bca..07bbb15ce11c 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_aes_internal_enc.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_aes_internal_enc.c @@ -124,6 +124,6 @@ void wlan_crypto_aes_encrypt(void *ctx, const uint8_t *plain, uint8_t *crypt) void wlan_crypto_aes_encrypt_deinit(void *ctx) { - qdf_mem_set(ctx, 0, AES_PRIV_SIZE); + qdf_mem_set(ctx, AES_PRIV_SIZE, 0); qdf_mem_free(ctx); } diff --git a/umac/cmn_services/crypto/src/wlan_crypto_aes_omac1.c b/umac/cmn_services/crypto/src/wlan_crypto_aes_omac1.c index 936a99b17b11..cf0518dd2ad5 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_aes_omac1.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_aes_omac1.c @@ -47,21 +47,23 @@ int omac1_aes_vector(const uint8_t *key, size_t key_len, size_t num_elem, const uint8_t *addr[], const size_t *len, uint8_t *mac) { void *ctx; - uint8_t cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; const uint8_t *pos, *end; int32_t status = -1; size_t i, e, left, total_len; + uint8_t cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; + ctx = wlan_crypto_aes_encrypt_init(key, key_len); if (ctx == NULL) return status; - qdf_mem_set(cbc, 0, AES_BLOCK_SIZE); total_len = 0; for (e = 0; e < num_elem; e++) total_len += len[e]; left = total_len; + qdf_mem_set(cbc, AES_BLOCK_SIZE, 0); + e = 0; pos = addr[0]; end = pos + len[0]; @@ -87,7 +89,7 @@ int omac1_aes_vector(const uint8_t *key, size_t key_len, size_t num_elem, left -= AES_BLOCK_SIZE; } - qdf_mem_set(pad, 0, AES_BLOCK_SIZE); + qdf_mem_set(pad, AES_BLOCK_SIZE, 0); wlan_crypto_aes_encrypt(ctx, pad, pad); gf_mulx(pad); diff --git a/umac/cmn_services/crypto/src/wlan_crypto_ccmp.c b/umac/cmn_services/crypto/src/wlan_crypto_ccmp.c index 0abc77f2e0c5..501bafe67cc5 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_ccmp.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_ccmp.c @@ -55,22 +55,19 @@ static QDF_STATUS ccmp_encap(struct wlan_crypto_key *key, /* * Copy down 802.11 header and add the IV, KeyID, and ExtIV. */ - if (encapdone) { ivp = (uint8_t *)qdf_nbuf_data(wbuf); } else { ivp = (uint8_t *)qdf_nbuf_push_head(wbuf, cipher_table->header); qdf_mem_move(ivp, ivp + cipher_table->header, hdrlen); - /* recompute hdr */ - hdr = (struct ieee80211_hdr *) qdf_nbuf_data(wbuf); + ivp = (uint8_t *) qdf_nbuf_data(wbuf); } ivp += hdrlen; /* XXX wrap at 48 bits */ key->keytsc++; - ivp[0] = key->keytsc >> 0; /* PN0 */ ivp[1] = key->keytsc >> 8; /* PN1 */ ivp[2] = 0; /* Reserved */ 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 4de720223538..4329a3764132 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h @@ -419,9 +419,33 @@ struct wlan_crypto_cipher { qdf_nbuf_t, uint8_t, uint8_t); }; -/* -* Return the size of the 802.11 header for a management or data frame. -*/ + +/** + * wlan_crypto_is_data_protected - check is frame is protected or not + * + * @data: frame + * This function check is frame is protected or not + * + * Return: TRUE/FALSE + */ +static inline bool wlan_crypto_is_data_protected(const void *data) +{ + const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)data; + + if (hdr->frame_control & WLAN_FC_ISWEP) + return true; + else + return false; +} + +/** + * ieee80211_hdrsize - calculate frame header size + * + * @data: frame + * This function calculate frame header size + * + * Return: header size of the frame + */ static inline int ieee80211_hdrsize(const void *data) { const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)data; @@ -442,6 +466,14 @@ static inline int ieee80211_hdrsize(const void *data) return size; } +/** + * wlan_get_tid - get tid of the frame + * + * @data: frame + * This function get tid of the frame + * + * Return: tid of the frame + */ static inline int wlan_get_tid(const void *data) { const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)data; 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 4a975cb5f3c5..8503078e9083 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -253,15 +253,6 @@ uint8_t wlan_crypto_is_htallowed(struct wlan_objmgr_vdev *vdev, } qdf_export_symbol(wlan_crypto_is_htallowed); -static void initialize_send_iv(uint8_t *iv, uint8_t *init_iv) -{ - int8_t i = 0; - - for (i = 0; i < WLAN_CRYPTO_WAPI_IV_SIZE/4; i++) { - *(((uint32_t *)iv)+i) = - qdf_be32_to_cpu(*(((uint32_t *)(init_iv))+i)); - } -} /** * wlan_crypto_setkey - called by ucfg to setkey * @@ -316,8 +307,8 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_INVAL; } - if ((IS_MGMT_CIPHER(req_key->type)) - || ((req_key->keylen != (cipher->keylen/NBBY)) + if (cipher && (!IS_MGMT_CIPHER(req_key->type)) + && ((req_key->keylen != (cipher->keylen/NBBY)) && (req_key->type != WLAN_CRYPTO_CIPHER_WEP))) { qdf_print("%s[%d] cipher invalid\n", __func__, __LINE__); return QDF_STATUS_E_INVAL; @@ -368,7 +359,13 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, } if (IS_MGMT_CIPHER(req_key->type)) { - key = crypto_priv->igtk_key; + key = qdf_mem_malloc(sizeof(struct wlan_crypto_key)); + if (key == NULL) { + qdf_print("%s[%d] igtk key alloc failed\n", + __func__, __LINE__); + return QDF_STATUS_E_NOMEM; + } + crypto_priv->igtk_key = key; crypto_priv->igtk_key_type = req_key->type; } else { if (!HAS_MCAST_CIPHER(crypto_params, req_key->type) @@ -421,7 +418,13 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_INVAL; } if (IS_MGMT_CIPHER(req_key->type)) { - key = crypto_priv->igtk_key; + key = qdf_mem_malloc(sizeof(struct wlan_crypto_key)); + if (key == NULL) { + qdf_print("%s[%d] igtk key alloc failed\n", + __func__, __LINE__); + return QDF_STATUS_E_NOMEM; + } + crypto_priv->igtk_key = key; } else { uint16_t kid = req_key->keyix; if (kid == WLAN_CRYPTO_KEYIX_NONE) @@ -447,7 +450,8 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, else key->keyix = req_key->keyix; - if (req_key->flags & WLAN_CRYPTO_KEY_DEFAULT) { + if (req_key->flags & WLAN_CRYPTO_KEY_DEFAULT + && (!IS_MGMT_CIPHER(req_key->type))) { crypto_priv->def_tx_keyid = key->keyix; key->flags |= WLAN_CRYPTO_KEY_DEFAULT; } @@ -471,18 +475,14 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, iv_AP[15] += 2; qdf_mem_copy(key->recviv, iv_STA, WLAN_CRYPTO_WAPI_IV_SIZE); - /*initialize send iv */ - qdf_mem_zero((uint8_t *)(key->txiv), + qdf_mem_copy(key->txiv, iv_AP, WLAN_CRYPTO_WAPI_IV_SIZE); - initialize_send_iv(key->txiv, iv_AP); } else { iv_STA[15] += 2; qdf_mem_copy(key->recviv, iv_AP, WLAN_CRYPTO_WAPI_IV_SIZE); - /*initialize send iv */ - qdf_mem_zero((uint8_t *)(key->txiv), + qdf_mem_copy(key->txiv, iv_STA, WLAN_CRYPTO_WAPI_IV_SIZE); - initialize_send_iv(key->txiv, iv_STA); } } else { uint8_t i = 0; @@ -497,9 +497,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, qdf_mem_copy(key->keyval, req_key->keydata, sizeof(key->keyval)); key->valid = 1; - - if ((IS_MGMT_CIPHER(req_key->type)) - && HAS_MGMT_CIPHER(crypto_params, req_key->type)) { + if ((IS_MGMT_CIPHER(req_key->type))) { if (HAS_CIPHER_CAP(crypto_params, WLAN_CRYPTO_CAP_PMF_OFFLOAD)) { if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) { @@ -596,9 +594,9 @@ QDF_STATUS wlan_crypto_getkey(struct wlan_objmgr_vdev *vdev, } if (req_key->keyix == WLAN_CRYPTO_KEYIX_NONE) - key = crypto_priv->key[crypto_priv->def_tx_keyid]; + key = crypto_priv->key[crypto_priv->def_tx_keyid]; else - key = crypto_priv->key[req_key->keyix]; + key = crypto_priv->key[req_key->keyix]; if (!key) return QDF_STATUS_E_INVAL; } @@ -615,6 +613,10 @@ QDF_STATUS wlan_crypto_getkey(struct wlan_objmgr_vdev *vdev, req_key->keylen = key->keylen; req_key->flags = key->flags; cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; + + if (!cipher_table) + return QDF_STATUS_SUCCESS; + req_key->type = cipher_table->cipher; } @@ -643,9 +645,9 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev, uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; if (!vdev || !macaddr || (key_idx >= WLAN_CRYPTO_MAXKEYIDX)) { - qdf_print("%s[%d] Invalid params vdev %p, macaddr %p keyidx %d\n", - __func__, __LINE__, vdev, - macaddr, key_idx); + qdf_print("%s[%d] Invalid params vdev %p, macaddr %p" + "keyidx %d\n", __func__, __LINE__, vdev, + macaddr, key_idx); return QDF_STATUS_E_INVAL; } @@ -742,8 +744,9 @@ QDF_STATUS wlan_crypto_default_key(struct wlan_objmgr_vdev *vdev, wlan_vdev_obj_unlock(vdev); if (!vdev || !macaddr || (key_idx >= WLAN_CRYPTO_MAXKEYIDX)) { - qdf_print("%s[%d] Invalid params vdev %p, macaddr %p keyidx %d\n", - __func__, __LINE__, vdev, macaddr, key_idx); + qdf_print("%s[%d] Invalid params vdev %p, macaddr %p" + "keyidx %d\n", __func__, __LINE__, + vdev, macaddr, key_idx); return QDF_STATUS_E_INVAL; } if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)macaddr)) { @@ -817,6 +820,9 @@ QDF_STATUS wlan_crypto_encap(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_psoc *psoc; uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + if (!wlan_crypto_is_data_protected((uint8_t *)qdf_nbuf_data(wbuf))) + return QDF_STATUS_E_INVAL; + wlan_vdev_obj_lock(vdev); qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN); psoc = wlan_vdev_get_psoc(vdev); @@ -868,7 +874,7 @@ QDF_STATUS wlan_crypto_encap(struct wlan_objmgr_vdev *vdev, /* if tkip, is counter measures enabled, then drop the frame */ cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; status = cipher_table->encap(key, wbuf, encapdone, - ieee80211_hdrsize(wbuf)); + ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf))); return status; } @@ -897,6 +903,9 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_psoc *psoc; uint8_t bssid_mac[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + if (!wlan_crypto_is_data_protected((uint8_t *)qdf_nbuf_data(wbuf))) + return QDF_STATUS_E_INVAL; + wlan_vdev_obj_lock(vdev); qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN); psoc = wlan_vdev_get_psoc(vdev); @@ -947,7 +956,8 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev, } /* if tkip, is counter measures enabled, then drop the frame */ cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; - status = cipher_table->decap(key, wbuf, tid, ieee80211_hdrsize(wbuf)); + status = cipher_table->decap(key, wbuf, tid, + ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf))); return status; } @@ -1027,7 +1037,7 @@ QDF_STATUS wlan_crypto_enmic(struct wlan_objmgr_vdev *vdev, /* if tkip, is counter measures enabled, then drop the frame */ cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; status = cipher_table->enmic(key, wbuf, encapdone, - ieee80211_hdrsize(wbuf)); + ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf))); return status; } @@ -1106,11 +1116,45 @@ QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev, } /* if tkip, is counter measures enabled, then drop the frame */ cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; - status = cipher_table->demic(key, wbuf, tid, ieee80211_hdrsize(wbuf)); + status = cipher_table->demic(key, wbuf, tid, + ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf))); return status; } +/** + * wlan_crypto_vdev_is_pmf_enabled - called to check is pmf enabled in vdev + * + * @vdev: vdev + * + * This function gets called to check is pmf enabled or not in vdev. + * + * Return: true or false + */ +bool wlan_crypto_vdev_is_pmf_enabled(struct wlan_objmgr_vdev *vdev) +{ + + struct wlan_crypto_comp_priv *crypto_priv; + struct wlan_crypto_params *vdev_crypto_params; + + if (!vdev) + return false; + vdev_crypto_params = wlan_crypto_vdev_get_comp_params(vdev, + &crypto_priv); + if (crypto_priv == NULL) { + qdf_print("%s[%d] crypto_priv NULL\n", __func__, __LINE__); + return QDF_STATUS_E_INVAL; + } + + if ((vdev_crypto_params->rsn_caps & + WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) + || (vdev_crypto_params->rsn_caps & + WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) { + return true; + } + + return false; +} /** * wlan_crypto_is_pmf_enabled - called by mgmt txrx to check is pmf enabled * @@ -1145,7 +1189,7 @@ bool wlan_crypto_is_pmf_enabled(struct wlan_objmgr_vdev *vdev, } if (((vdev_crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) && - (vdev_crypto_params->rsn_caps & + (peer_crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) || (vdev_crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)) { @@ -1154,7 +1198,6 @@ bool wlan_crypto_is_pmf_enabled(struct wlan_objmgr_vdev *vdev, return false; } - /** * wlan_crypto_add_mmie - called by mgmt txrx to add mmie in frame * @@ -1174,6 +1217,7 @@ uint8_t *wlan_crypto_add_mmie(struct wlan_objmgr_vdev *vdev, uint8_t *pn, *aad, *buf, *efrm, nounce[12]; struct ieee80211_hdr *hdr; uint32_t i, hdrlen, mic_len, aad_len; + uint8_t mic[16]; struct wlan_crypto_comp_priv *crypto_priv; struct wlan_crypto_params *crypto_params; int32_t ret; @@ -1201,12 +1245,20 @@ uint8_t *wlan_crypto_add_mmie(struct wlan_objmgr_vdev *vdev, efrm = bfrm + len; aad_len = 20; hdrlen = sizeof(struct ieee80211_hdr); + len += sizeof(struct wlan_crypto_mmie); mmie = (struct wlan_crypto_mmie *) efrm; + qdf_mem_zero((unsigned char *)mmie, sizeof(*mmie)); mmie->element_id = WLAN_ELEMID_MMIE; mmie->length = sizeof(*mmie) - 2; mmie->key_id = qdf_cpu_to_le16(key->keyix); + mic_len = (crypto_priv->igtk_key_type + == WLAN_CRYPTO_CIPHER_AES_CMAC) ? 8 : 16; + if (mic_len == 8) { + mmie->length -= 8; + len -= 8; + } /* PN = PN + 1 */ pn = (uint8_t *)&key->keytsc; @@ -1221,11 +1273,12 @@ uint8_t *wlan_crypto_add_mmie(struct wlan_objmgr_vdev *vdev, hdr = (struct ieee80211_hdr *) bfrm; - buf = qdf_mem_malloc(len - hdrlen); + buf = qdf_mem_malloc(len - hdrlen + 20); if (!buf) { qdf_print("%s[%d] malloc failed\n", __func__, __LINE__); return NULL; } + qdf_mem_zero(buf, len - hdrlen + 20); aad = buf; /* generate BIP AAD: FC(masked) || A1 || A2 || A3 */ @@ -1238,27 +1291,35 @@ uint8_t *wlan_crypto_add_mmie(struct wlan_objmgr_vdev *vdev, qdf_mem_copy(aad + 2, hdr->addr1, WLAN_ALEN); qdf_mem_copy(aad + 8, hdr->addr2, WLAN_ALEN); qdf_mem_copy(aad + 14, hdr->addr3, WLAN_ALEN); - qdf_mem_zero(mmie->mic, 16); + qdf_mem_zero(mic, 16); + /* * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */ - qdf_mem_copy(buf + 20, bfrm + hdrlen, len - hdrlen); + + qdf_mem_copy(buf + aad_len, bfrm + hdrlen, len - hdrlen); if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) { - mmie->length -= 8; + ret = omac1_aes_128(key->keyval, buf, - len + aad_len - hdrlen, mmie->mic); + len + aad_len - hdrlen, mic); + qdf_mem_copy(mmie->mic, mic, 8); + } else if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC_256) { + ret = omac1_aes_256(key->keyval, buf, len + aad_len - hdrlen, mmie->mic); + } else if ((crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_GMAC) || (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_GMAC_256)) { + qdf_mem_copy(nounce, hdr->addr2, WLAN_ALEN); qdf_mem_copy(nounce + 6, pn, 6); ret = wlan_crypto_aes_gmac(key->keyval, key->keylen, nounce, sizeof(nounce), buf, len + aad_len - hdrlen, mmie->mic); + } qdf_mem_free(buf); if (ret < 0) { @@ -1266,10 +1327,8 @@ uint8_t *wlan_crypto_add_mmie(struct wlan_objmgr_vdev *vdev, return NULL; } - len += sizeof(struct wlan_crypto_mmie); - if (mic_len == 8) - len -= 8; key->keytsc++; + return bfrm + len; } @@ -1342,7 +1401,7 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev, return false; } - buf = qdf_mem_malloc(len - hdrlen); + buf = qdf_mem_malloc(len - hdrlen + 20); if (!buf) { qdf_print("%s[%d] malloc failed\n", __func__, __LINE__); return false; @@ -1365,10 +1424,11 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev, * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */ qdf_mem_copy(buf + 20, frm + hdrlen, len - hdrlen); + qdf_mem_zero(buf + (len - hdrlen + 20 - mic_len), mic_len); + qdf_mem_zero(mic, 16); if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) { - mmie->length -= 8; ret = omac1_aes_128(key->keyval, buf, - len + aad_len - hdrlen, mic); + len - hdrlen + aad_len, mic); } else if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC_256) { ret = omac1_aes_256(key->keyval, buf, @@ -1398,6 +1458,7 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev, /* Update the receive sequence number */ qdf_mem_copy(key->keyrsc, ipn, 6); + qdf_print("%s[%d] mmie matched\n", __func__, __LINE__); return true; } @@ -2056,6 +2117,7 @@ uint8_t *wlan_crypto_build_rsnie(struct wlan_crypto_params *crypto_params, return frm; } + bool wlan_crypto_rsn_info(struct wlan_objmgr_vdev *vdev, struct wlan_crypto_params *crypto_params){ struct wlan_crypto_params *my_crypto_params; @@ -2253,3 +2315,37 @@ struct wlan_lmac_if_crypto_rx_ops *wlan_crypto_get_crypto_rx_ops( return &(psoc->soc_cb.rx_ops.crypto_rx_ops); } EXPORT_SYMBOL(wlan_crypto_get_crypto_rx_ops); + +/** + * wlan_crypto_vdev_has_auth_mode - check authmode for vdev + * + * @vdev: vdev + * @authvalue: authvalue to be checked + * + * This function check is authvalue passed is set in vdev or not + * + * Return: true or false + */ +bool wlan_crypto_vdev_has_auth_mode(struct wlan_objmgr_vdev *vdev, + wlan_crypto_auth_mode authvalue) +{ + return wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_AUTH_MODE) + & authvalue; +} + +/** + * wlan_crypto_peer_has_auth_mode - check authmode for peer + * + * @peer: peer + * @authvalue: authvalue to be checked + * + * This function check is authvalue passed is set in peer or not + * + * Return: true or false + */ +bool wlan_crypto_peer_has_auth_mode(struct wlan_objmgr_peer *peer, + wlan_crypto_auth_mode authvalue) +{ + return wlan_crypto_get_peer_param(peer, WLAN_CRYPTO_PARAM_AUTH_MODE) + & authvalue; +}