Commit 846239f6 authored by Jérôme Pouiller's avatar Jérôme Pouiller Committed by Greg Kroah-Hartman
Browse files

staging: wfx: introduce "secure link"

Chip support encryption of the link between host and chip. This feature
is called "secure link". Driver code on github[1] support it. However,
it relies on mbedtls for cryptographic functions. So, I decided to not
import this feature in current patch. However, in order to keep code
synchronized between github and kernel, I imported all code related to
this feature, even if most of it is just no-op.

[1]: https://github.com/SiliconLabs/wfx-linux-driver/



Signed-off-by: default avatarJérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20190919142527.31797-14-Jerome.Pouiller@silabs.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f95a29d4
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include "wfx.h"
#include "hwio.h"
#include "traces.h"
#include "secure_link.h"
#include "hif_rx.h"
#include "hif_api_cmd.h"

@@ -74,7 +75,18 @@ static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf)
	hif = (struct hif_msg *) skb->data;
	WARN(hif->encrypted & 0x1, "unsupported encryption type");
	if (hif->encrypted == 0x2) {
		BUG(); // Not yet implemented
		if (wfx_sl_decode(wdev, (void *) hif)) {
			dev_kfree_skb(skb);
			// If frame was a confirmation, expect trouble in next
			// exchange. However, it is harmless to fail to decode
			// an indication frame, so try to continue. Anyway,
			// piggyback is probably correct.
			return piggyback;
		}
		le16_to_cpus(hif->len);
		computed_len = round_up(hif->len - sizeof(hif->len), 16)
			       + sizeof(struct hif_sl_msg)
			       + sizeof(struct hif_sl_tag);
	} else {
		le16_to_cpus(hif->len);
		computed_len = round_up(hif->len, 2);
@@ -166,7 +178,22 @@ static void tx_helper(struct wfx_dev *wdev, struct hif_msg *hif)
	hif->seqnum = wdev->hif.tx_seqnum;
	wdev->hif.tx_seqnum = (wdev->hif.tx_seqnum + 1) % (HIF_COUNTER_MAX + 1);

	if (wfx_is_secure_command(wdev, hif->id)) {
		len = round_up(len - sizeof(hif->len), 16) + sizeof(hif->len)
		      + sizeof(struct hif_sl_msg_hdr) + sizeof(struct hif_sl_tag);
		// AES support encryption in-place. However, mac80211 access to
		// 802.11 header after frame was sent (to get MAC addresses).
		// So, keep origin buffer clear.
		data = kmalloc(len, GFP_KERNEL);
		if (!data)
			goto end;
		is_encrypted = true;
		ret = wfx_sl_encode(wdev, hif, data);
		if (ret)
			goto end;
	} else {
		data = hif;
	}
	WARN(len > wdev->hw_caps.size_inp_ch_buf,
	     "%s: request exceed WFx capability: %zu > %d\n", __func__,
	     len, wdev->hw_caps.size_inp_ch_buf);
+17 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 * Copyright (c) 2010, ST-Ericsson
 */
#include <linux/debugfs.h>
#include <linux/crc32.h>

#include "debug.h"
#include "wfx.h"
@@ -53,6 +54,21 @@ const char *get_reg_name(unsigned long id)
	return get_symbol(id, wfx_reg_print_map);
}

static ssize_t wfx_burn_slk_key_write(struct file *file,
				      const char __user *user_buf,
				      size_t count, loff_t *ppos)
{
	struct wfx_dev *wdev = file->private_data;

	dev_info(wdev->dev, "this driver does not support secure link\n");
	return -EINVAL;
}

static const struct file_operations wfx_burn_slk_key_fops = {
	.open = simple_open,
	.write = wfx_burn_slk_key_write,
};

struct dbgfs_hif_msg {
	struct wfx_dev *wdev;
	struct completion complete;
@@ -146,6 +162,7 @@ int wfx_debug_init(struct wfx_dev *wdev)
	struct dentry *d;

	d = debugfs_create_dir("wfx", wdev->hw->wiphy->debugfsdir);
	debugfs_create_file("burn_slk_key", 0200, d, wdev, &wfx_burn_slk_key_fops);
	debugfs_create_file("send_hif_msg", 0600, d, wdev, &wfx_send_hif_msg_fops);

	return 0;
+17 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@

#include "hif_rx.h"
#include "wfx.h"
#include "secure_link.h"
#include "hif_api_cmd.h"

static int hif_generic_confirm(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
@@ -46,6 +47,8 @@ static int hif_generic_confirm(struct wfx_dev *wdev, struct hif_msg *hif, void *
	} else {
		wdev->hif_cmd.buf_send = NULL;
		mutex_unlock(&wdev->hif_cmd.lock);
		if (cmd != HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS)
			mutex_unlock(&wdev->hif_cmd.key_renew_lock);
	}
	return status;
}
@@ -68,11 +71,25 @@ static int hif_startup_indication(struct wfx_dev *wdev, struct hif_msg *hif, voi
	return 0;
}

static int hif_keys_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
{
	struct hif_ind_sl_exchange_pub_keys *body = buf;

	// Compatibility with legacy secure link
	if (body->status == SL_PUB_KEY_EXCHANGE_STATUS_SUCCESS)
		body->status = 0;
	if (body->status)
		dev_warn(wdev->dev, "secure link negociation error\n");
	wfx_sl_check_pubkey(wdev, body->ncp_pub_key, body->ncp_pub_key_mac);
	return 0;
}

static const struct {
	int msg_id;
	int (*handler)(struct wfx_dev *wdev, struct hif_msg *hif, void *buf);
} hif_handlers[] = {
	{ HIF_IND_ID_STARTUP,              hif_startup_indication },
	{ HIF_IND_ID_SL_EXCHANGE_PUB_KEYS, hif_keys_indication },
};

void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb)
+6 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ void wfx_init_hif_cmd(struct wfx_hif_cmd *hif_cmd)
	init_completion(&hif_cmd->ready);
	init_completion(&hif_cmd->done);
	mutex_init(&hif_cmd->lock);
	mutex_init(&hif_cmd->key_renew_lock);
}

static void wfx_fill_header(struct hif_msg *hif, int if_id, unsigned int cmd, size_t size)
@@ -59,6 +60,9 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, void *reply, siz
	if (wdev->chip_frozen)
		return -ETIMEDOUT;

	if (cmd != HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS)
		mutex_lock(&wdev->hif_cmd.key_renew_lock);

	mutex_lock(&wdev->hif_cmd.lock);
	WARN(wdev->hif_cmd.buf_send, "data locking error");

@@ -107,6 +111,8 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, void *reply, siz
			 "WSM request %s%s%s (%#.2x) on vif %d returned status %d\n",
			 get_hif_name(cmd), mib_sep, mib_name, cmd, vif, ret);

	if (cmd != HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS)
		mutex_unlock(&wdev->hif_cmd.key_renew_lock);
	return ret;
}

+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ struct wfx_scan_params {

struct wfx_hif_cmd {
	struct mutex      lock;
	struct mutex      key_renew_lock;
	struct completion ready;
	struct completion done;
	bool              async;
Loading