Commit 7d24ddcc authored by Anderson Briglia's avatar Anderson Briglia Committed by Gustavo F. Padovan

Bluetooth: Add SMP confirmation checks methods

This patch includes support for generating and sending the random value
used to produce the confirmation value.
Signed-off-by: default avatarAnderson Briglia <anderson.briglia@openbossa.org>
Signed-off-by: default avatarVinicius Costa Gomes <vinicius.gomes@openbossa.org>
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent f01ead31
...@@ -399,6 +399,7 @@ struct l2cap_conn { ...@@ -399,6 +399,7 @@ struct l2cap_conn {
__u8 prsp[7]; /* SMP Pairing Response */ __u8 prsp[7]; /* SMP Pairing Response */
__u8 prnd[16]; /* SMP Pairing Random */ __u8 prnd[16]; /* SMP Pairing Random */
__u8 pcnf[16]; /* SMP Pairing Confirm */ __u8 pcnf[16]; /* SMP Pairing Confirm */
__u8 tk[16]; /* SMP Temporary Key */
struct list_head chan_l; struct list_head chan_l;
rwlock_t chan_lock; rwlock_t chan_lock;
......
...@@ -198,6 +198,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -198,6 +198,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
rp->resp_key_dist = 0x00; rp->resp_key_dist = 0x00;
rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM); 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; conn->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&conn->prsp[1], rp, sizeof(*rp)); memcpy(&conn->prsp[1], rp, sizeof(*rp));
...@@ -208,54 +211,120 @@ static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -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 *rp = (void *) skb->data;
struct smp_cmd_pairing_confirm cp; struct smp_cmd_pairing_confirm cp;
struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
int ret;
u8 res[16];
BT_DBG("conn %p", conn); 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; conn->prsp[0] = SMP_CMD_PAIRING_RSP;
memcpy(&conn->prsp[1], rp, sizeof(*rp)); memcpy(&conn->prsp[1], rp, sizeof(*rp));
skb_pull(skb, 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); smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
} }
static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, static void smp_cmd_pairing_confirm(struct l2cap_conn *conn,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
if (conn->hcon->out) { memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
struct smp_cmd_pairing_random random; 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), smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
&random); random);
} else { } 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), ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
&confirm); 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) 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"); 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) { 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 { } 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);
} }
} }
......
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