mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-15 01:01:56 -04:00
qcacld-3.0: Add HDD FIPS infrastructure
As part of the support for the FIPS certification feature add the HDD infrastructure. Change-Id: I76a545c42b10a662db04b5994de100c713a46c59 CRs-Fixed: 2065002
This commit is contained in:
parent
6136fb90e2
commit
6fa1e0113b
4 changed files with 398 additions and 1 deletions
4
Kbuild
4
Kbuild
|
|
@ -431,6 +431,10 @@ ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y)
|
|||
HDD_OBJS+= $(HDD_SRC_DIR)/wlan_hdd_ocb.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_WLAN_FEATURE_FIPS), y)
|
||||
HDD_OBJS+= $(HDD_SRC_DIR)/wlan_hdd_fips.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_WLAN_FEATURE_LPSS),y)
|
||||
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_lpass.o
|
||||
endif
|
||||
|
|
|
|||
291
core/hdd/src/wlan_hdd_fips.c
Normal file
291
core/hdd/src/wlan_hdd_fips.c
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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: wlan_hdd_fips.c
|
||||
*
|
||||
* WLAN Host Device Driver FIPS Certification Feature
|
||||
*/
|
||||
|
||||
#include "wlan_hdd_main.h"
|
||||
#include "wlan_hdd_fips.h"
|
||||
#include "wlan_hdd_request_manager.h"
|
||||
#include "qdf_mem.h"
|
||||
#include "sme_api.h"
|
||||
|
||||
|
||||
#define WLAN_WAIT_TIME_FIPS 5000
|
||||
|
||||
|
||||
/**
|
||||
* hdd_fips_context - hdd fips context
|
||||
* @status: status of response. 0: no error, -ENOMEM: unable to allocate
|
||||
* memory for the response payload
|
||||
* @request: fips request
|
||||
* @response: fips response
|
||||
*/
|
||||
struct hdd_fips_context {
|
||||
int status;
|
||||
struct fips_params request;
|
||||
struct wmi_host_fips_event_param response;
|
||||
};
|
||||
|
||||
/**
|
||||
* hdd_fips_event_dup () - duplicate a fips event
|
||||
* @dest: destination event
|
||||
* @src: source event
|
||||
*
|
||||
* Make a "deep" duplicate of a FIPS event
|
||||
*
|
||||
* Return: 0 if the event was duplicated, otherwise an error
|
||||
*/
|
||||
static int hdd_fips_event_dup(struct wmi_host_fips_event_param *dest,
|
||||
const struct wmi_host_fips_event_param *src)
|
||||
{
|
||||
*dest = *src;
|
||||
if (dest->data_len) {
|
||||
dest->data = qdf_mem_malloc(dest->data_len);
|
||||
if (!dest->data) {
|
||||
hdd_err("memory allocation failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
qdf_mem_copy(dest->data, src->data, src->data_len);
|
||||
} else {
|
||||
/* make sure we don't have a rogue pointer */
|
||||
dest->data = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_fips_cb () - fips response message handler
|
||||
* @cookie: hdd request cookie
|
||||
* @response: fips response parameters
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
static void hdd_fips_cb(void *cookie,
|
||||
struct wmi_host_fips_event_param *response)
|
||||
{
|
||||
struct hdd_request *request;
|
||||
struct hdd_fips_context *context;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (!response) {
|
||||
hdd_err("response is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
request = hdd_request_get(cookie);
|
||||
if (!request) {
|
||||
hdd_debug("Obsolete request");
|
||||
return;
|
||||
}
|
||||
|
||||
hdd_debug("pdev_id %u, status %u, data_len %u",
|
||||
response->pdev_id,
|
||||
response->error_status,
|
||||
response->data_len);
|
||||
qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
|
||||
response->data, response->data_len);
|
||||
|
||||
context = hdd_request_priv(request);
|
||||
if (response->error_status) {
|
||||
context->status = -ETIMEDOUT;
|
||||
} else {
|
||||
context->status = hdd_fips_event_dup(&context->response,
|
||||
response);
|
||||
}
|
||||
|
||||
hdd_request_complete(request);
|
||||
hdd_request_put(request);
|
||||
EXIT();
|
||||
}
|
||||
|
||||
static void hdd_fips_context_dealloc(void *priv)
|
||||
{
|
||||
struct hdd_fips_context *context = priv;
|
||||
|
||||
qdf_mem_free(context->response.data);
|
||||
}
|
||||
|
||||
|
||||
static int hdd_fips_validate_request(struct iw_fips_test_request *user_request,
|
||||
uint32_t request_len)
|
||||
{
|
||||
uint32_t expected_data_len;
|
||||
|
||||
if (request_len < sizeof(*user_request)) {
|
||||
hdd_debug("Request len %u is too small", request_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((user_request->key_len != FIPS_KEY_LENGTH_128) &&
|
||||
(user_request->key_len != FIPS_KEY_LENGTH_256)) {
|
||||
hdd_debug("Invalid key len %u", user_request->key_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
expected_data_len = request_len - sizeof(*user_request);
|
||||
if (expected_data_len != user_request->data_len) {
|
||||
hdd_debug("Unexpected data_len %u for request_len %u",
|
||||
user_request->data_len, request_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((user_request->mode != FIPS_ENGINE_AES_CTR) &&
|
||||
(user_request->mode != FIPS_ENGINE_AES_MIC)) {
|
||||
hdd_debug("Invalid mode %u", user_request->mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((user_request->operation != FIPS_ENCRYPT_CMD) &&
|
||||
(user_request->operation != FIPS_DECRYPT_CMD)) {
|
||||
hdd_debug("Invalid operation %u", user_request->operation);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __hdd_fips_test(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
hdd_adapter_t *adapter;
|
||||
hdd_context_t *hdd_ctx;
|
||||
struct iw_fips_test_request *user_request;
|
||||
struct iw_fips_test_response *user_response;
|
||||
uint32_t request_len;
|
||||
int ret;
|
||||
QDF_STATUS qdf_status;
|
||||
void *cookie;
|
||||
struct hdd_request *request;
|
||||
struct hdd_fips_context *context;
|
||||
struct fips_params *fips_request;
|
||||
struct wmi_host_fips_event_param *fips_response;
|
||||
static const struct hdd_request_params params = {
|
||||
.priv_size = sizeof(*context),
|
||||
.timeout_ms = WLAN_WAIT_TIME_FIPS,
|
||||
.dealloc = hdd_fips_context_dealloc,
|
||||
};
|
||||
|
||||
ENTER_DEV(dev);
|
||||
|
||||
adapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
||||
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
||||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
user_request = (struct iw_fips_test_request *)extra;
|
||||
request_len = wrqu->data.length;
|
||||
ret = hdd_fips_validate_request(user_request, request_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
request = hdd_request_alloc(¶ms);
|
||||
if (!request) {
|
||||
hdd_err("Request allocation failure");
|
||||
return -ENOMEM;
|
||||
}
|
||||
context = hdd_request_priv(request);
|
||||
fips_request = &context->request;
|
||||
fips_request->key = &user_request->key[0];
|
||||
fips_request->key_len = user_request->key_len;
|
||||
fips_request->data = &user_request->data[0];
|
||||
fips_request->data_len = user_request->data_len;
|
||||
fips_request->mode = user_request->mode;
|
||||
fips_request->op = user_request->operation;
|
||||
fips_request->pdev_id = WMI_PDEV_ID_1ST;
|
||||
|
||||
cookie = hdd_request_cookie(request);
|
||||
qdf_status = sme_fips_request(hdd_ctx->hHal, &context->request,
|
||||
hdd_fips_cb, cookie);
|
||||
|
||||
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
|
||||
hdd_err("Unable to post fips message");
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = hdd_request_wait_for_response(request);
|
||||
if (ret) {
|
||||
hdd_err("Target response timed out");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = context->status;
|
||||
if (ret) {
|
||||
hdd_err("Target response processing failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
fips_response = &context->response;
|
||||
if (fips_response->data_len != fips_request->data_len) {
|
||||
hdd_err("Data length mismatch, got %u, expected %u",
|
||||
fips_response->data_len, fips_request->data_len);
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
user_response = (struct iw_fips_test_response *)extra;
|
||||
user_response->status = context->status;
|
||||
if (user_response->status) {
|
||||
user_response->data_len = 0;
|
||||
} else {
|
||||
user_response->data_len = fips_response->data_len;
|
||||
qdf_mem_copy(user_response->data, fips_response->data,
|
||||
fips_response->data_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* By default wireless extensions private ioctls have either
|
||||
* SET semantics (even numbered ioctls) or GET semantics (odd
|
||||
* numbered ioctls). This is an even numbered ioctl so the SET
|
||||
* semantics apply. This means the core kernel ioctl code took
|
||||
* care of copying the request parameters from userspace to
|
||||
* kernel space. However this ioctl also needs to return the
|
||||
* response. Since the core kernel ioctl code doesn't support
|
||||
* SET ioctls returning anything other than status, we have to
|
||||
* explicitly copy the result to userspace.
|
||||
*/
|
||||
wrqu->data.length = sizeof(*user_response) + user_response->data_len;
|
||||
if (copy_to_user(wrqu->data.pointer, user_response, wrqu->data.length))
|
||||
ret = -EFAULT;
|
||||
|
||||
cleanup:
|
||||
hdd_request_put(request);
|
||||
|
||||
EXIT();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hdd_fips_test(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
int ret;
|
||||
|
||||
cds_ssr_protect(__func__);
|
||||
ret = __hdd_fips_test(dev, info, wrqu, extra);
|
||||
cds_ssr_unprotect(__func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
73
core/hdd/src/wlan_hdd_fips.h
Normal file
73
core/hdd/src/wlan_hdd_fips.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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: wlan_hdd_fips.h
|
||||
*
|
||||
* WLAN Host Device Driver FIPS Certification Feature
|
||||
*/
|
||||
|
||||
#ifndef __WLAN_HDD_FIPS_H__
|
||||
#define __WLAN_HDD_FIPS_H__
|
||||
|
||||
struct net_device;
|
||||
struct iw_request_info;
|
||||
union iwreq_data;
|
||||
struct hdd_adapter_s;
|
||||
void fips_test(struct hdd_adapter_s *adapter);
|
||||
|
||||
#define FIPS_KEY_LEN 32
|
||||
struct iw_fips_test_request {
|
||||
uint32_t operation;
|
||||
uint32_t mode;
|
||||
uint32_t key_len;
|
||||
uint8_t key[FIPS_KEY_LEN];
|
||||
uint32_t data_len;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
struct iw_fips_test_response {
|
||||
uint32_t status;
|
||||
uint32_t data_len;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* hdd_fips_test() - Perform FIPS test
|
||||
* @dev: netdev upon which the FIPS test ioctl was received
|
||||
* @info: ioctl request information
|
||||
* @wrqu: ioctl request data structure
|
||||
* @extra: extra payload for wireless extensions ioctl
|
||||
*
|
||||
* This API implements the FIPS test interface. Upon entry the @extra
|
||||
* buffer will contain a FIPS test vector formated as a &struct
|
||||
* iw_fips_test_request. This vector will be sent to firmware where it
|
||||
* will be run through the appropriate hardware. The result of the
|
||||
* operation will be sent back to userspace via @extra encoded as a
|
||||
* &struct iw_fips_test_response.
|
||||
*
|
||||
* Return: 0 if the test vector was processed, otherwise a negative
|
||||
* errno.
|
||||
*/
|
||||
|
||||
int hdd_fips_test(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra);
|
||||
|
||||
#endif /* __WLAN_HDD_FIPS_H__ */
|
||||
|
|
@ -82,6 +82,7 @@
|
|||
#include "sme_power_save_api.h"
|
||||
#include "wlan_policy_mgr_api.h"
|
||||
#include "wlan_hdd_conc_ut.h"
|
||||
#include "wlan_hdd_fips.h"
|
||||
#include "wlan_hdd_tsf.h"
|
||||
#include "wlan_hdd_ocb.h"
|
||||
#include "wlan_hdd_napi.h"
|
||||
|
|
@ -2534,6 +2535,28 @@ static const struct ccp_freq_chan_map freq_chan_map[] = {
|
|||
#define MAX_VAR_ARGS 9
|
||||
#endif
|
||||
|
||||
/*
|
||||
* <ioctl>
|
||||
* fips_test - Perform a FIPS test
|
||||
*
|
||||
* @INPUT: Binary representation of the following packed structure
|
||||
*
|
||||
* @OUTPUT: Binary representation of the following packed structure
|
||||
*
|
||||
* This IOCTL is used to perform FIPS certification testing
|
||||
*
|
||||
* @E.g: iwpriv wlan0 fips_test <test vector>
|
||||
*
|
||||
* iwpriv wlan0 fips_test <tbd>
|
||||
*
|
||||
* Supported Feature: FIPS
|
||||
*
|
||||
* Usage: Internal
|
||||
*
|
||||
* </ioctl>
|
||||
*/
|
||||
#define WLAN_PRIV_FIPS_TEST (SIOCIWFIRSTPRIV + 8)
|
||||
|
||||
/* Private ioctls (with no sub-ioctls) */
|
||||
/* note that they must be odd so that they have "get" semantics */
|
||||
/*
|
||||
|
|
@ -2627,7 +2650,6 @@ static const struct ccp_freq_chan_map freq_chan_map[] = {
|
|||
*/
|
||||
#define WLAN_PRIV_GET_TSPEC (SIOCIWFIRSTPRIV + 13)
|
||||
|
||||
/* (SIOCIWFIRSTPRIV + 8) is currently unused */
|
||||
/* (SIOCIWFIRSTPRIV + 10) is currently unused */
|
||||
/* (SIOCIWFIRSTPRIV + 12) is currently unused */
|
||||
/* (SIOCIWFIRSTPRIV + 14) is currently unused */
|
||||
|
|
@ -12818,6 +12840,7 @@ static const iw_handler we_private[] = {
|
|||
iw_hdd_set_var_ints_getnone,
|
||||
[WLAN_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] =
|
||||
iw_setnone_get_threeint,
|
||||
[WLAN_PRIV_FIPS_TEST - SIOCIWFIRSTPRIV] = hdd_fips_test,
|
||||
[WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec,
|
||||
[WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec,
|
||||
[WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec,
|
||||
|
|
@ -13841,6 +13864,12 @@ static const struct iw_priv_args we_private_args[] = {
|
|||
0,
|
||||
"gpio_control"},
|
||||
#endif
|
||||
/* handlers for main ioctl */
|
||||
{WLAN_PRIV_FIPS_TEST,
|
||||
IW_PRIV_TYPE_BYTE | WE_MAX_STR_LEN,
|
||||
IW_PRIV_TYPE_BYTE | WE_MAX_STR_LEN,
|
||||
"fips_test"},
|
||||
|
||||
/* handlers for main ioctl */
|
||||
{WLAN_PRIV_ADD_TSPEC,
|
||||
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | HDD_WLAN_WMM_PARAM_COUNT,
|
||||
|
|
|
|||
Loading…
Reference in a new issue