Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 256406
b: refs/heads/master
c: 7034b91
h: refs/heads/master
v: v3
  • Loading branch information
Vinicius Costa Gomes authored and Gustavo F. Padovan committed Jul 8, 2011
1 parent 8909b97 commit 367acb2
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fadd192e81b0a8d8086531b8c11bd88b311b68c2
refs/heads/master: 7034b911af1aa571995b56db3ed71a25daf00373
1 change: 1 addition & 0 deletions trunk/include/net/bluetooth/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,6 @@ struct smp_cmd_security_req {
/* SMP Commands */
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);

#endif /* __SMP_H */
1 change: 1 addition & 0 deletions trunk/net/bluetooth/l2cap_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4103,6 +4103,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
chan->sec_level = hcon->sec_level;
del_timer(&conn->security_timer);
l2cap_chan_ready(sk);
smp_distribute_keys(conn, 0);
}

bh_unlock_sock(sk);
Expand Down
114 changes: 112 additions & 2 deletions trunk/net/bluetooth/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
cmd->io_capability = conn->hcon->io_capability;
cmd->oob_flag = SMP_OOB_NOT_PRESENT;
cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
cmd->init_key_dist = 0x00;
cmd->resp_key_dist = 0x00;
cmd->init_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
cmd->resp_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
cmd->auth_req = authreq;
}

Expand Down Expand Up @@ -474,6 +474,26 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
return 0;
}

static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
{
BT_DBG("conn %p", conn);
/* FIXME: store the ltk */
return 0;
}

static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing *paircmd = (void *) &conn->prsp[1];
u8 keydist = paircmd->init_key_dist;

BT_DBG("keydist 0x%x", keydist);
/* FIXME: store ediv and rand */

smp_distribute_keys(conn, 1);

return 0;
}

int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
{
__u8 code = skb->data[0];
Expand Down Expand Up @@ -521,10 +541,20 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
break;

case SMP_CMD_ENCRYPT_INFO:
reason = smp_cmd_encrypt_info(conn, skb);
break;

case SMP_CMD_MASTER_IDENT:
reason = smp_cmd_master_ident(conn, skb);
break;

case SMP_CMD_IDENT_INFO:
case SMP_CMD_IDENT_ADDR_INFO:
case SMP_CMD_SIGN_INFO:
/* Just ignored */
reason = 0;
break;

default:
BT_DBG("Unknown command code 0x%2.2x", code);

Expand All @@ -541,3 +571,83 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
kfree_skb(skb);
return err;
}

int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
{
struct smp_cmd_pairing *req, *rsp;
__u8 *keydist;

BT_DBG("conn %p force %d", conn, force);

if (IS_ERR(conn->hcon->hdev->tfm))
return PTR_ERR(conn->hcon->hdev->tfm);

rsp = (void *) &conn->prsp[1];

/* The responder sends its keys first */
if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
return 0;

req = (void *) &conn->preq[1];

if (conn->hcon->out) {
keydist = &rsp->init_key_dist;
*keydist &= req->init_key_dist;
} else {
keydist = &rsp->resp_key_dist;
*keydist &= req->resp_key_dist;
}


BT_DBG("keydist 0x%x", *keydist);

if (*keydist & SMP_DIST_ENC_KEY) {
struct smp_cmd_encrypt_info enc;
struct smp_cmd_master_ident ident;
__le16 ediv;

get_random_bytes(enc.ltk, sizeof(enc.ltk));
get_random_bytes(&ediv, sizeof(ediv));
get_random_bytes(ident.rand, sizeof(ident.rand));

smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);

ident.ediv = cpu_to_le16(ediv);

smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);

*keydist &= ~SMP_DIST_ENC_KEY;
}

if (*keydist & SMP_DIST_ID_KEY) {
struct smp_cmd_ident_addr_info addrinfo;
struct smp_cmd_ident_info idinfo;

/* Send a dummy key */
get_random_bytes(idinfo.irk, sizeof(idinfo.irk));

smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);

/* Just public address */
memset(&addrinfo, 0, sizeof(addrinfo));
bacpy(&addrinfo.bdaddr, conn->src);

smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
&addrinfo);

*keydist &= ~SMP_DIST_ID_KEY;
}

if (*keydist & SMP_DIST_SIGN) {
struct smp_cmd_sign_info sign;

/* Send a dummy key */
get_random_bytes(sign.csrk, sizeof(sign.csrk));

smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);

*keydist &= ~SMP_DIST_SIGN;
}

return 0;
}

0 comments on commit 367acb2

Please sign in to comment.