From 94e34bb2627207e509cf4e2162ecc0235b55f214 Mon Sep 17 00:00:00 2001 From: "Padma, Santhosh Kumar" Date: Sun, 11 Sep 2016 18:24:59 +0530 Subject: [PATCH] qcacmn: Add changes for DISA certification Add TLV changes to pass DISA parameters received from WMA and pass them to firmware for firmware to encrypt data and send back to driver. Change-Id: Ic6928a93f799c47518fbbad96564062f595287dd CRs-Fixed: 1072545 --- wmi/inc/wmi_unified_api.h | 3 ++ wmi/inc/wmi_unified_param.h | 39 +++++++++++++++++ wmi/inc/wmi_unified_priv.h | 3 ++ wmi/src/wmi_unified_api.c | 20 +++++++++ wmi/src/wmi_unified_tlv.c | 84 +++++++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+) diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index a3d6d6012e..1829092f05 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -502,6 +502,9 @@ QDF_STATUS wmi_unified_probe_rsp_tmpl_send_cmd(void *wmi_hdl, QDF_STATUS wmi_unified_setup_install_key_cmd(void *wmi_hdl, struct set_key_params *key_params); +QDF_STATUS wmi_unified_encrypt_decrypt_send_cmd(void *wmi_hdl, + struct encrypt_decrypt_req_params *params); + QDF_STATUS wmi_unified_p2p_go_set_beacon_ie_cmd(void *wmi_hdl, A_UINT32 vdev_id, uint8_t *p2p_ie); diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 5f106114b4..f2ab5ace19 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -32,6 +32,13 @@ #ifndef _WMI_UNIFIED_PARAM_H_ #define _WMI_UNIFIED_PARAM_H_ + +#define MAC_MAX_KEY_LENGTH 32 +#define MAC_PN_LENGTH 8 +#define MAX_MAC_HEADER_LEN 32 +#define MIN_MAC_HEADER_LEN 24 +#define QOS_CONTROL_LEN 2 + #define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ #define WMI_MAC_MAX_SSID_LENGTH 32 #define WMI_SCAN_MAX_NUM_SSID 0x0A @@ -6567,5 +6574,37 @@ enum wmi_userspace_log_level { WMI_LOG_LEVEL_ACTIVE, }; +/** + * struct encrypt_decrypt_req_params - encrypt/decrypt params + * @vdev_id: virtual device id + * @key_flag: This indicates firmware to encrypt/decrypt payload + * see ENCRYPT_DECRYPT_FLAG + * @key_idx: Index used in storing key + * @key_cipher: cipher used for encryption/decryption + * Eg: see WMI_CIPHER_AES_CCM for CCMP + * @key_len: length of key data + * @key_txmic_len: length of Tx MIC + * @key_rxmic_len: length of Rx MIC + * @key_data: Key + * @pn: packet number + * @mac_header: MAC header + * @data_len: length of data + * @data: pointer to payload + */ +struct encrypt_decrypt_req_params { + uint32_t vdev_id; + uint8_t key_flag; + uint32_t key_idx; + uint32_t key_cipher; + uint32_t key_len; + uint32_t key_txmic_len; + uint32_t key_rxmic_len; + uint8_t key_data[MAC_MAX_KEY_LENGTH]; + uint8_t pn[MAC_PN_LENGTH]; + uint8_t mac_header[MAX_MAC_HEADER_LEN]; + uint32_t data_len; + uint8_t *data; +}; + #endif /* _WMI_UNIFIED_PARAM_H_ */ diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 2a4c9e90c0..c7efe6bafe 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1129,6 +1129,9 @@ QDF_STATUS (*send_adapt_dwelltime_params_cmd)(wmi_unified_t wmi_handle, QDF_STATUS (*send_fw_test_cmd)(wmi_unified_t wmi_handle, struct set_fwtest_params *wmi_fwtest); + +QDF_STATUS (*send_encrypt_decrypt_send_cmd)(wmi_unified_t wmi_handle, + struct encrypt_decrypt_req_params *params); }; struct target_abi_version { diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 1516e0d9d2..3d9e1854b2 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -6122,3 +6122,23 @@ QDF_STATUS wmi_unified_send_power_dbg_cmd(void *wmi_hdl, return QDF_STATUS_E_FAILURE; } + +/** + * wmi_unified_encrypt_decrypt_send_cmd() - send encryptdecrypt cmd to fw + * @wmi_hdl: wmi handle + * @params: encrypt/decrypt params + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_encrypt_decrypt_send_cmd(void *wmi_hdl, + struct encrypt_decrypt_req_params *params) +{ + wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl; + + if (wmi_handle->ops->send_encrypt_decrypt_send_cmd) + return wmi_handle->ops->send_encrypt_decrypt_send_cmd( + wmi_handle, + params); + + return QDF_STATUS_E_FAILURE; +} diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index ee33ae828c..18bb8e70bc 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -4028,6 +4028,88 @@ QDF_STATUS send_setup_install_key_cmd_tlv(wmi_unified_t wmi_handle, return status; } +/** + * send_encrypt_decrypt_send_cmd() - send encrypt/decrypt cmd to fw + * @wmi_handle: wmi handle + * @params: encrypt/decrypt params + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS send_encrypt_decrypt_send_cmd_tlv(wmi_unified_t wmi_handle, + struct encrypt_decrypt_req_params *encrypt_decrypt_params) +{ + wmi_vdev_encrypt_decrypt_data_req_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint8_t *buf_ptr; + QDF_STATUS ret; + uint32_t len; + + WMI_LOGD(FL("Send encrypt decrypt cmd")); + + len = sizeof(*cmd) + + roundup(encrypt_decrypt_params->data_len, sizeof(A_UINT32)) + + WMI_TLV_HDR_SIZE; + wmi_buf = wmi_buf_alloc(wmi_handle, len); + if (!wmi_buf) { + WMI_LOGP("%s: failed to allocate memory for encrypt/decrypt msg", + __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = wmi_buf_data(wmi_buf); + cmd = (wmi_vdev_encrypt_decrypt_data_req_cmd_fixed_param *)buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_encrypt_decrypt_data_req_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_encrypt_decrypt_data_req_cmd_fixed_param)); + + cmd->vdev_id = encrypt_decrypt_params->vdev_id; + cmd->key_flag = encrypt_decrypt_params->key_flag; + cmd->key_idx = encrypt_decrypt_params->key_idx; + cmd->key_cipher = encrypt_decrypt_params->key_cipher; + cmd->key_len = encrypt_decrypt_params->key_len; + cmd->key_txmic_len = encrypt_decrypt_params->key_txmic_len; + cmd->key_rxmic_len = encrypt_decrypt_params->key_rxmic_len; + + qdf_mem_copy(cmd->key_data, encrypt_decrypt_params->key_data, + encrypt_decrypt_params->key_len); + + qdf_mem_copy(cmd->mac_hdr, encrypt_decrypt_params->mac_header, + MAX_MAC_HEADER_LEN); + + cmd->data_len = encrypt_decrypt_params->data_len; + + if (cmd->data_len) { + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, + roundup(encrypt_decrypt_params->data_len, + sizeof(A_UINT32))); + buf_ptr += WMI_TLV_HDR_SIZE; + qdf_mem_copy(buf_ptr, encrypt_decrypt_params->data, + encrypt_decrypt_params->data_len); + } + + /* This conversion is to facilitate data to FW in little endian */ + cmd->pn[5] = encrypt_decrypt_params->pn[0]; + cmd->pn[4] = encrypt_decrypt_params->pn[1]; + cmd->pn[3] = encrypt_decrypt_params->pn[2]; + cmd->pn[2] = encrypt_decrypt_params->pn[3]; + cmd->pn[1] = encrypt_decrypt_params->pn[4]; + cmd->pn[0] = encrypt_decrypt_params->pn[5]; + + ret = wmi_unified_cmd_send(wmi_handle, + wmi_buf, len, + WMI_VDEV_ENCRYPT_DECRYPT_DATA_REQ_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) { + WMI_LOGE("Failed to send ENCRYPT DECRYPT cmd: %d", ret); + wmi_buf_free(wmi_buf); + } + + return ret; +} + + /** * send_p2p_go_set_beacon_ie_cmd_tlv() - set beacon IE for p2p go @@ -12541,6 +12623,8 @@ struct wmi_ops tlv_ops = { .extract_chan_info_event = extract_chan_info_event_tlv, .extract_channel_hopping_event = extract_channel_hopping_event_tlv, .send_fw_test_cmd = send_fw_test_cmd_tlv, + .send_encrypt_decrypt_send_cmd = + send_encrypt_decrypt_send_cmd_tlv, }; #ifndef CONFIG_MCL