Skip to content

Commit

Permalink
Bluetooth: Add SMP confirmation checks methods
Browse files Browse the repository at this point in the history
This patch includes support for generating and sending the random value
used to produce the confirmation value.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
  • Loading branch information
Anderson Briglia authored and Gustavo F. Padovan committed Jun 13, 2011
1 parent f01ead3 commit 7d24ddc
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 14 deletions.
1 change: 1 addition & 0 deletions include/net/bluetooth/l2cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ struct l2cap_conn {
__u8 prsp[7]; /* SMP Pairing Response */
__u8 prnd[16]; /* SMP Pairing Random */
__u8 pcnf[16]; /* SMP Pairing Confirm */
__u8 tk[16]; /* SMP Temporary Key */

struct list_head chan_l;
rwlock_t chan_lock;
Expand Down
97 changes: 83 additions & 14 deletions net/bluetooth/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
rp->resp_key_dist = 0x00;
rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);

/* Just works */
memset(conn->tk, 0, sizeof(conn->tk));

conn->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&conn->prsp[1], rp, sizeof(*rp));

Expand All @@ -208,54 +211,120 @@ static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing *rp = (void *) skb->data;
struct smp_cmd_pairing_confirm cp;
struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
int ret;
u8 res[16];

BT_DBG("conn %p", conn);

memset(&cp, 0, sizeof(cp));
/* Just works */
memset(conn->tk, 0, sizeof(conn->tk));

conn->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&conn->prsp[1], rp, sizeof(*rp));
skb_pull(skb, sizeof(*rp));

ret = smp_rand(conn->prnd);
if (ret)
return;

ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
conn->src, conn->hcon->dst_type, conn->dst, res);
if (ret)
return;

swap128(res, cp.confirm_val);

smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
}

static void smp_cmd_pairing_confirm(struct l2cap_conn *conn,
struct sk_buff *skb)
{
struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;

BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");

if (conn->hcon->out) {
struct smp_cmd_pairing_random random;
memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
skb_pull(skb, sizeof(conn->pcnf));

memset(&random, 0, sizeof(random));
if (conn->hcon->out) {
u8 random[16];

swap128(conn->prnd, random);
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
&random);
random);
} else {
struct smp_cmd_pairing_confirm confirm;
struct smp_cmd_pairing_confirm cp;
int ret;
u8 res[16];

memset(&confirm, 0, sizeof(confirm));
ret = smp_rand(conn->prnd);
if (ret)
return;

smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
&confirm);
ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
conn->hcon->dst_type, conn->dst,
0, conn->src, res);
if (ret)
return;

swap128(res, cp.confirm_val);

smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
}
}

static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing_random cp;
struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
int ret;
u8 key[16], res[16], random[16], confirm[16], buf[128];

swap128(skb->data, random);
skb_pull(skb, sizeof(random));

if (conn->hcon->out)
ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
conn->src, conn->hcon->dst_type, conn->dst,
res);
else
ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
conn->hcon->dst_type, conn->dst, 0, conn->src,
res);
if (ret)
return;

BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");

skb_pull(skb, sizeof(cp));
swap128(res, confirm);

if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
struct smp_cmd_pairing_fail cp;

BT_ERR("Pairing failed (confirmation values mismatch)");
cp.reason = SMP_CONFIRM_FAILED;
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(cp), &cp);
return;
}

if (conn->hcon->out) {
/* FIXME: start encryption */
smp_s1(tfm, conn->tk, random, conn->prnd, key);

hex_dump_to_buffer(key, sizeof(key), 16, 1, buf,
sizeof(buf), 0);
BT_DBG("key %s", buf);
} else {
memset(&cp, 0, sizeof(cp));
u8 r[16];

swap128(conn->prnd, r);
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);

smp_s1(tfm, conn->tk, conn->prnd, random, key);

smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf,
sizeof(buf), 0);
BT_DBG("key %s", buf);
}
}

Expand Down

0 comments on commit 7d24ddc

Please sign in to comment.