From 25531c4717a8387b489ffd4103603da3879ec2a6 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Wed, 19 Sep 2018 13:48:48 -0700 Subject: [PATCH] qcacmn: Add support for SET KEY convergence Make changes to the cmn driver to support SET KEY convergence feature Change-Id: I17b5f368a1f735eb394ea70f9b61cc033c3eb20a CRs-Fixed: 2358796 --- os_if/linux/crypto/inc/wlan_cfg80211_crypto.h | 72 ++++++ .../crypto/inc/wlan_nl_to_crypto_params.h | 16 +- os_if/linux/crypto/src/wlan_cfg80211_crypto.c | 138 +++++++++++ .../crypto/src/wlan_nl_to_crypto_params.c | 37 ++- target_if/core/src/target_if_main.c | 19 +- target_if/crypto/inc/target_if_crypto.h | 48 ++++ target_if/crypto/src/target_if_crypto.c | 224 ++++++++++++++++++ .../crypto/inc/wlan_crypto_global_api.h | 125 +++++++++- .../crypto/inc/wlan_crypto_global_def.h | 50 +++- .../crypto/src/wlan_crypto_def_i.h | 4 +- .../crypto/src/wlan_crypto_global_api.c | 180 +++++++++++++- .../crypto/src/wlan_crypto_param_handling.c | 4 +- .../crypto/src/wlan_crypto_ucfg_api.c | 42 ++++ wmi/inc/wmi_unified_api.h | 22 +- wmi/inc/wmi_unified_param.h | 5 +- wmi/src/wmi_unified_api.c | 60 ++++- wmi/src/wmi_unified_tlv.c | 8 +- 17 files changed, 1014 insertions(+), 40 deletions(-) create mode 100644 os_if/linux/crypto/inc/wlan_cfg80211_crypto.h create mode 100644 os_if/linux/crypto/src/wlan_cfg80211_crypto.c create mode 100644 target_if/crypto/inc/target_if_crypto.h create mode 100644 target_if/crypto/src/target_if_crypto.c create mode 100644 umac/cmn_services/crypto/src/wlan_crypto_ucfg_api.c diff --git a/os_if/linux/crypto/inc/wlan_cfg80211_crypto.h b/os_if/linux/crypto/inc/wlan_cfg80211_crypto.h new file mode 100644 index 0000000000..6a70eb5c28 --- /dev/null +++ b/os_if/linux/crypto/inc/wlan_cfg80211_crypto.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declares crypto functions interfacing with linux kernel + */ + +#ifndef _WLAN_CFG80211_CRYPTO_H_ +#define _WLAN_CFG80211_CRYPTO_H_ +#include + +#ifdef CONFIG_CRYPTO_COMPONENT +/** + * wlan_cfg80211_set_default_key() - to set the default key to be used + * @vdev: VDEV Object pointer + * @key_index: Index to be set as the default + * @bssid: BSSID for which the key is to be set + * + * Return: Zero for success and negative for failure. + */ +int wlan_cfg80211_set_default_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index, + struct qdf_mac_addr *bssid); +#else +static inline int wlan_cfg80211_set_default_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index, + struct qdf_mac_addr *bssid) +{ + return 0; +} +#endif + +/** + * wlan_cfg80211_store_key() - Store the key + * @vdev: VDEV Object pointer + * @key_index: Index to be set as the default + * @pairwise: denotes if the key is pairwise or group key + * @mac_addr: BSSID for which the key is to be set + * @key_params: Params received from the kernel + * + * Return: Zero for success and negative for failure. + */ +int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index, bool pairwise, + const u8 *mac_addr, struct key_params *params); + +/** + * wlan_cfg80211_crypto_add_key() - Add key for the specified vdev + * @vdev: vdev object + * @pairwise: denotes if the add key request is for pairwise or group key + * @key_index: Index of the key that needs to be added + * + * Return: Zero on Success, negative value on failure + */ +int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev, bool pairwise, + uint8_t key_index); +#endif diff --git a/os_if/linux/crypto/inc/wlan_nl_to_crypto_params.h b/os_if/linux/crypto/inc/wlan_nl_to_crypto_params.h index bc49fc7a08..58e44c21f4 100644 --- a/os_if/linux/crypto/inc/wlan_nl_to_crypto_params.h +++ b/os_if/linux/crypto/inc/wlan_nl_to_crypto_params.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -52,6 +52,16 @@ int osif_nl_to_crypto_akm_type(u32 key_mgmt); * set the crypto cipher type for corresponding cipher type received * from NL. * - * Return: crypto cipher type, negative value for failure + * Return: crypto cipher type */ -int osif_nl_to_crypto_cipher_type(u32 cipher); +enum wlan_crypto_cipher_type osif_nl_to_crypto_cipher_type(u32 cipher); + +/** + * osif_nl_to_crypto_cipher_len() - return the cipher length + * @cipher: NL cipher type + * + * Check the cipher type and return the corresponding length + * + * Return: crypto cipher length, negative value for failure + */ +int osif_nl_to_crypto_cipher_len(u32 cipher); diff --git a/os_if/linux/crypto/src/wlan_cfg80211_crypto.c b/os_if/linux/crypto/src/wlan_cfg80211_crypto.c new file mode 100644 index 0000000000..90694f43a2 --- /dev/null +++ b/os_if/linux/crypto/src/wlan_cfg80211_crypto.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: defines crypto driver functions interfacing with linux kernel + */ +#include +#include +#include +#include +#include +#include +#include "wlan_cfg80211_crypto.h" +#include + +static void wlan_cfg80211_translate_key(uint8_t key_index, bool pairwise, + const u8 *mac_addr, + struct key_params *params, + struct wlan_crypto_key *crypto_key) +{ + static const struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT; + + qdf_mem_zero(crypto_key, sizeof(*crypto_key)); + crypto_key->keylen = params->key_len; + crypto_key->keyix = key_index; + qdf_mem_copy(&crypto_key->keyval[0], params->key, params->key_len); + qdf_mem_copy(&crypto_key->keyrsc[0], params->seq, params->seq_len); + + crypto_key->cipher_type = osif_nl_to_crypto_cipher_type(params->cipher); + if (pairwise) { + crypto_key->flags |= PAIRWISE_USAGE; + qdf_mem_copy(&crypto_key->macaddr, mac_addr, + QDF_MAC_ADDR_SIZE); + } else { + crypto_key->flags |= GROUP_USAGE; + qdf_mem_copy(&crypto_key->macaddr, &bcast_mac, + QDF_MAC_ADDR_SIZE); + } +} + +int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index, bool pairwise, + const u8 *mac_addr, struct key_params *params) +{ + struct wlan_crypto_key *crypto_key = NULL; + enum wlan_crypto_cipher_type cipher; + int cipher_len; + QDF_STATUS status; + + if (!vdev) { + cfg80211_err("vdev is NULL"); + return -EINVAL; + } + if (!params) { + cfg80211_err("Key params is NULL"); + return -EINVAL; + } + if (pairwise && !mac_addr) { + cfg80211_err("mac_addr is NULL for pairwise Key"); + return -EINVAL; + } + cipher_len = osif_nl_to_crypto_cipher_len(params->cipher); + if (cipher_len < 0 || params->key_len < cipher_len) { + cfg80211_err("cipher length %d less than reqd len %d", + params->key_len, cipher_len); + return -EINVAL; + } + cipher = osif_nl_to_crypto_cipher_type(params->cipher); + status = wlan_crypto_validate_key_params(cipher, key_index, + params->key_len, + params->seq_len); + if (QDF_IS_STATUS_ERROR(status)) { + cfg80211_err("Invalid key params"); + return -EINVAL; + } + + /* + * key may already exist at times and may be retrieved only to + * update it. + */ + crypto_key = wlan_crypto_get_key(vdev, key_index); + if (!crypto_key) { + crypto_key = qdf_mem_malloc(sizeof(*crypto_key)); + if (!crypto_key) + return -EINVAL; + status = wlan_crypto_save_key(vdev, key_index, crypto_key); + if (QDF_IS_STATUS_ERROR(status)) { + cfg80211_err("Failed to save key"); + qdf_mem_free(crypto_key); + return -EINVAL; + } + } + + wlan_cfg80211_translate_key(key_index, pairwise, mac_addr, + params, crypto_key); + + return 0; +} + +int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev, bool pairwise, + uint8_t key_index) +{ + struct wlan_crypto_key *crypto_key; + QDF_STATUS status; + + crypto_key = wlan_crypto_get_key(vdev, key_index); + if (!crypto_key) { + cfg80211_err("Crypto KEY is NULL"); + return -EINVAL; + } + status = ucfg_crypto_set_key_req(vdev, crypto_key, pairwise); + + return qdf_status_to_os_return(status); +} + +#ifdef CONFIG_CRYPTO_COMPONENT +int wlan_cfg80211_set_default_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index, struct qdf_mac_addr *bssid) +{ + return wlan_crypto_default_key(vdev, (uint8_t *)bssid, + key_index, true); +} +#endif diff --git a/os_if/linux/crypto/src/wlan_nl_to_crypto_params.c b/os_if/linux/crypto/src/wlan_nl_to_crypto_params.c index 90aa67c8ee..59cfda57f4 100644 --- a/os_if/linux/crypto/src/wlan_nl_to_crypto_params.c +++ b/os_if/linux/crypto/src/wlan_nl_to_crypto_params.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -55,12 +55,14 @@ struct osif_akm_type_crypto_mapping { * to internal crypto cipher type * @cipher_suite: NL cipher type * @cipher_crypto: cipher crypto type + * @cipher_len: Length of the cipher * * mapping cipher type received from NL to internal crypto cipher type */ struct osif_cipher_crypto_mapping { u32 cipher_suite; wlan_crypto_cipher_type cipher_crypto; + u32 cipher_len; }; /** @@ -160,57 +162,70 @@ static const struct osif_cipher_crypto_mapping { .cipher_suite = IW_AUTH_CIPHER_NONE, .cipher_crypto = WLAN_CRYPTO_CIPHER_NONE, + .cipher_len = 0, }, { .cipher_suite = WLAN_CIPHER_SUITE_WEP40, .cipher_crypto = WLAN_CRYPTO_CIPHER_WEP_40, + .cipher_len = WLAN_CRYPTO_KEY_WEP40_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_TKIP, .cipher_crypto = WLAN_CRYPTO_CIPHER_TKIP, + .cipher_len = WLAN_CRYPTO_KEY_TKIP_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_CCMP, .cipher_crypto = WLAN_CRYPTO_CIPHER_AES_CCM, + .cipher_len = WLAN_CRYPTO_KEY_CCMP_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_WEP104, .cipher_crypto = WLAN_CRYPTO_CIPHER_WEP_104, + .cipher_len = WLAN_CRYPTO_KEY_WEP104_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_GCMP, .cipher_crypto = WLAN_CRYPTO_CIPHER_AES_GCM, + .cipher_len = WLAN_CRYPTO_KEY_GCMP_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_GCMP_256, .cipher_crypto = WLAN_CRYPTO_CIPHER_AES_GCM_256, + .cipher_len = WLAN_CRYPTO_KEY_GCMP_256_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_CCMP_256, .cipher_crypto = WLAN_CRYPTO_CIPHER_AES_CCM_256, + .cipher_len = WLAN_CRYPTO_KEY_CCMP_256_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_AES_CMAC, .cipher_crypto = WLAN_CRYPTO_CIPHER_AES_CMAC, + .cipher_len = WLAN_CRYPTO_KEY_CCMP_LEN, }, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) { .cipher_suite = WLAN_CIPHER_SUITE_BIP_GMAC_128, .cipher_crypto = WLAN_CRYPTO_CIPHER_AES_GMAC, + .cipher_len = WLAN_CRYPTO_KEY_GMAC_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_BIP_GMAC_256, .cipher_crypto = WLAN_CRYPTO_CIPHER_AES_GMAC_256, + .cipher_len = WLAN_CRYPTO_KEY_GMAC_256_LEN, }, { .cipher_suite = WLAN_CIPHER_SUITE_BIP_CMAC_256, .cipher_crypto = WLAN_CRYPTO_CIPHER_AES_CMAC_256, + .cipher_len = WLAN_CRYPTO_KEY_CCMP_256_LEN, }, #endif #ifdef FEATURE_WLAN_WAPI { .cipher_suite = WLAN_CIPHER_SUITE_SMS4, .cipher_crypto = WLAN_CRYPTO_CIPHER_WAPI_SMS4, + .cipher_len = WLAN_CRYPTO_KEY_WAPI_LEN, }, #endif }; @@ -257,13 +272,13 @@ int osif_nl_to_crypto_akm_type(u32 key_mgmt) return crypto_akm_type; } -int osif_nl_to_crypto_cipher_type(u32 cipher) +enum wlan_crypto_cipher_type osif_nl_to_crypto_cipher_type(u32 cipher) { uint8_t index; bool cipher_crypto_exist = false; wlan_crypto_cipher_type crypto_cipher_type = WLAN_CRYPTO_CIPHER_NONE; - for (index = 0; index < QDF_ARRAY_SIZE(osif_auth_type_crypto_mapping); + for (index = 0; index < QDF_ARRAY_SIZE(osif_cipher_crypto_mapping); index++) { if (osif_cipher_crypto_mapping[index].cipher_suite == cipher) { crypto_cipher_type = osif_cipher_crypto_mapping[index]. @@ -275,10 +290,24 @@ int osif_nl_to_crypto_cipher_type(u32 cipher) if (!cipher_crypto_exist) { QDF_TRACE_ERROR(QDF_MODULE_ID_OS_IF, "Unknown type: %d", cipher); - return -EINVAL; + return WLAN_CRYPTO_CIPHER_INVALID; } QDF_TRACE_DEBUG(QDF_MODULE_ID_OS_IF, "Cipher suite, NL: %d, crypto: %d", cipher, crypto_cipher_type); return crypto_cipher_type; } + +int osif_nl_to_crypto_cipher_len(u32 cipher) +{ + uint8_t index; + + for (index = 0; index < QDF_ARRAY_SIZE(osif_cipher_crypto_mapping); + index++) { + if (osif_cipher_crypto_mapping[index].cipher_suite == cipher) + return osif_cipher_crypto_mapping[index].cipher_len; + } + + return -EINVAL; +} + diff --git a/target_if/core/src/target_if_main.c b/target_if/core/src/target_if_main.c index 4e3c978c88..ce4045a909 100644 --- a/target_if/core/src/target_if_main.c +++ b/target_if/core/src/target_if_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -72,6 +72,9 @@ #include "qdf_module.h" #include +#ifdef CRYPTO_SET_KEY_CONVERGED +#include +#endif static struct target_if_ctx *g_target_if_ctx; @@ -313,6 +316,18 @@ static QDF_STATUS target_if_green_ap_tx_ops_register( return QDF_STATUS_SUCCESS; } #endif /* WLAN_SUPPORT_GREEN_AP */ +#if defined(WLAN_CONV_CRYPTO_SUPPORTED) && defined(CRYPTO_SET_KEY_CONVERGED) +static void target_if_crypto_tx_ops_register( + struct wlan_lmac_if_tx_ops *tx_ops) +{ + target_if_crypto_register_tx_ops(tx_ops); +} +#else +static inline void target_if_crypto_tx_ops_register( + struct wlan_lmac_if_tx_ops *tx_ops) +{ +} +#endif static void target_if_target_tx_ops_register( struct wlan_lmac_if_tx_ops *tx_ops) @@ -402,6 +417,8 @@ QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) target_if_cp_stats_tx_ops_register(tx_ops); + target_if_crypto_tx_ops_register(tx_ops); + /* Converged UMAC components to register their TX-ops here */ return QDF_STATUS_SUCCESS; } diff --git a/target_if/crypto/inc/target_if_crypto.h b/target_if/crypto/inc/target_if_crypto.h new file mode 100644 index 0000000000..4be54582b1 --- /dev/null +++ b/target_if/crypto/inc/target_if_crypto.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declares crypto functions interfacing with the target + */ + +#ifndef __TARGET_IF_CRYPTO_H__ +#define __TARGET_IF_CRYPTO_H__ +#include + +/** + * target_if_crypto_register_tx_ops() - lmac handler to register + * crypto tx_ops callback functions + * @tx_ops: wlan_lmac_if_tx_ops object + * + * Return: QDF_STATUS + */ +QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); + +/** + * target_if_crypto_set_key() - lmac handler to set key + * @vdev: VDEV object pointer + * @req: Key parameters that are required to install the key + * @key_type: Pairwise or Group Key type + * + * Return: QDF_STATUS + */ +QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *req, + enum wlan_crypto_key_type key_type); + +#endif diff --git a/target_if/crypto/src/target_if_crypto.c b/target_if/crypto/src/target_if_crypto.c new file mode 100644 index 0000000000..b80bc952e3 --- /dev/null +++ b/target_if/crypto/src/target_if_crypto.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: offload lmac interface APIs definitions for crypto + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef FEATURE_WLAN_WAPI +static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev, + bool pairwise, + enum wlan_crypto_cipher_type cipher_type, + struct set_key_params *params) +{ + static const unsigned char tx_iv[16] = {0x36, 0x5c, 0x36, 0x5c, 0x36, + 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, + 0x5c}; + + static const unsigned char rx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, + 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x37}; + + if (cipher_type != WLAN_CRYPTO_CIPHER_WAPI_SMS4 || + cipher_type != WLAN_CRYPTO_CIPHER_WAPI_GCM4) + return; + + qdf_mem_copy(¶ms->rx_iv, &rx_iv, + WLAN_CRYPTO_WAPI_IV_SIZE); + qdf_mem_copy(¶ms->tx_iv, &tx_iv, + WLAN_CRYPTO_WAPI_IV_SIZE); + + if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) { + if (pairwise) + params->tx_iv[0] = 0x37; + + params->rx_iv[WLAN_CRYPTO_WAPI_IV_SIZE - 1] = 0x36; + } else { + if (!pairwise) + params->rx_iv[WLAN_CRYPTO_WAPI_IV_SIZE - 1] = 0x36; + } + + params->key_txmic_len = WLAN_CRYPTO_MIC_LEN; + params->key_rxmic_len = WLAN_CRYPTO_MIC_LEN; +} +#else +static inline void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev, + bool pairwise, + enum wlan_crypto_cipher_type cipher, + struct set_key_params *params) +{ +} +#endif /* FEATURE_WLAN_WAPI */ + +#ifdef BIG_ENDIAN_HOST +static void wlan_crypto_endianness_conversion(uint8_t *dest, uint8_t *src, + uint32_t keylen) +{ + int8_t i; + + for (i = 0; i < roundup(keylen, sizeof(uint32_t)) / 4; i++) { + *dest = le32_to_cpu(*src); + dest++; + src++; + } +} +#else +static void wlan_crypto_endianness_conversion(uint8_t *dest, uint8_t *src, + uint32_t keylen) +{ + qdf_mem_copy(dest, src, keylen); +} +#endif + +QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *req, + enum wlan_crypto_key_type key_type) +{ + struct set_key_params params = {0}; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + enum cdp_sec_type sec_type = cdp_sec_type_none; + void *soc = cds_get_context(QDF_MODULE_ID_SOC); + struct cdp_pdev *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX); + struct cdp_vdev *txrx_vdev; + uint32_t pn[4] = {0, 0, 0, 0}; + struct cdp_peer *peer = NULL; + uint8_t peer_id; + uint8_t def_tx_idx; + void *pdev_wmi_handle; + bool pairwise = false; + QDF_STATUS status; + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + target_if_err("Invalid PDEV"); + return QDF_STATUS_E_FAILURE; + } + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + target_if_err("Invalid PSOC"); + return QDF_STATUS_E_FAILURE; + } + soc = wlan_psoc_get_dp_handle(psoc); + if (!soc) { + target_if_err("Invalid DP Handle"); + return QDF_STATUS_E_FAILURE; + } + params.vdev_id = wlan_vdev_get_id(vdev); + params.key_idx = req->keyix; + qdf_mem_copy(params.peer_mac, req->macaddr, IEEE80211_ADDR_LEN); + pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); + if (!pdev_wmi_handle) { + target_if_err("Invalid PDEV WMI handle"); + return QDF_STATUS_E_FAILURE; + } + + if (key_type != WLAN_CRYPTO_KEY_TYPE_UNICAST) + pairwise = false; + qdf_mem_copy(¶ms.key_rsc_ctr, + &req->keyrsc[0], sizeof(uint64_t)); + params.key_flags = req->flags; + txrx_vdev = (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc, + (struct cdp_pdev *)txrx_pdev, params.vdev_id); + peer = cdp_peer_find_by_addr(soc, txrx_pdev, req->macaddr, &peer_id); + + if (!txrx_vdev) { + target_if_err("Invalid txrx vdev"); + return QDF_STATUS_E_FAILURE; + } + + if (!peer) { + target_if_err("Invalid peer"); + return QDF_STATUS_E_FAILURE; + } + + params.key_cipher = wlan_crypto_cipher_to_wmi_cipher(req->cipher_type); + sec_type = wlan_crypto_cipher_to_cdp_sec_type(req->cipher_type); + wlan_crypto_set_wapi_key(vdev, pairwise, req->cipher_type, ¶ms); + + switch (req->cipher_type) { + case WLAN_CRYPTO_CIPHER_WEP: + def_tx_idx = wlan_crypto_get_default_key_idx(vdev, false); + if (pairwise && params.key_idx == def_tx_idx) + params.key_flags |= TX_USAGE; + else if ((vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) && + (params.key_idx == def_tx_idx)) + params.key_flags |= TX_USAGE; + break; + case WLAN_CRYPTO_CIPHER_TKIP: + params.key_txmic_len = WLAN_CRYPTO_MIC_LEN; + params.key_rxmic_len = WLAN_CRYPTO_MIC_LEN; + break; + default: + break; + } + + wlan_crypto_endianness_conversion(¶ms.key_data[0], + &req->keyval[0], + req->keylen); + params.key_len = req->keylen; + /* Set PN check & security type in data path */ + cdp_set_pn_check(soc, txrx_vdev, peer, sec_type, pn); + cdp_set_key(soc, peer, pairwise, + (uint32_t *)(req->keyval + + WLAN_CRYPTO_IV_SIZE + + WLAN_CRYPTO_MIC_LEN)); + + target_if_debug("vdev_id:%d, key: idx:%d,len:%d", params.vdev_id, + params.key_idx, params.key_len); + target_if_debug("peer mac %pM", params.peer_mac); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_DEBUG, + ¶ms.key_rsc_ctr, sizeof(uint64_t)); + status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, ¶ms); + + return status; +} + +QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + struct wlan_lmac_if_crypto_tx_ops *crypto; + + if (!tx_ops) { + target_if_err("txops NULL"); + return QDF_STATUS_E_FAILURE; + } + crypto = &tx_ops->crypto_tx_ops; + + crypto->set_key = target_if_crypto_set_key; + + return QDF_STATUS_SUCCESS; +} + 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 0bb58d5582..22d6c335f1 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -23,7 +23,6 @@ #define _WLAN_CRYPTO_GLOBAL_API_H_ #include "wlan_crypto_global_def.h" - /** * wlan_crypto_set_vdev_param - called by ucfg to set crypto param * @vdev: vdev @@ -679,4 +678,126 @@ static inline int omac1_aes_256(const uint8_t *key, const uint8_t *data, } #endif +/** + * ucfg_crypto_set_key_req() - Set key request to UCFG + * @vdev: vdev object + * @req: key request information + * @pairwise: indicates the type of key to be set, unicast or group key + * + * Return: None + */ +QDF_STATUS ucfg_crypto_set_key_req(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *req, bool pairwise); + +/** + * wlan_crypto_get_default_key_idx() - Get the default key index + * @vdev: vdev object + * @igtk: denotes if the request is for igtk key type or not + * + * Return: Index of the requested key + */ +int8_t wlan_crypto_get_default_key_idx(struct wlan_objmgr_vdev *vdev, + bool igtk); + +/** + * wlan_crypto_get_cipher() - Get the cipher type for the vdev + * @vdev: vdev object + * @pairwise: denotes if the request is for pairwise cipher or not + * @key_index: Index of the key whose cipher type has to be returned + * + * Return: enum wlan_crypto_cipher_type + */ +enum wlan_crypto_cipher_type +wlan_crypto_get_cipher(struct wlan_objmgr_vdev *vdev, + bool pairwise, uint8_t key_index); + +#ifdef CRYPTO_SET_KEY_CONVERGED +/** + * wlan_crypto_update_set_key_peer() - Update the peer for set key + * @vdev: vdev object + * @pairwise: denotes if the request is for pairwise cipher or not + * @key_index: Index of the key whose peer has to be set + * @peer_mac: MAC address of the peer + * + * Return: None + */ +void wlan_crypto_update_set_key_peer(struct wlan_objmgr_vdev *vdev, + bool pairwise, uint8_t key_index, + struct qdf_mac_addr *peer_mac); + +/** + * wlan_crypto_validate_key_params() - validates key parameters + * @cipher: cipher type + * @key_index: the index of the key + * @key_len: key length + * @seq_len: sequence counter length + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_crypto_validate_key_params(enum wlan_crypto_cipher_type cipher, + uint8_t key_index, uint8_t key_len, + uint8_t seq_len); + +/** + * wlan_crypto_save_key() - Allocate memory for storing key + * @vdev: vdev object + * @key_index: the index of the key that needs to be allocated + * @crypto_key: Pointer to crypto key + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index, + struct wlan_crypto_key *crypto_key); + +/** + * wlan_crypto_get_key() - Get the stored key information + * @vdev: vdev object + * @key_index: the index of the key that needs to be retrieved + * + * Return: Key material + */ +struct wlan_crypto_key *wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index); + +/** + * wlan_crypto_set_key_req() - Set key request + * @vdev: vdev object + * @req: key request information + * @pairwise: indicates the type of key to be set, unicast or group key + * + * Return: QDF status + */ +QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *req, bool pairwise); +#else +static inline void wlan_crypto_update_set_key_peer( + struct wlan_objmgr_vdev *vdev, + bool pairwise, + uint8_t key_index, + struct qdf_mac_addr *peer_mac) +{ +} + +static inline QDF_STATUS +wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev, uint8_t key_index, + struct wlan_crypto_key *crypto_key) +{ + return QDF_STATUS_SUCCESS; +} + +static inline struct wlan_crypto_key * +wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev, uint8_t key_index) +{ + return NULL; +} + +static inline QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *req, + bool pairwise) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* CRYPTO_SET_KEY_CONVERGED */ + #endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */ 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 da88dca3be..3e87fe0a11 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -27,11 +27,14 @@ #ifdef WLAN_CRYPTO_SUPPORT_FILS #include "wlan_crypto_fils_def.h" #endif +#include #define WLAN_CRYPTO_TID_SIZE (17) +#define WLAN_CRYPTO_RSC_SIZE (16) #define WLAN_CRYPTO_KEYBUF_SIZE (32) #define WLAN_CRYPTO_MICBUF_SIZE (16) #define WLAN_CRYPTO_MIC_LEN (8) +#define WLAN_CRYPTO_IV_SIZE (16) #define WLAN_CRYPTO_MIC256_LEN (16) #define WLAN_CRYPTO_TXMIC_OFFSET (0) #define WLAN_CRYPTO_RXMIC_OFFSET (WLAN_CRYPTO_TXMIC_OFFSET + \ @@ -53,6 +56,14 @@ /* 128 bit wep key len */ #define WLAN_CRYPTO_KEY_WEP128_LEN (16) +#define WLAN_CRYPTO_KEY_TKIP_LEN (32) +#define WLAN_CRYPTO_KEY_CCMP_LEN (16) +#define WLAN_CRYPTO_KEY_CCMP_256_LEN (32) +#define WLAN_CRYPTO_KEY_GCMP_LEN (16) +#define WLAN_CRYPTO_KEY_GCMP_256_LEN (32) +#define WLAN_CRYPTO_KEY_WAPI_LEN (32) +#define WLAN_CRYPTO_KEY_GMAC_LEN (16) +#define WLAN_CRYPTO_KEY_GMAC_256_LEN (32) #define WLAN_CRYPTO_WPI_SMS4_IVLEN (16) #define WLAN_CRYPTO_WPI_SMS4_KIDLEN (1) #define WLAN_CRYPTO_WPI_SMS4_PADLEN (1) @@ -113,6 +124,7 @@ typedef enum wlan_crypto_cipher_type { WLAN_CRYPTO_CIPHER_WEP_104 = 16, WLAN_CRYPTO_CIPHER_NONE = 17, WLAN_CRYPTO_CIPHER_MAX = WLAN_CRYPTO_CIPHER_NONE, + WLAN_CRYPTO_CIPHER_INVALID, } wlan_crypto_cipher_type; /* Auth types */ @@ -188,6 +200,11 @@ typedef enum wlan_crypto_key_mgmt { WLAN_CRYPTO_KEY_MGMT_MAX = WLAN_CRYPTO_KEY_MGMT_DPP, } wlan_crypto_key_mgmt; +enum wlan_crypto_key_type { + WLAN_CRYPTO_KEY_TYPE_UNICAST, + WLAN_CRYPTO_KEY_TYPE_GROUP, +}; + /** * struct wlan_crypto_params - holds crypto params * @authmodeset: authentication mode @@ -226,6 +243,8 @@ typedef enum wlan_crypto_param_type { * @valid: is key valid or not * @flags: key flags * @keyix: key id + * @cipher_type: cipher type being used for this key + * @mac_addr: MAC address of the peer * @cipher_table: table which stores cipher related info * @private: private pointer to save cipher context * @keylock: spin lock @@ -245,6 +264,8 @@ struct wlan_crypto_key { bool valid; uint16_t flags; uint16_t keyix; + enum wlan_crypto_cipher_type cipher_type; + uint8_t macaddr[QDF_MAC_ADDR_SIZE]; void *cipher_table; void *private; qdf_spinlock_t keylock; @@ -303,23 +324,26 @@ struct wlan_crypto_req_key { * @setkey: function pointer to setkey in hw * @delkey: function pointer to delkey in hw * @defaultkey: function pointer to set default key + * @set_key: converged function pointer to set key in hw */ struct wlan_lmac_if_crypto_tx_ops { - QDF_STATUS(*allockey)(struct wlan_objmgr_vdev *vdev, - struct wlan_crypto_key *key, - uint8_t *macaddr, uint32_t key_type); - QDF_STATUS(*setkey)(struct wlan_objmgr_vdev *vdev, - struct wlan_crypto_key *key, - uint8_t *macaddr, uint32_t key_type); - QDF_STATUS(*delkey)(struct wlan_objmgr_vdev *vdev, - struct wlan_crypto_key *key, - uint8_t *macaddr, uint32_t key_type); - QDF_STATUS(*defaultkey)(struct wlan_objmgr_vdev *vdev, - uint8_t keyix, uint8_t *macaddr); + QDF_STATUS (*allockey)(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *key, + uint8_t *macaddr, uint32_t key_type); + QDF_STATUS (*setkey)(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *key, + uint8_t *macaddr, uint32_t key_type); + QDF_STATUS (*delkey)(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *key, + uint8_t *macaddr, uint32_t key_type); + QDF_STATUS (*defaultkey)(struct wlan_objmgr_vdev *vdev, + uint8_t keyix, uint8_t *macaddr); + QDF_STATUS (*set_key)(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *key, + enum wlan_crypto_key_type key_type); }; - /** * struct wlan_lmac_if_crypto_rx_ops - structure of crypto rx function * pointers 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 e4faff5036..d25e8ff460 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -169,6 +169,8 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val) (psoc->soc_cb.tx_ops.crypto_tx_ops.delkey) #define WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc) \ (psoc->soc_cb.tx_ops.crypto_tx_ops.defaultkey) +#define WLAN_CRYPTO_TX_OPS_SET_KEY(psoc) \ + ((psoc)->soc_cb.tx_ops.crypto_tx_ops.set_key) /* unalligned little endian access */ #ifndef LE_READ_2 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 598d69da62..4d4115eebf 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -35,10 +35,8 @@ #include "wlan_crypto_def_i.h" #include "wlan_crypto_param_handling_i.h" #include "wlan_crypto_obj_mgr_i.h" - #include - const struct wlan_crypto_cipher *wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX]; #define WPA_ADD_CIPHER_TO_SUITE(frm, cipher) \ @@ -954,6 +952,32 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } +#ifdef CRYPTO_SET_KEY_CONVERGED +static QDF_STATUS wlan_crypto_set_default_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_idx, uint8_t *macaddr) +{ + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS wlan_crypto_set_default_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_idx, uint8_t *macaddr) +{ + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + crypto_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + if (WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)) { + WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)(vdev, key_idx, + macaddr); + } + + return QDF_STATUS_SUCCESS; +} +#endif + /** * wlan_crypto_default_key - called by ucfg to set default tx key * @vdev: vdev @@ -1035,10 +1059,9 @@ QDF_STATUS wlan_crypto_default_key(struct wlan_objmgr_vdev *vdev, if (!key->valid) return QDF_STATUS_E_INVAL; - if (WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)) { - WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)(vdev, key_idx, - macaddr); - } + if (wlan_crypto_set_default_key(vdev, key_idx, macaddr) != + QDF_STATUS_SUCCESS) + return QDF_STATUS_E_INVAL; crypto_priv->def_tx_keyid = key_idx; return QDF_STATUS_SUCCESS; @@ -3682,3 +3705,146 @@ QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev, return send_fail ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS; } + +int8_t wlan_crypto_get_default_key_idx(struct wlan_objmgr_vdev *vdev, bool igtk) +{ + struct wlan_crypto_comp_priv *crypto_priv; + + crypto_priv = wlan_get_vdev_crypto_obj(vdev); + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return QDF_STATUS_E_FAILURE; + } + + if (igtk) + return crypto_priv->def_igtk_tx_keyid; + else + return crypto_priv->def_tx_keyid; +} + +enum wlan_crypto_cipher_type +wlan_crypto_get_cipher(struct wlan_objmgr_vdev *vdev, + bool pairwise, uint8_t key_index) +{ + struct wlan_crypto_key *crypto_key; + + crypto_key = wlan_crypto_get_key(vdev, key_index); + + if (crypto_key) + return crypto_key->cipher_type; + else + return WLAN_CRYPTO_CIPHER_INVALID; +} + +#ifdef CRYPTO_SET_KEY_CONVERGED +QDF_STATUS wlan_crypto_validate_key_params(enum wlan_crypto_cipher_type cipher, + uint8_t key_index, uint8_t key_len, + uint8_t seq_len) +{ + if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) { + crypto_err("Invalid Key index %d", key_index); + return QDF_STATUS_E_INVAL; + } + if (cipher == WLAN_CRYPTO_CIPHER_INVALID) { + crypto_err("Invalid Cipher %d", cipher); + return QDF_STATUS_E_INVAL; + } + if ((!(cipher == WLAN_CRYPTO_CIPHER_AES_CMAC || + cipher == WLAN_CRYPTO_CIPHER_AES_CMAC_256 || + cipher == WLAN_CRYPTO_CIPHER_AES_GMAC || + cipher == WLAN_CRYPTO_CIPHER_AES_GMAC_256)) && + (key_index >= WLAN_CRYPTO_MAXKEYIDX)) { + crypto_err("Invalid key index %d for cipher %d", + key_index, cipher); + return QDF_STATUS_E_INVAL; + } + if (key_len > (WLAN_CRYPTO_KEYBUF_SIZE + WLAN_CRYPTO_MICBUF_SIZE)) { + crypto_err("Invalid key length %d", key_len); + return QDF_STATUS_E_INVAL; + } + + if (seq_len > WLAN_CRYPTO_RSC_SIZE) { + crypto_err("Invalid seq length %d", seq_len); + return QDF_STATUS_E_INVAL; + } + + crypto_debug("key: idx:%d, len:%d, seq len:%d", + key_index, key_len, seq_len); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index, + struct wlan_crypto_key *crypto_key) +{ + struct wlan_crypto_comp_priv *crypto_priv; + + crypto_priv = wlan_get_vdev_crypto_obj(vdev); + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return QDF_STATUS_E_FAILURE; + } + if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) { + crypto_err("Invalid Key index %d", key_index); + return QDF_STATUS_E_FAILURE; + } + if (key_index < WLAN_CRYPTO_MAXKEYIDX) + crypto_priv->key[key_index] = crypto_key; + else + crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX] = + crypto_key; + + return QDF_STATUS_SUCCESS; +} + +struct wlan_crypto_key *wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev, + uint8_t key_index) +{ + struct wlan_crypto_comp_priv *crypto_priv; + + crypto_priv = wlan_get_vdev_crypto_obj(vdev); + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return NULL; + } + if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) { + crypto_err("Invalid Key index %d", key_index); + return NULL; + } + if (key_index < WLAN_CRYPTO_MAXKEYIDX) + return crypto_priv->key[key_index]; + + return crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX]; +} + +QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *req, + bool pairwise) +{ + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_vdev_get_psoc(vdev); + if (psoc && WLAN_CRYPTO_TX_OPS_SET_KEY(psoc)) + WLAN_CRYPTO_TX_OPS_SET_KEY(psoc)(vdev, req, pairwise); + else + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +void wlan_crypto_update_set_key_peer(struct wlan_objmgr_vdev *vdev, + bool pairwise, uint8_t key_index, + struct qdf_mac_addr *peer_mac) +{ + struct wlan_crypto_key *crypto_key; + + crypto_key = wlan_crypto_get_key(vdev, key_index); + if (!crypto_key) { + crypto_err("crypto_key not present for key_idx %d", key_index); + return; + } + + qdf_mem_copy(crypto_key->macaddr, peer_mac, QDF_MAC_ADDR_SIZE); +} +#endif diff --git a/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c b/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c index 435a7a9852..33d24db046 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_param_handling.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -40,6 +40,8 @@ cipher2cap(int cipher) { switch (cipher) { case WLAN_CRYPTO_CIPHER_WEP: return WLAN_CRYPTO_CAP_WEP; + case WLAN_CRYPTO_CIPHER_WEP_40: return WLAN_CRYPTO_CAP_WEP; + case WLAN_CRYPTO_CIPHER_WEP_104: return WLAN_CRYPTO_CAP_WEP; case WLAN_CRYPTO_CIPHER_AES_OCB: return WLAN_CRYPTO_CAP_AES; case WLAN_CRYPTO_CIPHER_AES_CCM: return WLAN_CRYPTO_CAP_AES; case WLAN_CRYPTO_CIPHER_AES_CCM_256: return WLAN_CRYPTO_CAP_AES; diff --git a/umac/cmn_services/crypto/src/wlan_crypto_ucfg_api.c b/umac/cmn_services/crypto/src/wlan_crypto_ucfg_api.c new file mode 100644 index 0000000000..211203aff4 --- /dev/null +++ b/umac/cmn_services/crypto/src/wlan_crypto_ucfg_api.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains crypto north bound interface definitions + */ + +#include +#include +#include +#include +QDF_STATUS ucfg_crypto_set_key_req(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_key *req, bool pairwise) +{ + /* + * It is the job of dispatcher to decide whether the + * request has to be sent to scheduler or should be + * sent as a offload request or process directly. + * + * Current requirement is to process set key request + * as run to completion without posting any messages. + * Hence the request handler is directly called from + * here. + */ + return wlan_crypto_set_key_req(vdev, req, pairwise); +} + diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 173cc171e4..19e931072a 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1682,4 +1682,24 @@ QDF_STATUS wmi_unified_send_obss_color_collision_cfg_cmd(void *wmi_hdl, QDF_STATUS wmi_unified_extract_obss_color_collision_info(void *wmi_hdl, uint8_t *data, struct wmi_obss_color_collision_info *info); +#ifdef CRYPTO_SET_KEY_CONVERGED +/** + * wlan_crypto_cipher_to_wmi_cipher() - Convert crypto cipher to WMI cipher + * @crypto_cipher: cipher type in crypto format + * + * Return: cipher type in WMI cipher type + */ +uint8_t wlan_crypto_cipher_to_wmi_cipher( + enum wlan_crypto_cipher_type crypto_cipher); + +/** + * wlan_crypto_cipher_to_cdp_sec_type() - Convert crypto cipher to CDP type + * @crypto_cipher: cipher type in crypto format + * + * Return: security type in cdp_sec_type data format type + */ +enum cdp_sec_type wlan_crypto_cipher_to_cdp_sec_type( + enum wlan_crypto_cipher_type crypto_cipher); + +#endif #endif /* _WMI_UNIFIED_API_H_ */ diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 8654da595f..b61e92fc25 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1747,6 +1747,8 @@ struct wmi_probe_resp_params { * @key_rxmic_len: rx mic length * @key_tsc_counter: key tx sc counter * @key_rsc_counter: key rx sc counter + * @key_rsc_ctr: key rx sc counter (stack variable, unnecessary heap alloc for + * key_rsc_counter should be cleaned up eventually) * @rx_iv: receive IV, applicable only in case of WAPI * @tx_iv: transmit IV, applicable only in case of WAPI * @key_data: key data @@ -1762,6 +1764,7 @@ struct set_key_params { uint32_t key_rxmic_len; uint64_t key_tsc_counter; uint64_t *key_rsc_counter; + uint64_t key_rsc_ctr; #if defined(ATH_SUPPORT_WAPI) || defined(FEATURE_WLAN_WAPI) uint8_t rx_iv[16]; uint8_t tx_iv[16]; diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 6b750d8410..fb6fe11c7d 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -19,6 +19,7 @@ #include "wmi_unified_priv.h" #include "wmi_unified_param.h" #include "qdf_module.h" +#include "cdp_txrx_cmn_struct.h" static const wmi_host_channel_width mode_to_width[WMI_HOST_MODE_MAX] = { [WMI_HOST_MODE_11A] = WMI_HOST_CHAN_WIDTH_20, @@ -4466,6 +4467,63 @@ wmi_unified_send_roam_scan_stats_cmd(void *wmi_hdl, return QDF_STATUS_E_FAILURE; } +#ifdef CRYPTO_SET_KEY_CONVERGED +uint8_t wlan_crypto_cipher_to_wmi_cipher( + enum wlan_crypto_cipher_type crypto_cipher) +{ + switch (crypto_cipher) { + case WLAN_CRYPTO_CIPHER_NONE: + return WMI_CIPHER_NONE; + case WLAN_CRYPTO_CIPHER_WEP: + return WMI_CIPHER_WEP; + case WLAN_CRYPTO_CIPHER_TKIP: + return WMI_CIPHER_TKIP; + case WLAN_CRYPTO_CIPHER_WAPI_SMS4: + case WLAN_CRYPTO_CIPHER_WAPI_GCM4: + return WMI_CIPHER_WAPI; + case WLAN_CRYPTO_CIPHER_AES_CCM: + case WLAN_CRYPTO_CIPHER_AES_CCM_256: + return WMI_CIPHER_AES_CCM; + case WLAN_CRYPTO_CIPHER_AES_CMAC: + return WMI_CIPHER_AES_CMAC; + case WLAN_CRYPTO_CIPHER_AES_GMAC: + case WLAN_CRYPTO_CIPHER_AES_GMAC_256: + return WMI_CIPHER_AES_GMAC; + case WLAN_CRYPTO_CIPHER_AES_GCM: + case WLAN_CRYPTO_CIPHER_AES_GCM_256: + return WMI_CIPHER_AES_GCM; + default: + return 0; + } +} + +enum cdp_sec_type wlan_crypto_cipher_to_cdp_sec_type( + enum wlan_crypto_cipher_type crypto_cipher) +{ + switch (crypto_cipher) { + case WLAN_CRYPTO_CIPHER_NONE: + return cdp_sec_type_none; + case WLAN_CRYPTO_CIPHER_WEP: + return cdp_sec_type_wep104; + case WLAN_CRYPTO_CIPHER_TKIP: + return cdp_sec_type_tkip; + case WLAN_CRYPTO_CIPHER_WAPI_SMS4: + case WLAN_CRYPTO_CIPHER_WAPI_GCM4: + return cdp_sec_type_wapi; + case WLAN_CRYPTO_CIPHER_AES_CCM: + return cdp_sec_type_aes_ccmp; + case WLAN_CRYPTO_CIPHER_AES_CCM_256: + return cdp_sec_type_aes_ccmp_256; + case WLAN_CRYPTO_CIPHER_AES_GCM: + return cdp_sec_type_aes_gcmp; + case WLAN_CRYPTO_CIPHER_AES_GCM_256: + return cdp_sec_type_aes_gcmp_256; + default: + return cdp_sec_type_none; + } +} +#endif /* CRYPTO_SET_KEY_CONVERGED */ + QDF_STATUS wmi_extract_roam_scan_stats_res_evt(wmi_unified_t wmi, void *evt_buf, uint32_t *vdev_id, diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index f61c0f19d6..6796e08ce6 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -3996,9 +3996,8 @@ static QDF_STATUS send_setup_install_key_cmd_tlv(wmi_unified_t wmi_handle, key_data = (uint8_t *) (buf_ptr + WMI_TLV_HDR_SIZE); qdf_mem_copy((void *)key_data, (const void *)key_params->key_data, key_params->key_len); - if (key_params->key_rsc_counter) - qdf_mem_copy(&cmd->key_rsc_counter, key_params->key_rsc_counter, - sizeof(wmi_key_seq_counter)); + qdf_mem_copy(&cmd->key_rsc_counter, &key_params->key_rsc_ctr, + sizeof(wmi_key_seq_counter)); cmd->key_len = key_params->key_len; wmi_mtrace(WMI_VDEV_INSTALL_KEY_CMDID, cmd->vdev_id, 0); @@ -4646,7 +4645,6 @@ static QDF_STATUS send_process_ll_stats_clear_cmd_tlv(wmi_unified_t wmi_handle, WMI_LOGD("Clear Stat Mask : %d", cmd->stats_clear_req_mask); /* WMI_LOGD("Peer MAC Addr : %pM", cmd->peer_macaddr); */ - wmi_mtrace(WMI_CLEAR_LINK_STATS_CMDID, cmd->vdev_id, 0); ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_CLEAR_LINK_STATS_CMDID);