From b0ac369215b6cb8ad41dc99fb99b3bc3bd61a23a Mon Sep 17 00:00:00 2001 From: Nandha Kishore Easwaran Date: Fri, 8 Dec 2017 10:39:00 +0530 Subject: [PATCH] qcacmn: Delete igtk keys: key_idx 4 and 5 for PMF Delete igtk keys of index 4, 5 if PMF configuration is changed Change-Id: I5f0de09fb713864a0e2cb3036633bf5c131e1f8c --- .../crypto/inc/wlan_crypto_global_def.h | 1 + .../crypto/src/wlan_crypto_def_i.h | 5 +- .../crypto/src/wlan_crypto_global_api.c | 76 ++++++++++++++----- .../crypto/src/wlan_crypto_obj_mgr.c | 8 +- 4 files changed, 68 insertions(+), 22 deletions(-) diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h index 64a2bb3c4b8c..8c341568ad0e 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h @@ -41,6 +41,7 @@ #define WLAN_CRYPTO_EXT_IV_BIT (0x20) #define WLAN_CRYPTO_KEYIX_NONE ((uint16_t)-1) #define WLAN_CRYPTO_MAXKEYIDX (4) +#define WLAN_CRYPTO_MAXIGTKKEYIDX (2) /* 40 bit wep key len */ #define WLAN_CRYPTO_KEY_WEP40_LEN (5) 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 6da06c537ed3..602e1a7f0d0d 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h @@ -393,10 +393,11 @@ struct wlan_crypto_mmie { struct wlan_crypto_comp_priv { struct wlan_crypto_params crypto_params; - struct wlan_crypto_key *key[4]; - struct wlan_crypto_key *igtk_key; + struct wlan_crypto_key *key[WLAN_CRYPTO_MAXKEYIDX]; + struct wlan_crypto_key *igtk_key[WLAN_CRYPTO_MAXIGTKKEYIDX]; uint32_t igtk_key_type; uint8_t def_tx_keyid; + uint8_t def_igtk_tx_keyid; }; 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 474f6b22a82c..10cc5d675e9d 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -276,6 +276,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, uint8_t macaddr[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; bool isbcast; enum QDF_OPMODE vdev_mode; + uint8_t igtk_idx = 0; if (!vdev || !req_key || req_key->keylen > (sizeof(req_key->keydata))) { qdf_print("%s[%d] Invalid params vdev%pK, req_key%pK\n", @@ -367,14 +368,25 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, } if (IS_MGMT_CIPHER(req_key->type)) { + igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX; + if (igtk_idx > WLAN_CRYPTO_MAXIGTKKEYIDX) { + qdf_print("%s[%d] igtk key invalid keyid %d \n", + __func__, __LINE__, igtk_idx); + return QDF_STATUS_E_INVAL; + } 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; + + if (crypto_priv->igtk_key[igtk_idx]) + qdf_mem_free(crypto_priv->igtk_key[igtk_idx]); + + crypto_priv->igtk_key[igtk_idx] = key; crypto_priv->igtk_key_type = req_key->type; + crypto_priv->def_igtk_tx_keyid = igtk_idx; } else { if (!HAS_MCAST_CIPHER(crypto_params, req_key->type) && (req_key->type != WLAN_CRYPTO_CIPHER_WEP)) { @@ -397,7 +409,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, qdf_print("%s[%d] peer %pK failed\n", __func__, __LINE__, peer); if (IS_MGMT_CIPHER(req_key->type)) { - crypto_priv->igtk_key = NULL; + crypto_priv->igtk_key[igtk_idx] = NULL; crypto_priv->igtk_key_type = WLAN_CRYPTO_CIPHER_NONE; } else @@ -433,13 +445,24 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_INVAL; } if (IS_MGMT_CIPHER(req_key->type)) { + igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX; + if (igtk_idx > WLAN_CRYPTO_MAXIGTKKEYIDX) { + qdf_print("%s[%d] igtk key invalid keyid %d \n", + __func__, __LINE__, igtk_idx); + return QDF_STATUS_E_INVAL; + } 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; + if (crypto_priv->igtk_key[igtk_idx]) + qdf_mem_free(crypto_priv->igtk_key[igtk_idx]); + + crypto_priv->igtk_key[igtk_idx] = key; + crypto_priv->igtk_key_type = req_key->type; + crypto_priv->def_igtk_tx_keyid = igtk_idx; } else { uint16_t kid = req_key->keyix; if (kid == WLAN_CRYPTO_KEYIX_NONE) @@ -668,7 +691,9 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_psoc *psoc; uint8_t bssid_mac[WLAN_ALEN]; - if (!vdev || !macaddr || (key_idx >= WLAN_CRYPTO_MAXKEYIDX)) { + if (!vdev || !macaddr || + (key_idx > + (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))) { qdf_print("%s[%d] Invalid params vdev %pK, macaddr %pK" "keyidx %d\n", __func__, __LINE__, vdev, macaddr, key_idx); @@ -693,11 +718,6 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev, __func__, __LINE__); return QDF_STATUS_E_INVAL; } - - key = crypto_priv->key[key_idx]; - if (!key) - return QDF_STATUS_E_INVAL; - crypto_priv->key[key_idx] = NULL; } else { struct wlan_objmgr_peer *peer; @@ -716,12 +736,21 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev, __func__, __LINE__); return QDF_STATUS_E_INVAL; } + } + if (key_idx >= WLAN_CRYPTO_MAXKEYIDX) { + uint8_t igtk_idx = key_idx - WLAN_CRYPTO_MAXKEYIDX; + key = crypto_priv->igtk_key[igtk_idx]; + crypto_priv->igtk_key[igtk_idx] = NULL; + key->valid = 0; + } else { key = crypto_priv->key[key_idx]; - if (!key) - return QDF_STATUS_E_INVAL; crypto_priv->key[key_idx] = NULL; } + + if (!key) + return QDF_STATUS_E_INVAL; + if (key->valid) { cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; @@ -1258,7 +1287,13 @@ uint8_t *wlan_crypto_add_mmie(struct wlan_objmgr_vdev *vdev, return NULL; } - key = crypto_priv->igtk_key; + if (crypto_priv->def_igtk_tx_keyid > WLAN_CRYPTO_MAXIGTKKEYIDX) { + qdf_print("%s[%d] igtk key invalid keyid %d \n", + __func__, __LINE__, crypto_priv->def_igtk_tx_keyid); + return NULL; + } + + key = crypto_priv->igtk_key[crypto_priv->def_igtk_tx_keyid]; if (!key) { qdf_print("%s[%d] No igtk key present\n", __func__, __LINE__); return NULL; @@ -1396,11 +1431,6 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev, crypto_params = &(crypto_priv->crypto_params); - key = crypto_priv->igtk_key; - if (!key) { - qdf_print("%s[%d] No igtk key present\n", __func__, __LINE__); - return false; - } mic_len = (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) ? 8 : 16; @@ -1418,6 +1448,18 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev, return false; } + if (mmie->key_id > (WLAN_CRYPTO_MAXKEYIDX + + WLAN_CRYPTO_MAXIGTKKEYIDX)) { + qdf_print("%s[%d] keyid not valid\n", __func__, __LINE__); + return false; + } + + key = crypto_priv->igtk_key[mmie->key_id - WLAN_CRYPTO_MAXKEYIDX]; + if (!key) { + qdf_print("%s[%d] No igtk key present\n", __func__, __LINE__); + return false; + } + /* validate ipn */ ipn = mmie->sequence_number; if (qdf_mem_cmp(ipn, key->keyrsc, 6) <= 0) { diff --git a/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c b/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c index 585c1949d69b..0a9ad7bcd948 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c @@ -204,9 +204,11 @@ static void wlan_crypto_free_key(struct wlan_crypto_comp_priv *crypto_priv) } } - if (crypto_priv->igtk_key) { - qdf_mem_free(crypto_priv->igtk_key); - crypto_priv->igtk_key = NULL; + for (i = 0; i < WLAN_CRYPTO_MAXIGTKKEYIDX; i++) { + if (crypto_priv->igtk_key[i]) { + qdf_mem_free(crypto_priv->igtk_key[i]); + crypto_priv->igtk_key[i] = NULL; + } } }