Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142
Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 391888b..e1c4ef3 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -25,7 +25,6 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/smp.h>
#include <linux/crypto.h>
-#include <linux/scatterlist.h>
#include <crypto/b128ops.h>
#define SMP_TIMEOUT 30000 /* 30 seconds */
@@ -146,7 +145,7 @@
}
static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
- u16 dlen, void *data)
+ u16 dlen, void *data)
{
struct sk_buff *skb;
struct l2cap_hdr *lh;
@@ -181,7 +180,7 @@
if (!skb)
return;
- hci_send_acl(conn->hcon, skb, 0);
+ hci_send_acl(conn->hcon, NULL, skb, 0);
}
static __u8 seclevel_to_authreq(__u8 level)
@@ -201,11 +200,12 @@
struct smp_cmd_pairing *rsp,
__u8 authreq)
{
+ u8 all_keys = 0;
u8 dist_keys;
dist_keys = 0;
if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
- dist_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
+ dist_keys = SMP_DIST_ENC_KEY;
authreq |= SMP_AUTH_BONDING;
}
@@ -214,7 +214,7 @@
req->oob_flag = SMP_OOB_NOT_PRESENT;
req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
req->init_key_dist = dist_keys;
- req->resp_key_dist = dist_keys;
+ req->resp_key_dist = all_keys;
req->auth_req = authreq;
return;
}
@@ -222,7 +222,7 @@
rsp->io_capability = conn->hcon->io_capability;
rsp->oob_flag = SMP_OOB_NOT_PRESENT;
rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
- rsp->init_key_dist = req->init_key_dist & dist_keys;
+ rsp->init_key_dist = req->init_key_dist & all_keys;
rsp->resp_key_dist = req->resp_key_dist & dist_keys;
rsp->auth_req = authreq;
}
@@ -461,29 +461,25 @@
BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
- if (!lmp_host_le_capable(hcon->hdev))
- return 1;
-
if (IS_ERR(hcon->hdev->tfm))
return 1;
if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
- return 0;
+ return -EINPROGRESS;
if (sec_level == BT_SECURITY_LOW)
return 1;
- if (hcon->sec_level >= sec_level)
+ if (hcon->sec_level > sec_level)
return 1;
authreq = seclevel_to_authreq(sec_level);
if (hcon->link_mode & HCI_LM_MASTER) {
- struct smp_cmd_pairing cp;
struct link_key *key;
key = hci_find_link_key_type(hcon->hdev, conn->dst,
- HCI_LK_SMP_LTK);
+ KEY_TYPE_LTK);
if (key) {
struct key_master_id *master = (void *) key->data;
@@ -493,6 +489,10 @@
goto done;
}
+ }
+
+ if (hcon->link_mode & HCI_LM_MASTER) {
+ struct smp_cmd_pairing cp;
build_pairing_cmd(conn, &cp, NULL, authreq);
conn->preq[0] = SMP_CMD_PAIRING_REQ;
@@ -518,10 +518,18 @@
static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_encrypt_info *rp = (void *) skb->data;
+ u8 rand[8];
+ int err;
skb_pull(skb, sizeof(*rp));
- memcpy(conn->tk, rp->ltk, sizeof(conn->tk));
+ BT_DBG("conn %p", conn);
+
+ memset(rand, 0, sizeof(rand));
+
+ err = hci_add_ltk(conn->hcon->hdev, 0, conn->dst, 0, 0, rand, rp->ltk);
+ if (err)
+ return SMP_UNSPECIFIED;
return 0;
}
@@ -529,11 +537,25 @@
static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_master_ident *rp = (void *) skb->data;
+ struct smp_cmd_pairing *paircmd = (void *) &conn->prsp[1];
+ struct link_key *key;
+ struct key_master_id *id;
+ u8 keydist = paircmd->init_key_dist;
skb_pull(skb, sizeof(*rp));
+ key = hci_find_link_key_type(conn->hcon->hdev, conn->dst, KEY_TYPE_LTK);
+ if (key == NULL)
+ return SMP_UNSPECIFIED;
+
+ BT_DBG("keydist 0x%x", keydist);
+
+ id = (void *) key->data;
+ id->ediv = rp->ediv;
+ memcpy(id->rand, rp->rand, sizeof(rp->rand));
+
hci_add_ltk(conn->hcon->hdev, 1, conn->src, conn->smp_key_size,
- rp->ediv, rp->rand, conn->tk);
+ rp->ediv, rp->rand, key->val);
smp_distribute_keys(conn, 1);
@@ -546,12 +568,6 @@
__u8 reason;
int err = 0;
- if (!lmp_host_le_capable(conn->hcon->hdev)) {
- err = -ENOTSUPP;
- reason = SMP_PAIRING_NOTSUPP;
- goto done;
- }
-
if (IS_ERR(conn->hcon->hdev->tfm)) {
err = PTR_ERR(conn->hcon->hdev->tfm);
reason = SMP_PAIRING_NOTSUPP;