RE: [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Hi Vinicius,


> -----Original Message-----
> From: linux-bluetooth-owner@xxxxxxxxxxxxxxx [mailto:linux-bluetooth-
> owner@xxxxxxxxxxxxxxx] On Behalf Of Vinicius Costa Gomes
> Sent: 06 December, 2010 1:44 PM
> To: linux-bluetooth@xxxxxxxxxxxxxxx
> Cc: Vinicius Costa Gomes
> Subject: [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption
> 
> This adds support for starting SMP Phase 2 Encryption, when the initial
> SMP negotiation is successful. This adds the LE Start Encryption and LE
> Long Term Key Request commands and related events.
> 
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@xxxxxxxxxxxxx>
> ---
>  include/net/bluetooth/hci.h      |   34 +++++++++++++++++++
>  include/net/bluetooth/hci_core.h |    5 +++
>  net/bluetooth/hci_conn.c         |   47 ++++++++++++++++++++++++++
>  net/bluetooth/hci_event.c        |   67
> ++++++++++++++++++++++++++++++++++++++
>  net/bluetooth/smp.c              |    8 ++++-
>  5 files changed, 160 insertions(+), 1 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index dff6ded..e6bed3f 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -626,6 +626,33 @@ struct hci_cp_le_create_conn {
> 
>  #define HCI_OP_LE_CREATE_CONN_CANCEL	0x200e
> 
> +#define HCI_OP_LE_START_ENC		0x2019
> +struct hci_cp_le_start_enc {
> +	__le16	handle;
> +	__u8	rand[8];
> +	__le16	ediv;
> +	__u8	ltk[16];
> +} __packed;
> +
> +#define HCI_OP_LE_LTK_REPLY		0x201a
> +struct hci_cp_le_ltk_reply {
> +	__le16	handle;
> +	__u8	ltk[16];
> +} __packed;
> +struct hci_rp_le_ltk_reply {
> +	__u8	status;
> +	__le16	handle;
> +} __packed;
> +
> +#define HCI_OP_LE_LTK_NEG_REPLY		0x201b
> +struct hci_cp_le_ltk_neg_reply {
> +	__le16	handle;
> +} __packed;
> +struct hci_rp_le_ltk_neg_reply {
> +	__u8	status;
> +	__le16	handle;
> +} __packed;
> +
>  /* ---- HCI Events ---- */
>  #define HCI_EV_INQUIRY_COMPLETE		0x01
> 
> @@ -897,6 +924,13 @@ struct hci_ev_le_conn_complete {
>  	__u8     clk_accurancy;
>  } __packed;
> 
> +#define HCI_EV_LE_LTK_REQ		0x05
> +struct hci_ev_le_ltk_req {
> +	__le16	handle;
> +	__u8	random[8];
> +	__le16	ediv;
> +} __packed;
> +
>  /* Internal events generated by Bluetooth stack */
>  #define HCI_EV_STACK_INTERNAL	0xfd
>  struct hci_ev_stack_internal {
> diff --git a/include/net/bluetooth/hci_core.h
> b/include/net/bluetooth/hci_core.h
> index d0a9f5d..c6c44eb 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -192,6 +192,7 @@ struct hci_conn {
>  	__u8             sec_level;
>  	__u8             power_save;
>  	__u16            disc_timeout;
> +	__u8		 ltk[16];
>  	unsigned long	 pend;
> 
>  	unsigned int	 sent;
> @@ -713,4 +714,8 @@ struct hci_sec_filter {
> 
>  void hci_req_complete(struct hci_dev *hdev, int result);
> 
> +void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16]);
> +void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
> +void hci_le_ltk_neg_reply(struct hci_conn *conn);
> +
>  #endif /* __HCI_CORE_H */
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index edfb48b..f919ddb 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -183,6 +183,53 @@ void hci_setup_sync(struct hci_conn *conn, __u16
> handle)
>  	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
>  }
> 
> +void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16])
> +{
> +	struct hci_dev *hdev = conn->hdev;
> +	struct hci_cp_le_start_enc cp;
> +
> +	BT_DBG("%p", conn);
> +
> +	memset(&cp, 0, sizeof(cp));
> +
> +	cp.handle = cpu_to_le16(conn->handle);
> +	memcpy(cp.ltk, ltk, 16);
> +
> +	hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
> +}
> +EXPORT_SYMBOL(hci_le_start_enc);


This appears only useful for link encryption with the STK, as both the ediv
random values are Zero.  If this is how it was intended, the OK, however
it may be more appropriate in smp.c

> +
> +void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
> +{
> +	struct hci_dev *hdev = conn->hdev;
> +	struct hci_cp_le_ltk_reply cp;
> +
> +	BT_DBG("%p", conn);
> +
> +	memset(&cp, 0, sizeof(cp));
> +
> +	cp.handle = cpu_to_le16(conn->handle);
> +	memcpy(&cp.ltk, ltk, sizeof(ltk));
> +
> +	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
> +}
> +EXPORT_SYMBOL(hci_le_ltk_reply);
> +
> +void hci_le_ltk_neg_reply(struct hci_conn *conn)
> +{
> +	struct hci_dev *hdev = conn->hdev;
> +	struct hci_cp_le_ltk_neg_reply cp;
> +
> +	BT_DBG("%p", conn);
> +
> +	memset(&cp, 0, sizeof(cp));
> +
> +	cp.handle = cpu_to_le16(conn->handle);
> +
> +	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
> +}
> +EXPORT_SYMBOL(hci_le_ltk_neg_reply);
> +
>  /* Device _must_ be locked */
>  void hci_sco_setup(struct hci_conn *conn, __u8 status)
>  {
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 55cdd6a..c90696f 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -559,6 +559,30 @@ static void hci_cc_le_read_buffer_size(struct
> hci_dev *hdev,
>  	hci_req_complete(hdev, rp->status);
>  }
> 
> +static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff
> *skb)
> +{
> +	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
> +
> +	BT_DBG("%s status 0x%x", hdev->name, rp->status);
> +
> +	if (rp->status)
> +		return;
> +
> +	hci_req_complete(hdev, rp->status);
> +}
> +
> +static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct
> sk_buff *skb)
> +{
> +	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
> +
> +	BT_DBG("%s status 0x%x", hdev->name, rp->status);
> +
> +	if (rp->status)
> +		return;
> +
> +	hci_req_complete(hdev, rp->status);
> +}
> +
>  static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
>  {
>  	BT_DBG("%s status 0x%x", hdev->name, status);
> @@ -920,6 +944,11 @@ static void hci_cs_le_create_conn(struct hci_dev
> *hdev, __u8 status)
>  	hci_dev_unlock(hdev);
>  }
> 
> +static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
> +{
> +	BT_DBG("%s status 0x%x", hdev->name, status);
> +}
> +
>  static inline void hci_inquiry_complete_evt(struct hci_dev *hdev,
> struct sk_buff *skb)
>  {
>  	__u8 status = *((__u8 *) skb->data);
> @@ -1440,6 +1469,14 @@ static inline void hci_cmd_complete_evt(struct
> hci_dev *hdev, struct sk_buff *sk
>  		hci_cc_le_read_buffer_size(hdev, skb);
>  		break;
> 
> +	case HCI_OP_LE_LTK_REPLY:
> +		hci_cc_le_ltk_reply(hdev, skb);
> +		break;
> +
> +	case HCI_OP_LE_LTK_NEG_REPLY:
> +		hci_cc_le_ltk_neg_reply(hdev, skb);
> +		break;
> +
>  	default:
>  		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
>  		break;
> @@ -1510,6 +1547,10 @@ static inline void hci_cmd_status_evt(struct
> hci_dev *hdev, struct sk_buff *skb)
>  		hci_cs_le_create_conn(hdev, ev->status);
>  		break;
> 
> +	case HCI_OP_LE_START_ENC:
> +		hci_cs_le_start_enc(hdev, ev->status);
> +		break;
> +
>  	default:
>  		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
>  		break;
> @@ -2013,6 +2054,28 @@ unlock:
>  	hci_dev_unlock(hdev);
>  }
> 
> +static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
> +						struct sk_buff *skb)
> +{
> +	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
> +	struct hci_cp_le_ltk_reply cp;
> +	struct hci_conn *conn;
> +
> +	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
> +
> +	hci_dev_lock(hdev);
> +
> +	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev-
> >handle));
> +
> +	memset(&cp, 0, sizeof(cp));
> +	cp.handle = cpu_to_le16(conn->handle);
> +	memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk));
> +
> +	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
> +
> +	hci_dev_unlock(hdev);
> +}

Same basic problem here, except ediv and random should be checked
for all Zeros, in which case it should be considered an STK request
and rejected unless part of an intended SM Pairing procedure. If
they are not zero, then they are the values that should be used to
look up the LTK for the LTK_REPLY, because the BD ADDR of the remote
device may have changed since the last time it was connected.

> +
>  static inline void hci_le_meta_evt(struct hci_dev *hdev, struct
> sk_buff *skb)
>  {
>  	struct hci_ev_le_meta *le_ev = (void *) skb->data;
> @@ -2024,6 +2087,10 @@ static inline void hci_le_meta_evt(struct
> hci_dev *hdev, struct sk_buff *skb)
>  		hci_le_conn_complete_evt(hdev, skb);
>  		break;
> 
> +	case HCI_EV_LE_LTK_REQ:
> +		hci_le_ltk_request_evt(hdev, skb);
> +		break;
> +
>  	default:
>  		break;
>  	}
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index 7d7e8ad..d19b8a2 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -289,7 +289,8 @@ static void smp_cmd_pairing_confirm(struct
> l2cap_conn *conn, struct sk_buff *skb
> 
>  static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct
> sk_buff *skb)
>  {
> -	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
> +	struct hci_conn *hcon = conn->hcon;
> +	struct crypto_blkcipher *tfm = hcon->hdev->tfm;
>  	int ret;
>  	u8 k[16], key[16], res[16], random[16], confirm[16], buf[128];
> 
> @@ -297,6 +298,7 @@ static void smp_cmd_pairing_random(struct
> l2cap_conn *conn, struct sk_buff *skb)
>  	skb_pull(skb, 16);
> 
>  	memset(k, 0, sizeof(k));
> +	memset(hcon->ltk, 0, sizeof(hcon->ltk));
> 
>  	if (conn->hcon->out)
>  		ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0,
> @@ -320,6 +322,9 @@ static void smp_cmd_pairing_random(struct
> l2cap_conn *conn, struct sk_buff *skb)
> 
>  	if (conn->hcon->out) {
>  		smp_s1(tfm, k, random, conn->prnd, key);
> +		swap128(key, hcon->ltk);
> +
> +		hci_le_start_enc(conn->hcon, hcon->ltk);
> 
>  		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf,
> sizeof(buf), 0);
>  		BT_DBG("key %s", buf);
> @@ -330,6 +335,7 @@ static void smp_cmd_pairing_random(struct
> l2cap_conn *conn, struct sk_buff *skb)
>  		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r);
> 
>  		smp_s1(tfm, k, conn->prnd, random, key);
> +		swap128(key, hcon->ltk);
> 
>  		hex_dump_to_buffer(key, sizeof(key), 16, 1, buf,
> sizeof(buf), 0);
>  		BT_DBG("key %s", buf);
> --
> 1.7.3.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> bluetooth" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux