Commit f730cc9f authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2017-10-19

Here's the first bluetooth-next pull request targeting the 4.15 kernel
release.

 - Multiple fixes & improvements to the hci_bcm driver
 - DT improvements, e.g. new local-bd-address property
 - Fixes & improvements to ECDH usage. Private key is now generated by
   the crypto subsystem.
 - gcc-4.9 warning fixes

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 164a5e7a fac72b24
The following properties are common to the Bluetooth controllers:
- local-bd-address: array of 6 bytes, specifies the BD address that was
uniquely assigned to the Bluetooth device, formatted with least significant
byte first (little-endian).
...@@ -37,6 +37,11 @@ The following properties are defined to the bluetooth node: ...@@ -37,6 +37,11 @@ The following properties are defined to the bluetooth node:
Definition: must be: Definition: must be:
"qcom,wcnss-bt" "qcom,wcnss-bt"
- local-bd-address:
Usage: optional
Value type: <u8 array>
Definition: see Documentation/devicetree/bindings/net/bluetooth.txt
== WiFi == WiFi
The following properties are defined to the WiFi node: The following properties are defined to the WiFi node:
...@@ -91,6 +96,9 @@ smd { ...@@ -91,6 +96,9 @@ smd {
bt { bt {
compatible = "qcom,wcnss-bt"; compatible = "qcom,wcnss-bt";
/* BD address 00:11:22:33:44:55 */
local-bd-address = [ 55 44 33 22 11 00 ];
}; };
wlan { wlan {
......
...@@ -65,6 +65,7 @@ config BT_HCIBTSDIO ...@@ -65,6 +65,7 @@ config BT_HCIBTSDIO
config BT_HCIUART config BT_HCIUART
tristate "HCI UART driver" tristate "HCI UART driver"
depends on SERIAL_DEV_BUS || !SERIAL_DEV_BUS
depends on TTY depends on TTY
help help
Bluetooth HCI UART driver. Bluetooth HCI UART driver.
...@@ -79,7 +80,6 @@ config BT_HCIUART ...@@ -79,7 +80,6 @@ config BT_HCIUART
config BT_HCIUART_SERDEV config BT_HCIUART_SERDEV
bool bool
depends on SERIAL_DEV_BUS && BT_HCIUART depends on SERIAL_DEV_BUS && BT_HCIUART
depends on SERIAL_DEV_BUS=y || SERIAL_DEV_BUS=BT_HCIUART
default y default y
config BT_HCIUART_H4 config BT_HCIUART_H4
...@@ -169,6 +169,7 @@ config BT_HCIUART_BCM ...@@ -169,6 +169,7 @@ config BT_HCIUART_BCM
bool "Broadcom protocol support" bool "Broadcom protocol support"
depends on BT_HCIUART depends on BT_HCIUART
depends on BT_HCIUART_SERDEV depends on BT_HCIUART_SERDEV
depends on (!ACPI || SERIAL_DEV_CTRL_TTYPORT)
select BT_HCIUART_H4 select BT_HCIUART_H4
select BT_BCM select BT_BCM
help help
......
...@@ -121,7 +121,7 @@ static void bcm203x_complete(struct urb *urb) ...@@ -121,7 +121,7 @@ static void bcm203x_complete(struct urb *urb)
} }
data->state = BCM203X_LOAD_FIRMWARE; data->state = BCM203X_LOAD_FIRMWARE;
/* fall through */
case BCM203X_LOAD_FIRMWARE: case BCM203X_LOAD_FIRMWARE:
if (data->fw_sent == data->fw_size) { if (data->fw_sent == data->fw_size) {
usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP),
......
...@@ -156,9 +156,9 @@ static void bluecard_detach(struct pcmcia_device *p_dev); ...@@ -156,9 +156,9 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
/* ======================== LED handling routines ======================== */ /* ======================== LED handling routines ======================== */
static void bluecard_activity_led_timeout(u_long arg) static void bluecard_activity_led_timeout(struct timer_list *t)
{ {
struct bluecard_info *info = (struct bluecard_info *)arg; struct bluecard_info *info = from_timer(info, t, timer);
unsigned int iobase = info->p_dev->resource[0]->start; unsigned int iobase = info->p_dev->resource[0]->start;
if (test_bit(CARD_ACTIVITY, &(info->hw_state))) { if (test_bit(CARD_ACTIVITY, &(info->hw_state))) {
...@@ -691,8 +691,7 @@ static int bluecard_open(struct bluecard_info *info) ...@@ -691,8 +691,7 @@ static int bluecard_open(struct bluecard_info *info)
spin_lock_init(&(info->lock)); spin_lock_init(&(info->lock));
setup_timer(&(info->timer), &bluecard_activity_led_timeout, timer_setup(&info->timer, bluecard_activity_led_timeout, 0);
(u_long)info);
skb_queue_head_init(&(info->txq)); skb_queue_head_init(&(info->txq));
......
...@@ -327,6 +327,8 @@ static const struct { ...@@ -327,6 +327,8 @@ static const struct {
{ 0x4406, "BCM4324B3" }, /* 002.004.006 */ { 0x4406, "BCM4324B3" }, /* 002.004.006 */
{ 0x610c, "BCM4354" }, /* 003.001.012 */ { 0x610c, "BCM4354" }, /* 003.001.012 */
{ 0x2209, "BCM43430A1" }, /* 001.002.009 */ { 0x2209, "BCM43430A1" }, /* 001.002.009 */
{ 0x6119, "BCM4345C0" }, /* 003.001.025 */
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
{ } { }
}; };
...@@ -361,6 +363,7 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len) ...@@ -361,6 +363,7 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len)
switch ((rev & 0xf000) >> 12) { switch ((rev & 0xf000) >> 12) {
case 0: case 0:
case 1: case 1:
case 2:
case 3: case 3:
for (i = 0; bcm_uart_subver_table[i].name; i++) { for (i = 0; bcm_uart_subver_table[i].name; i++) {
if (subver == bcm_uart_subver_table[i].subver) { if (subver == bcm_uart_subver_table[i].subver) {
......
...@@ -64,7 +64,7 @@ static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv) ...@@ -64,7 +64,7 @@ static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
struct btmrvl_sdio_card *card = priv; struct btmrvl_sdio_card *card = priv;
struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg; struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg;
pr_info("%s: wake by bt", __func__); pr_info("%s: wake by bt\n", __func__);
cfg->wake_by_bt = true; cfg->wake_by_bt = true;
disable_irq_nosync(irq); disable_irq_nosync(irq);
...@@ -87,7 +87,7 @@ static int btmrvl_sdio_probe_of(struct device *dev, ...@@ -87,7 +87,7 @@ static int btmrvl_sdio_probe_of(struct device *dev,
if (!dev->of_node || if (!dev->of_node ||
!of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) { !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) {
pr_err("sdio platform data not available"); pr_err("sdio platform data not available\n");
return -1; return -1;
} }
...@@ -99,7 +99,7 @@ static int btmrvl_sdio_probe_of(struct device *dev, ...@@ -99,7 +99,7 @@ static int btmrvl_sdio_probe_of(struct device *dev,
if (cfg && card->plt_of_node) { if (cfg && card->plt_of_node) {
cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0); cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0);
if (!cfg->irq_bt) { if (!cfg->irq_bt) {
dev_err(dev, "fail to parse irq_bt from device tree"); dev_err(dev, "fail to parse irq_bt from device tree\n");
cfg->irq_bt = -1; cfg->irq_bt = -1;
} else { } else {
ret = devm_request_irq(dev, cfg->irq_bt, ret = devm_request_irq(dev, cfg->irq_bt,
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/rpmsg.h> #include <linux/rpmsg.h>
#include <linux/of.h>
#include <linux/soc/qcom/wcnss_ctrl.h> #include <linux/soc/qcom/wcnss_ctrl.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -26,6 +28,7 @@ ...@@ -26,6 +28,7 @@
struct btqcomsmd { struct btqcomsmd {
struct hci_dev *hdev; struct hci_dev *hdev;
bdaddr_t bdaddr;
struct rpmsg_endpoint *acl_channel; struct rpmsg_endpoint *acl_channel;
struct rpmsg_endpoint *cmd_channel; struct rpmsg_endpoint *cmd_channel;
}; };
...@@ -100,6 +103,38 @@ static int btqcomsmd_close(struct hci_dev *hdev) ...@@ -100,6 +103,38 @@ static int btqcomsmd_close(struct hci_dev *hdev)
return 0; return 0;
} }
static int btqcomsmd_setup(struct hci_dev *hdev)
{
struct btqcomsmd *btq = hci_get_drvdata(hdev);
struct sk_buff *skb;
int err;
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb))
return PTR_ERR(skb);
kfree_skb(skb);
/* Devices do not have persistent storage for BD address. If no
* BD address has been retrieved during probe, mark the device
* as having an invalid BD address.
*/
if (!bacmp(&btq->bdaddr, BDADDR_ANY)) {
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
return 0;
}
/* When setting a configured BD address fails, mark the device
* as having an invalid BD address.
*/
err = qca_set_bdaddr_rome(hdev, &btq->bdaddr);
if (err) {
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
return 0;
}
return 0;
}
static int btqcomsmd_probe(struct platform_device *pdev) static int btqcomsmd_probe(struct platform_device *pdev)
{ {
struct btqcomsmd *btq; struct btqcomsmd *btq;
...@@ -123,6 +158,15 @@ static int btqcomsmd_probe(struct platform_device *pdev) ...@@ -123,6 +158,15 @@ static int btqcomsmd_probe(struct platform_device *pdev)
if (IS_ERR(btq->cmd_channel)) if (IS_ERR(btq->cmd_channel))
return PTR_ERR(btq->cmd_channel); return PTR_ERR(btq->cmd_channel);
/* The local-bd-address property is usually injected by the
* bootloader which has access to the allocated BD address.
*/
if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address",
(u8 *)&btq->bdaddr, sizeof(bdaddr_t))) {
dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree",
&btq->bdaddr);
}
hdev = hci_alloc_dev(); hdev = hci_alloc_dev();
if (!hdev) if (!hdev)
return -ENOMEM; return -ENOMEM;
...@@ -135,6 +179,7 @@ static int btqcomsmd_probe(struct platform_device *pdev) ...@@ -135,6 +179,7 @@ static int btqcomsmd_probe(struct platform_device *pdev)
hdev->open = btqcomsmd_open; hdev->open = btqcomsmd_open;
hdev->close = btqcomsmd_close; hdev->close = btqcomsmd_close;
hdev->send = btqcomsmd_send; hdev->send = btqcomsmd_send;
hdev->setup = btqcomsmd_setup;
hdev->set_bdaddr = qca_set_bdaddr_rome; hdev->set_bdaddr = qca_set_bdaddr_rome;
ret = hci_register_dev(hdev); ret = hci_register_dev(hdev);
......
...@@ -66,7 +66,6 @@ static struct usb_driver btusb_driver; ...@@ -66,7 +66,6 @@ static struct usb_driver btusb_driver;
#define BTUSB_BCM2045 0x40000 #define BTUSB_BCM2045 0x40000
#define BTUSB_IFNUM_2 0x80000 #define BTUSB_IFNUM_2 0x80000
#define BTUSB_CW6622 0x100000 #define BTUSB_CW6622 0x100000
#define BTUSB_BCM_NO_PRODID 0x200000
static const struct usb_device_id btusb_table[] = { static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
...@@ -171,10 +170,6 @@ static const struct usb_device_id btusb_table[] = { ...@@ -171,10 +170,6 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM }, .driver_info = BTUSB_BCM_PATCHRAM },
/* Broadcom devices with missing product id */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0000, 0x0000, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM | BTUSB_BCM_NO_PRODID },
/* Intel Bluetooth USB Bootloader (RAM module) */ /* Intel Bluetooth USB Bootloader (RAM module) */
{ USB_DEVICE(0x8087, 0x0a5a), { USB_DEVICE(0x8087, 0x0a5a),
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC }, .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
...@@ -2909,19 +2904,6 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -2909,19 +2904,6 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info == BTUSB_IGNORE) if (id->driver_info == BTUSB_IGNORE)
return -ENODEV; return -ENODEV;
if (id->driver_info & BTUSB_BCM_NO_PRODID) {
struct usb_device *udev = interface_to_usbdev(intf);
/* For the broken Broadcom devices that show 0000:0000
* as USB vendor and product information, check that the
* manufacturer string identifies them as Broadcom based
* devices.
*/
if (!udev->manufacturer ||
strcmp(udev->manufacturer, "Broadcom Corp"))
return -ENODEV;
}
if (id->driver_info & BTUSB_ATH3012) { if (id->driver_info & BTUSB_ATH3012) {
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
......
This diff is collapsed.
...@@ -65,6 +65,7 @@ struct bcsp_struct { ...@@ -65,6 +65,7 @@ struct bcsp_struct {
u8 rxseq_txack; /* rxseq == txack. */ u8 rxseq_txack; /* rxseq == txack. */
u8 rxack; /* Last packet sent by us that the peer ack'ed */ u8 rxack; /* Last packet sent by us that the peer ack'ed */
struct timer_list tbcsp; struct timer_list tbcsp;
struct hci_uart *hu;
enum { enum {
BCSP_W4_PKT_DELIMITER, BCSP_W4_PKT_DELIMITER,
...@@ -697,10 +698,10 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) ...@@ -697,10 +698,10 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count)
} }
/* Arrange to retransmit all messages in the relq. */ /* Arrange to retransmit all messages in the relq. */
static void bcsp_timed_event(unsigned long arg) static void bcsp_timed_event(struct timer_list *t)
{ {
struct hci_uart *hu = (struct hci_uart *)arg; struct bcsp_struct *bcsp = from_timer(bcsp, t, tbcsp);
struct bcsp_struct *bcsp = hu->priv; struct hci_uart *hu = bcsp->hu;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags; unsigned long flags;
...@@ -729,11 +730,12 @@ static int bcsp_open(struct hci_uart *hu) ...@@ -729,11 +730,12 @@ static int bcsp_open(struct hci_uart *hu)
return -ENOMEM; return -ENOMEM;
hu->priv = bcsp; hu->priv = bcsp;
bcsp->hu = hu;
skb_queue_head_init(&bcsp->unack); skb_queue_head_init(&bcsp->unack);
skb_queue_head_init(&bcsp->rel); skb_queue_head_init(&bcsp->rel);
skb_queue_head_init(&bcsp->unrel); skb_queue_head_init(&bcsp->unrel);
setup_timer(&bcsp->tbcsp, bcsp_timed_event, (u_long)hu); timer_setup(&bcsp->tbcsp, bcsp_timed_event, 0);
bcsp->rx_state = BCSP_W4_PKT_DELIMITER; bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
......
...@@ -78,6 +78,7 @@ struct h5 { ...@@ -78,6 +78,7 @@ struct h5 {
int (*rx_func)(struct hci_uart *hu, u8 c); int (*rx_func)(struct hci_uart *hu, u8 c);
struct timer_list timer; /* Retransmission timer */ struct timer_list timer; /* Retransmission timer */
struct hci_uart *hu; /* Parent HCI UART */
u8 tx_seq; /* Next seq number to send */ u8 tx_seq; /* Next seq number to send */
u8 tx_ack; /* Next ack number to send */ u8 tx_ack; /* Next ack number to send */
...@@ -120,12 +121,12 @@ static u8 h5_cfg_field(struct h5 *h5) ...@@ -120,12 +121,12 @@ static u8 h5_cfg_field(struct h5 *h5)
return h5->tx_win & 0x07; return h5->tx_win & 0x07;
} }
static void h5_timed_event(unsigned long arg) static void h5_timed_event(struct timer_list *t)
{ {
const unsigned char sync_req[] = { 0x01, 0x7e }; const unsigned char sync_req[] = { 0x01, 0x7e };
unsigned char conf_req[3] = { 0x03, 0xfc }; unsigned char conf_req[3] = { 0x03, 0xfc };
struct hci_uart *hu = (struct hci_uart *)arg; struct h5 *h5 = from_timer(h5, t, timer);
struct h5 *h5 = hu->priv; struct hci_uart *hu = h5->hu;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags; unsigned long flags;
...@@ -197,6 +198,7 @@ static int h5_open(struct hci_uart *hu) ...@@ -197,6 +198,7 @@ static int h5_open(struct hci_uart *hu)
return -ENOMEM; return -ENOMEM;
hu->priv = h5; hu->priv = h5;
h5->hu = hu;
skb_queue_head_init(&h5->unack); skb_queue_head_init(&h5->unack);
skb_queue_head_init(&h5->rel); skb_queue_head_init(&h5->rel);
...@@ -204,7 +206,7 @@ static int h5_open(struct hci_uart *hu) ...@@ -204,7 +206,7 @@ static int h5_open(struct hci_uart *hu)
h5_reset_rx(h5); h5_reset_rx(h5);
setup_timer(&h5->timer, h5_timed_event, (unsigned long)hu); timer_setup(&h5->timer, h5_timed_event, 0);
h5->tx_win = H5_TX_WIN_MAX; h5->tx_win = H5_TX_WIN_MAX;
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/serdev.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -298,6 +299,12 @@ void hci_uart_set_flow_control(struct hci_uart *hu, bool enable) ...@@ -298,6 +299,12 @@ void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
unsigned int set = 0; unsigned int set = 0;
unsigned int clear = 0; unsigned int clear = 0;
if (hu->serdev) {
serdev_device_set_flow_control(hu->serdev, !enable);
serdev_device_set_rts(hu->serdev, !enable);
return;
}
if (enable) { if (enable) {
/* Disable hardware flow control */ /* Disable hardware flow control */
ktermios = tty->termios; ktermios = tty->termios;
......
...@@ -242,7 +242,7 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu) ...@@ -242,7 +242,7 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu)
* perfectly safe to always send one. * perfectly safe to always send one.
*/ */
BT_DBG("dual wake-up-indication"); BT_DBG("dual wake-up-indication");
/* deliberate fall-through - do not add break */ /* fall through */
case HCILL_ASLEEP: case HCILL_ASLEEP:
/* acknowledge device wake up */ /* acknowledge device wake up */
if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) { if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) {
......
...@@ -307,10 +307,10 @@ static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work) ...@@ -307,10 +307,10 @@ static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work)
serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu); serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
} }
static void hci_ibs_tx_idle_timeout(unsigned long arg) static void hci_ibs_tx_idle_timeout(struct timer_list *t)
{ {
struct hci_uart *hu = (struct hci_uart *)arg; struct qca_data *qca = from_timer(qca, t, tx_idle_timer);
struct qca_data *qca = hu->priv; struct hci_uart *hu = qca->hu;
unsigned long flags; unsigned long flags;
BT_DBG("hu %p idle timeout in %d state", hu, qca->tx_ibs_state); BT_DBG("hu %p idle timeout in %d state", hu, qca->tx_ibs_state);
...@@ -342,10 +342,10 @@ static void hci_ibs_tx_idle_timeout(unsigned long arg) ...@@ -342,10 +342,10 @@ static void hci_ibs_tx_idle_timeout(unsigned long arg)
spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
} }
static void hci_ibs_wake_retrans_timeout(unsigned long arg) static void hci_ibs_wake_retrans_timeout(struct timer_list *t)
{ {
struct hci_uart *hu = (struct hci_uart *)arg; struct qca_data *qca = from_timer(qca, t, wake_retrans_timer);
struct qca_data *qca = hu->priv; struct hci_uart *hu = qca->hu;
unsigned long flags, retrans_delay; unsigned long flags, retrans_delay;
bool retransmit = false; bool retransmit = false;
...@@ -438,11 +438,10 @@ static int qca_open(struct hci_uart *hu) ...@@ -438,11 +438,10 @@ static int qca_open(struct hci_uart *hu)
hu->priv = qca; hu->priv = qca;
setup_timer(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout, timer_setup(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout, 0);
(u_long)hu);
qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS; qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS;
setup_timer(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, (u_long)hu); timer_setup(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, 0);
qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS; qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS;
BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u", BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u",
......
...@@ -1944,7 +1944,7 @@ static int ca8210_skb_tx( ...@@ -1944,7 +1944,7 @@ static int ca8210_skb_tx(
) )
{ {
int status; int status;
struct ieee802154_hdr header = { 0 }; struct ieee802154_hdr header = { };
struct secspec secspec; struct secspec secspec;
unsigned int mac_len; unsigned int mac_len;
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "ecdh_helper.h" #include "ecdh_helper.h"
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <crypto/kpp.h>
#include <crypto/ecdh.h> #include <crypto/ecdh.h>
struct ecdh_completion { struct ecdh_completion {
...@@ -50,55 +49,35 @@ static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits) ...@@ -50,55 +49,35 @@ static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits)
out[i] = __swab64(in[ndigits - 1 - i]); out[i] = __swab64(in[ndigits - 1 - i]);
} }
bool compute_ecdh_secret(const u8 public_key[64], const u8 private_key[32], /* compute_ecdh_secret() - function assumes that the private key was
* already set.
* @tfm: KPP tfm handle allocated with crypto_alloc_kpp().
* @public_key: pair's ecc public key.
* secret: memory where the ecdh computed shared secret will be saved.
*
* Return: zero on success; error code in case of error.
*/
int compute_ecdh_secret(struct crypto_kpp *tfm, const u8 public_key[64],
u8 secret[32]) u8 secret[32])
{ {
struct crypto_kpp *tfm;
struct kpp_request *req; struct kpp_request *req;
struct ecdh p; u8 *tmp;
struct ecdh_completion result; struct ecdh_completion result;
struct scatterlist src, dst; struct scatterlist src, dst;
u8 *tmp, *buf; int err;
unsigned int buf_len;
int err = -ENOMEM;
tmp = kmalloc(64, GFP_KERNEL); tmp = kmalloc(64, GFP_KERNEL);
if (!tmp) if (!tmp)
return false; return -ENOMEM;
tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0); req = kpp_request_alloc(tfm, GFP_KERNEL);
if (IS_ERR(tfm)) { if (!req) {
pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n", err = -ENOMEM;
PTR_ERR(tfm));
goto free_tmp; goto free_tmp;
} }
req = kpp_request_alloc(tfm, GFP_KERNEL);
if (!req)
goto free_kpp;
init_completion(&result.completion); init_completion(&result.completion);
/* Security Manager Protocol holds digits in litte-endian order
* while ECC API expect big-endian data
*/
swap_digits((u64 *)private_key, (u64 *)tmp, 4);
p.key = (char *)tmp;
p.key_size = 32;
/* Set curve_id */
p.curve_id = ECC_CURVE_NIST_P256;
buf_len = crypto_ecdh_key_len(&p);
buf = kmalloc(buf_len, GFP_KERNEL);
if (!buf)
goto free_req;
crypto_ecdh_encode_key(buf, buf_len, &p);
/* Set A private Key */
err = crypto_kpp_set_secret(tfm, (void *)buf, buf_len);
if (err)
goto free_all;
swap_digits((u64 *)public_key, (u64 *)tmp, 4); /* x */ swap_digits((u64 *)public_key, (u64 *)tmp, 4); /* x */
swap_digits((u64 *)&public_key[32], (u64 *)&tmp[32], 4); /* y */ swap_digits((u64 *)&public_key[32], (u64 *)&tmp[32], 4); /* y */
...@@ -123,65 +102,88 @@ bool compute_ecdh_secret(const u8 public_key[64], const u8 private_key[32], ...@@ -123,65 +102,88 @@ bool compute_ecdh_secret(const u8 public_key[64], const u8 private_key[32],
memcpy(secret, tmp, 32); memcpy(secret, tmp, 32);
free_all: free_all:
kzfree(buf);
free_req:
kpp_request_free(req); kpp_request_free(req);
free_kpp:
crypto_free_kpp(tfm);
free_tmp: free_tmp:
kfree(tmp); kzfree(tmp);
return (err == 0); return err;
} }
bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32]) /* set_ecdh_privkey() - set or generate ecc private key.
*
* Function generates an ecc private key in the crypto subsystem when receiving
* a NULL private key or sets the received key when not NULL.
*
* @tfm: KPP tfm handle allocated with crypto_alloc_kpp().
* @private_key: user's ecc private key. When not NULL, the key is expected
* in little endian format.
*
* Return: zero on success; error code in case of error.
*/
int set_ecdh_privkey(struct crypto_kpp *tfm, const u8 private_key[32])
{ {
struct crypto_kpp *tfm; u8 *buf, *tmp = NULL;
struct kpp_request *req;
struct ecdh p;
struct ecdh_completion result;
struct scatterlist dst;
u8 *tmp, *buf;
unsigned int buf_len; unsigned int buf_len;
int err = -ENOMEM; int err;
const unsigned short max_tries = 16; struct ecdh p = {0};
unsigned short tries = 0;
tmp = kmalloc(64, GFP_KERNEL); p.curve_id = ECC_CURVE_NIST_P256;
if (!tmp)
return false;
tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0); if (private_key) {
if (IS_ERR(tfm)) { tmp = kmalloc(32, GFP_KERNEL);
pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n", if (!tmp)
PTR_ERR(tfm)); return -ENOMEM;
goto free_tmp; swap_digits((u64 *)private_key, (u64 *)tmp, 4);
p.key = tmp;
p.key_size = 32;
} }
req = kpp_request_alloc(tfm, GFP_KERNEL);
if (!req)
goto free_kpp;
init_completion(&result.completion);
/* Set curve_id */
p.curve_id = ECC_CURVE_NIST_P256;
p.key_size = 32;
buf_len = crypto_ecdh_key_len(&p); buf_len = crypto_ecdh_key_len(&p);
buf = kmalloc(buf_len, GFP_KERNEL); buf = kmalloc(buf_len, GFP_KERNEL);
if (!buf) if (!buf) {
goto free_req; err = -ENOMEM;
goto free_tmp;
}
do { err = crypto_ecdh_encode_key(buf, buf_len, &p);
if (tries++ >= max_tries) if (err)
goto free_all; goto free_all;
/* Set private Key */
p.key = (char *)private_key;
crypto_ecdh_encode_key(buf, buf_len, &p);
err = crypto_kpp_set_secret(tfm, buf, buf_len); err = crypto_kpp_set_secret(tfm, buf, buf_len);
if (err) /* fall through */
goto free_all; free_all:
kzfree(buf);
free_tmp:
kzfree(tmp);
return err;
}
/* generate_ecdh_public_key() - function assumes that the private key was
* already set.
*
* @tfm: KPP tfm handle allocated with crypto_alloc_kpp().
* @public_key: memory where the computed ecc public key will be saved.
*
* Return: zero on success; error code in case of error.
*/
int generate_ecdh_public_key(struct crypto_kpp *tfm, u8 public_key[64])
{
struct kpp_request *req;
u8 *tmp;
struct ecdh_completion result;
struct scatterlist dst;
int err;
tmp = kmalloc(64, GFP_KERNEL);
if (!tmp)
return -ENOMEM;
req = kpp_request_alloc(tfm, GFP_KERNEL);
if (!req) {
err = -ENOMEM;
goto free_tmp;
}
init_completion(&result.completion);
sg_init_one(&dst, tmp, 64); sg_init_one(&dst, tmp, 64);
kpp_request_set_input(req, NULL, 0); kpp_request_set_input(req, NULL, 0);
kpp_request_set_output(req, &dst, 64); kpp_request_set_output(req, &dst, 64);
...@@ -189,38 +191,40 @@ bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32]) ...@@ -189,38 +191,40 @@ bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32])
ecdh_complete, &result); ecdh_complete, &result);
err = crypto_kpp_generate_public_key(req); err = crypto_kpp_generate_public_key(req);
if (err == -EINPROGRESS) { if (err == -EINPROGRESS) {
wait_for_completion(&result.completion); wait_for_completion(&result.completion);
err = result.err; err = result.err;
} }
/* Private key is not valid. Regenerate */
if (err == -EINVAL)
continue;
if (err < 0) if (err < 0)
goto free_all; goto free_all;
else
break;
} while (true);
/* Keys are handed back in little endian as expected by Security /* The public key is handed back in little endian as expected by
* Manager Protocol * the Security Manager Protocol.
*/ */
swap_digits((u64 *)tmp, (u64 *)public_key, 4); /* x */ swap_digits((u64 *)tmp, (u64 *)public_key, 4); /* x */
swap_digits((u64 *)&tmp[32], (u64 *)&public_key[32], 4); /* y */ swap_digits((u64 *)&tmp[32], (u64 *)&public_key[32], 4); /* y */
swap_digits((u64 *)private_key, (u64 *)tmp, 4);
memcpy(private_key, tmp, 32);
free_all: free_all:
kzfree(buf);
free_req:
kpp_request_free(req); kpp_request_free(req);
free_kpp:
crypto_free_kpp(tfm);
free_tmp: free_tmp:
kfree(tmp); kfree(tmp);
return (err == 0); return err;
}
/* generate_ecdh_keys() - generate ecc key pair.
*
* @tfm: KPP tfm handle allocated with crypto_alloc_kpp().
* @public_key: memory where the computed ecc public key will be saved.
*
* Return: zero on success; error code in case of error.
*/
int generate_ecdh_keys(struct crypto_kpp *tfm, u8 public_key[64])
{
int err;
err = set_ecdh_privkey(tfm, NULL);
if (err)
return err;
return generate_ecdh_public_key(tfm, public_key);
} }
...@@ -20,8 +20,11 @@ ...@@ -20,8 +20,11 @@
* COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
* SOFTWARE IS DISCLAIMED. * SOFTWARE IS DISCLAIMED.
*/ */
#include <crypto/kpp.h>
#include <linux/types.h> #include <linux/types.h>
bool compute_ecdh_secret(const u8 pub_a[64], const u8 priv_b[32], int compute_ecdh_secret(struct crypto_kpp *tfm, const u8 pair_public_key[64],
u8 secret[32]); u8 secret[32]);
bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32]); int set_ecdh_privkey(struct crypto_kpp *tfm, const u8 *private_key);
int generate_ecdh_public_key(struct crypto_kpp *tfm, u8 public_key[64]);
int generate_ecdh_keys(struct crypto_kpp *tfm, u8 public_key[64]);
...@@ -138,12 +138,12 @@ static const u8 dhkey_3[32] __initconst = { ...@@ -138,12 +138,12 @@ static const u8 dhkey_3[32] __initconst = {
0x7c, 0x1c, 0xf9, 0x49, 0xe6, 0xd7, 0xaa, 0x70, 0x7c, 0x1c, 0xf9, 0x49, 0xe6, 0xd7, 0xaa, 0x70,
}; };
static int __init test_ecdh_sample(const u8 priv_a[32], const u8 priv_b[32], static int __init test_ecdh_sample(struct crypto_kpp *tfm, const u8 priv_a[32],
const u8 pub_a[64], const u8 pub_b[64], const u8 priv_b[32], const u8 pub_a[64],
const u8 dhkey[32]) const u8 pub_b[64], const u8 dhkey[32])
{ {
u8 *tmp, *dhkey_a, *dhkey_b; u8 *tmp, *dhkey_a, *dhkey_b;
int ret = 0; int ret;
tmp = kmalloc(64, GFP_KERNEL); tmp = kmalloc(64, GFP_KERNEL);
if (!tmp) if (!tmp)
...@@ -152,17 +152,30 @@ static int __init test_ecdh_sample(const u8 priv_a[32], const u8 priv_b[32], ...@@ -152,17 +152,30 @@ static int __init test_ecdh_sample(const u8 priv_a[32], const u8 priv_b[32],
dhkey_a = &tmp[0]; dhkey_a = &tmp[0];
dhkey_b = &tmp[32]; dhkey_b = &tmp[32];
compute_ecdh_secret(pub_b, priv_a, dhkey_a); ret = set_ecdh_privkey(tfm, priv_a);
compute_ecdh_secret(pub_a, priv_b, dhkey_b); if (ret)
goto out;
ret = compute_ecdh_secret(tfm, pub_b, dhkey_a);
if (ret)
goto out;
if (memcmp(dhkey_a, dhkey, 32)) { if (memcmp(dhkey_a, dhkey, 32)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
ret = set_ecdh_privkey(tfm, priv_b);
if (ret)
goto out;
ret = compute_ecdh_secret(tfm, pub_a, dhkey_b);
if (ret)
goto out;
if (memcmp(dhkey_b, dhkey, 32)) if (memcmp(dhkey_b, dhkey, 32))
ret = -EINVAL; ret = -EINVAL;
/* fall through*/
out: out:
kfree(tmp); kfree(tmp);
return ret; return ret;
...@@ -185,30 +198,43 @@ static const struct file_operations test_ecdh_fops = { ...@@ -185,30 +198,43 @@ static const struct file_operations test_ecdh_fops = {
static int __init test_ecdh(void) static int __init test_ecdh(void)
{ {
struct crypto_kpp *tfm;
ktime_t calltime, delta, rettime; ktime_t calltime, delta, rettime;
unsigned long long duration; unsigned long long duration = 0;
int err; int err;
calltime = ktime_get(); calltime = ktime_get();
err = test_ecdh_sample(priv_a_1, priv_b_1, pub_a_1, pub_b_1, dhkey_1); tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
if (IS_ERR(tfm)) {
BT_ERR("Unable to create ECDH crypto context");
err = PTR_ERR(tfm);
goto done;
}
err = test_ecdh_sample(tfm, priv_a_1, priv_b_1, pub_a_1, pub_b_1,
dhkey_1);
if (err) { if (err) {
BT_ERR("ECDH sample 1 failed"); BT_ERR("ECDH sample 1 failed");
goto done; goto done;
} }
err = test_ecdh_sample(priv_a_2, priv_b_2, pub_a_2, pub_b_2, dhkey_2); err = test_ecdh_sample(tfm, priv_a_2, priv_b_2, pub_a_2, pub_b_2,
dhkey_2);
if (err) { if (err) {
BT_ERR("ECDH sample 2 failed"); BT_ERR("ECDH sample 2 failed");
goto done; goto done;
} }
err = test_ecdh_sample(priv_a_3, priv_a_3, pub_a_3, pub_a_3, dhkey_3); err = test_ecdh_sample(tfm, priv_a_3, priv_a_3, pub_a_3, pub_a_3,
dhkey_3);
if (err) { if (err) {
BT_ERR("ECDH sample 3 failed"); BT_ERR("ECDH sample 3 failed");
goto done; goto done;
} }
crypto_free_kpp(tfm);
rettime = ktime_get(); rettime = ktime_get();
delta = ktime_sub(rettime, calltime); delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10; duration = (unsigned long long) ktime_to_ns(delta) >> 10;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <crypto/algapi.h> #include <crypto/algapi.h>
#include <crypto/b128ops.h> #include <crypto/b128ops.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include <crypto/kpp.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -83,7 +84,6 @@ enum { ...@@ -83,7 +84,6 @@ enum {
struct smp_dev { struct smp_dev {
/* Secure Connections OOB data */ /* Secure Connections OOB data */
u8 local_pk[64]; u8 local_pk[64];
u8 local_sk[32];
u8 local_rand[16]; u8 local_rand[16];
bool debug_key; bool debug_key;
...@@ -92,6 +92,7 @@ struct smp_dev { ...@@ -92,6 +92,7 @@ struct smp_dev {
struct crypto_cipher *tfm_aes; struct crypto_cipher *tfm_aes;
struct crypto_shash *tfm_cmac; struct crypto_shash *tfm_cmac;
struct crypto_kpp *tfm_ecdh;
}; };
struct smp_chan { struct smp_chan {
...@@ -124,13 +125,13 @@ struct smp_chan { ...@@ -124,13 +125,13 @@ struct smp_chan {
/* Secure Connections variables */ /* Secure Connections variables */
u8 local_pk[64]; u8 local_pk[64];
u8 local_sk[32];
u8 remote_pk[64]; u8 remote_pk[64];
u8 dhkey[32]; u8 dhkey[32];
u8 mackey[16]; u8 mackey[16];
struct crypto_cipher *tfm_aes; struct crypto_cipher *tfm_aes;
struct crypto_shash *tfm_cmac; struct crypto_shash *tfm_cmac;
struct crypto_kpp *tfm_ecdh;
}; };
/* These debug key values are defined in the SMP section of the core /* These debug key values are defined in the SMP section of the core
...@@ -565,22 +566,22 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) ...@@ -565,22 +566,22 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) { if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
BT_DBG("Using debug keys"); BT_DBG("Using debug keys");
err = set_ecdh_privkey(smp->tfm_ecdh, debug_sk);
if (err)
return err;
memcpy(smp->local_pk, debug_pk, 64); memcpy(smp->local_pk, debug_pk, 64);
memcpy(smp->local_sk, debug_sk, 32);
smp->debug_key = true; smp->debug_key = true;
} else { } else {
while (true) { while (true) {
/* Seed private key with random number */ /* Generate key pair for Secure Connections */
get_random_bytes(smp->local_sk, 32); err = generate_ecdh_keys(smp->tfm_ecdh, smp->local_pk);
if (err)
/* Generate local key pair for Secure Connections */ return err;
if (!generate_ecdh_keys(smp->local_pk, smp->local_sk))
return -EIO;
/* This is unlikely, but we need to check that /* This is unlikely, but we need to check that
* we didn't accidentially generate a debug key. * we didn't accidentially generate a debug key.
*/ */
if (crypto_memneq(smp->local_sk, debug_sk, 32)) if (crypto_memneq(smp->local_pk, debug_pk, 64))
break; break;
} }
smp->debug_key = false; smp->debug_key = false;
...@@ -588,7 +589,6 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) ...@@ -588,7 +589,6 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
SMP_DBG("OOB Public Key X: %32phN", smp->local_pk); SMP_DBG("OOB Public Key X: %32phN", smp->local_pk);
SMP_DBG("OOB Public Key Y: %32phN", smp->local_pk + 32); SMP_DBG("OOB Public Key Y: %32phN", smp->local_pk + 32);
SMP_DBG("OOB Private Key: %32phN", smp->local_sk);
get_random_bytes(smp->local_rand, 16); get_random_bytes(smp->local_rand, 16);
...@@ -771,6 +771,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn) ...@@ -771,6 +771,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
crypto_free_cipher(smp->tfm_aes); crypto_free_cipher(smp->tfm_aes);
crypto_free_shash(smp->tfm_cmac); crypto_free_shash(smp->tfm_cmac);
crypto_free_kpp(smp->tfm_ecdh);
/* Ensure that we don't leave any debug key around if debug key /* Ensure that we don't leave any debug key around if debug key
* support hasn't been explicitly enabled. * support hasn't been explicitly enabled.
...@@ -1391,16 +1392,19 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) ...@@ -1391,16 +1392,19 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
smp->tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); smp->tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(smp->tfm_aes)) { if (IS_ERR(smp->tfm_aes)) {
BT_ERR("Unable to create AES crypto context"); BT_ERR("Unable to create AES crypto context");
kzfree(smp); goto zfree_smp;
return NULL;
} }
smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
if (IS_ERR(smp->tfm_cmac)) { if (IS_ERR(smp->tfm_cmac)) {
BT_ERR("Unable to create CMAC crypto context"); BT_ERR("Unable to create CMAC crypto context");
crypto_free_cipher(smp->tfm_aes); goto free_cipher;
kzfree(smp); }
return NULL;
smp->tfm_ecdh = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
if (IS_ERR(smp->tfm_ecdh)) {
BT_ERR("Unable to create ECDH crypto context");
goto free_shash;
} }
smp->conn = conn; smp->conn = conn;
...@@ -1413,6 +1417,14 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) ...@@ -1413,6 +1417,14 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
hci_conn_hold(conn->hcon); hci_conn_hold(conn->hcon);
return smp; return smp;
free_shash:
crypto_free_shash(smp->tfm_cmac);
free_cipher:
crypto_free_cipher(smp->tfm_aes);
zfree_smp:
kzfree(smp);
return NULL;
} }
static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16]) static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
...@@ -1883,7 +1895,6 @@ static u8 sc_send_public_key(struct smp_chan *smp) ...@@ -1883,7 +1895,6 @@ static u8 sc_send_public_key(struct smp_chan *smp)
smp_dev = chan->data; smp_dev = chan->data;
memcpy(smp->local_pk, smp_dev->local_pk, 64); memcpy(smp->local_pk, smp_dev->local_pk, 64);
memcpy(smp->local_sk, smp_dev->local_sk, 32);
memcpy(smp->lr, smp_dev->local_rand, 16); memcpy(smp->lr, smp_dev->local_rand, 16);
if (smp_dev->debug_key) if (smp_dev->debug_key)
...@@ -1894,22 +1905,20 @@ static u8 sc_send_public_key(struct smp_chan *smp) ...@@ -1894,22 +1905,20 @@ static u8 sc_send_public_key(struct smp_chan *smp)
if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) { if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
BT_DBG("Using debug keys"); BT_DBG("Using debug keys");
if (set_ecdh_privkey(smp->tfm_ecdh, debug_sk))
return SMP_UNSPECIFIED;
memcpy(smp->local_pk, debug_pk, 64); memcpy(smp->local_pk, debug_pk, 64);
memcpy(smp->local_sk, debug_sk, 32);
set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
} else { } else {
while (true) { while (true) {
/* Seed private key with random number */ /* Generate key pair for Secure Connections */
get_random_bytes(smp->local_sk, 32); if (generate_ecdh_keys(smp->tfm_ecdh, smp->local_pk))
/* Generate local key pair for Secure Connections */
if (!generate_ecdh_keys(smp->local_pk, smp->local_sk))
return SMP_UNSPECIFIED; return SMP_UNSPECIFIED;
/* This is unlikely, but we need to check that /* This is unlikely, but we need to check that
* we didn't accidentially generate a debug key. * we didn't accidentially generate a debug key.
*/ */
if (crypto_memneq(smp->local_sk, debug_sk, 32)) if (crypto_memneq(smp->local_pk, debug_pk, 64))
break; break;
} }
} }
...@@ -1917,7 +1926,6 @@ static u8 sc_send_public_key(struct smp_chan *smp) ...@@ -1917,7 +1926,6 @@ static u8 sc_send_public_key(struct smp_chan *smp)
done: done:
SMP_DBG("Local Public Key X: %32phN", smp->local_pk); SMP_DBG("Local Public Key X: %32phN", smp->local_pk);
SMP_DBG("Local Public Key Y: %32phN", smp->local_pk + 32); SMP_DBG("Local Public Key Y: %32phN", smp->local_pk + 32);
SMP_DBG("Local Private Key: %32phN", smp->local_sk);
smp_send_cmd(smp->conn, SMP_CMD_PUBLIC_KEY, 64, smp->local_pk); smp_send_cmd(smp->conn, SMP_CMD_PUBLIC_KEY, 64, smp->local_pk);
...@@ -2645,6 +2653,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -2645,6 +2653,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
struct l2cap_chan *chan = conn->smp; struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data; struct smp_chan *smp = chan->data;
struct hci_dev *hdev = hcon->hdev; struct hci_dev *hdev = hcon->hdev;
struct crypto_kpp *tfm_ecdh;
struct smp_cmd_pairing_confirm cfm; struct smp_cmd_pairing_confirm cfm;
int err; int err;
...@@ -2677,7 +2686,18 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -2677,7 +2686,18 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk); SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk);
SMP_DBG("Remote Public Key Y: %32phN", smp->remote_pk + 32); SMP_DBG("Remote Public Key Y: %32phN", smp->remote_pk + 32);
if (!compute_ecdh_secret(smp->remote_pk, smp->local_sk, smp->dhkey)) /* Compute the shared secret on the same crypto tfm on which the private
* key was set/generated.
*/
if (test_bit(SMP_FLAG_LOCAL_OOB, &smp->flags)) {
struct smp_dev *smp_dev = chan->data;
tfm_ecdh = smp_dev->tfm_ecdh;
} else {
tfm_ecdh = smp->tfm_ecdh;
}
if (compute_ecdh_secret(tfm_ecdh, smp->remote_pk, smp->dhkey))
return SMP_UNSPECIFIED; return SMP_UNSPECIFIED;
SMP_DBG("DHKey %32phN", smp->dhkey); SMP_DBG("DHKey %32phN", smp->dhkey);
...@@ -3169,6 +3189,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) ...@@ -3169,6 +3189,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
struct smp_dev *smp; struct smp_dev *smp;
struct crypto_cipher *tfm_aes; struct crypto_cipher *tfm_aes;
struct crypto_shash *tfm_cmac; struct crypto_shash *tfm_cmac;
struct crypto_kpp *tfm_ecdh;
if (cid == L2CAP_CID_SMP_BREDR) { if (cid == L2CAP_CID_SMP_BREDR) {
smp = NULL; smp = NULL;
...@@ -3194,8 +3215,18 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) ...@@ -3194,8 +3215,18 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
return ERR_CAST(tfm_cmac); return ERR_CAST(tfm_cmac);
} }
tfm_ecdh = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
if (IS_ERR(tfm_ecdh)) {
BT_ERR("Unable to create ECDH crypto context");
crypto_free_shash(tfm_cmac);
crypto_free_cipher(tfm_aes);
kzfree(smp);
return ERR_CAST(tfm_ecdh);
}
smp->tfm_aes = tfm_aes; smp->tfm_aes = tfm_aes;
smp->tfm_cmac = tfm_cmac; smp->tfm_cmac = tfm_cmac;
smp->tfm_ecdh = tfm_ecdh;
smp->min_key_size = SMP_MIN_ENC_KEY_SIZE; smp->min_key_size = SMP_MIN_ENC_KEY_SIZE;
smp->max_key_size = SMP_MAX_ENC_KEY_SIZE; smp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
...@@ -3205,6 +3236,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) ...@@ -3205,6 +3236,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
if (smp) { if (smp) {
crypto_free_cipher(smp->tfm_aes); crypto_free_cipher(smp->tfm_aes);
crypto_free_shash(smp->tfm_cmac); crypto_free_shash(smp->tfm_cmac);
crypto_free_kpp(smp->tfm_ecdh);
kzfree(smp); kzfree(smp);
} }
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -3252,6 +3284,7 @@ static void smp_del_chan(struct l2cap_chan *chan) ...@@ -3252,6 +3284,7 @@ static void smp_del_chan(struct l2cap_chan *chan)
chan->data = NULL; chan->data = NULL;
crypto_free_cipher(smp->tfm_aes); crypto_free_cipher(smp->tfm_aes);
crypto_free_shash(smp->tfm_cmac); crypto_free_shash(smp->tfm_cmac);
crypto_free_kpp(smp->tfm_ecdh);
kzfree(smp); kzfree(smp);
} }
...@@ -3490,25 +3523,18 @@ void smp_unregister(struct hci_dev *hdev) ...@@ -3490,25 +3523,18 @@ void smp_unregister(struct hci_dev *hdev)
#if IS_ENABLED(CONFIG_BT_SELFTEST_SMP) #if IS_ENABLED(CONFIG_BT_SELFTEST_SMP)
static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits) static int __init test_debug_key(struct crypto_kpp *tfm_ecdh)
{
int i;
for (i = 0; i < ndigits; i++)
out[i] = __swab64(in[ndigits - 1 - i]);
}
static int __init test_debug_key(void)
{ {
u8 pk[64], sk[32]; u8 pk[64];
int err;
swap_digits((u64 *)debug_sk, (u64 *)sk, 4);
if (!generate_ecdh_keys(pk, sk)) err = set_ecdh_privkey(tfm_ecdh, debug_sk);
return -EINVAL; if (err)
return err;
if (crypto_memneq(sk, debug_sk, 32)) err = generate_ecdh_public_key(tfm_ecdh, pk);
return -EINVAL; if (err)
return err;
if (crypto_memneq(pk, debug_pk, 64)) if (crypto_memneq(pk, debug_pk, 64))
return -EINVAL; return -EINVAL;
...@@ -3763,7 +3789,8 @@ static const struct file_operations test_smp_fops = { ...@@ -3763,7 +3789,8 @@ static const struct file_operations test_smp_fops = {
}; };
static int __init run_selftests(struct crypto_cipher *tfm_aes, static int __init run_selftests(struct crypto_cipher *tfm_aes,
struct crypto_shash *tfm_cmac) struct crypto_shash *tfm_cmac,
struct crypto_kpp *tfm_ecdh)
{ {
ktime_t calltime, delta, rettime; ktime_t calltime, delta, rettime;
unsigned long long duration; unsigned long long duration;
...@@ -3771,7 +3798,7 @@ static int __init run_selftests(struct crypto_cipher *tfm_aes, ...@@ -3771,7 +3798,7 @@ static int __init run_selftests(struct crypto_cipher *tfm_aes,
calltime = ktime_get(); calltime = ktime_get();
err = test_debug_key(); err = test_debug_key(tfm_ecdh);
if (err) { if (err) {
BT_ERR("debug_key test failed"); BT_ERR("debug_key test failed");
goto done; goto done;
...@@ -3848,6 +3875,7 @@ int __init bt_selftest_smp(void) ...@@ -3848,6 +3875,7 @@ int __init bt_selftest_smp(void)
{ {
struct crypto_cipher *tfm_aes; struct crypto_cipher *tfm_aes;
struct crypto_shash *tfm_cmac; struct crypto_shash *tfm_cmac;
struct crypto_kpp *tfm_ecdh;
int err; int err;
tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
...@@ -3863,10 +3891,19 @@ int __init bt_selftest_smp(void) ...@@ -3863,10 +3891,19 @@ int __init bt_selftest_smp(void)
return PTR_ERR(tfm_cmac); return PTR_ERR(tfm_cmac);
} }
err = run_selftests(tfm_aes, tfm_cmac); tfm_ecdh = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
if (IS_ERR(tfm_ecdh)) {
BT_ERR("Unable to create ECDH crypto context");
crypto_free_shash(tfm_cmac);
crypto_free_cipher(tfm_aes);
return PTR_ERR(tfm_ecdh);
}
err = run_selftests(tfm_aes, tfm_cmac, tfm_ecdh);
crypto_free_shash(tfm_cmac); crypto_free_shash(tfm_cmac);
crypto_free_cipher(tfm_aes); crypto_free_cipher(tfm_aes);
crypto_free_kpp(tfm_ecdh);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment