aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorVinicius Costa Gomes <vinicius.gomes@openbossa.org>2011-07-07 17:59:38 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-07-08 16:37:02 -0400
commit54790f73a3ec87c181e4d6e5eb6963de3d50ebd7 (patch)
treecf980caec48ba49e4c9681149d51e6beac0916d6 /net/bluetooth
parentbea710feff617e3469789dd8f930b284c83a87f5 (diff)
Bluetooth: Fix SM pairing parameters negotiation
Before implementing SM key distribution, the pairing features exchange must be better negotiated, taking into account some features of the host and connection requirements. If we are in the "not pairable" state, it makes no sense to exchange any key. This allows for simplification of the key negociation method. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/smp.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 82443b95f24e..ffbfdd9e5738 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -197,14 +197,34 @@ static __u8 seclevel_to_authreq(__u8 level)
197} 197}
198 198
199static void build_pairing_cmd(struct l2cap_conn *conn, 199static void build_pairing_cmd(struct l2cap_conn *conn,
200 struct smp_cmd_pairing *cmd, __u8 authreq) 200 struct smp_cmd_pairing *req,
201 struct smp_cmd_pairing *rsp,
202 __u8 authreq)
201{ 203{
202 cmd->io_capability = conn->hcon->io_capability; 204 u8 dist_keys;
203 cmd->oob_flag = SMP_OOB_NOT_PRESENT; 205
204 cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE; 206 dist_keys = 0;
205 cmd->init_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN; 207 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
206 cmd->resp_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN; 208 dist_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
207 cmd->auth_req = authreq; 209 authreq |= SMP_AUTH_BONDING;
210 }
211
212 if (rsp == NULL) {
213 req->io_capability = conn->hcon->io_capability;
214 req->oob_flag = SMP_OOB_NOT_PRESENT;
215 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
216 req->init_key_dist = dist_keys;
217 req->resp_key_dist = dist_keys;
218 req->auth_req = authreq;
219 return;
220 }
221
222 rsp->io_capability = conn->hcon->io_capability;
223 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
224 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
225 rsp->init_key_dist = req->init_key_dist & dist_keys;
226 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
227 rsp->auth_req = authreq;
208} 228}
209 229
210static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) 230static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
@@ -233,7 +253,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
233 return SMP_OOB_NOT_AVAIL; 253 return SMP_OOB_NOT_AVAIL;
234 254
235 /* We didn't start the pairing, so no requirements */ 255 /* We didn't start the pairing, so no requirements */
236 build_pairing_cmd(conn, &rsp, SMP_AUTH_NONE); 256 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
237 257
238 key_size = min(req->max_key_size, rsp.max_key_size); 258 key_size = min(req->max_key_size, rsp.max_key_size);
239 if (check_enc_key_size(conn, key_size)) 259 if (check_enc_key_size(conn, key_size))
@@ -412,7 +432,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
412 skb_pull(skb, sizeof(*rp)); 432 skb_pull(skb, sizeof(*rp));
413 433
414 memset(&cp, 0, sizeof(cp)); 434 memset(&cp, 0, sizeof(cp));
415 build_pairing_cmd(conn, &cp, rp->auth_req); 435 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
416 436
417 conn->preq[0] = SMP_CMD_PAIRING_REQ; 437 conn->preq[0] = SMP_CMD_PAIRING_REQ;
418 memcpy(&conn->preq[1], &cp, sizeof(cp)); 438 memcpy(&conn->preq[1], &cp, sizeof(cp));
@@ -454,7 +474,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
454 if (hcon->link_mode & HCI_LM_MASTER) { 474 if (hcon->link_mode & HCI_LM_MASTER) {
455 struct smp_cmd_pairing cp; 475 struct smp_cmd_pairing cp;
456 476
457 build_pairing_cmd(conn, &cp, authreq); 477 build_pairing_cmd(conn, &cp, NULL, authreq);
458 conn->preq[0] = SMP_CMD_PAIRING_REQ; 478 conn->preq[0] = SMP_CMD_PAIRING_REQ;
459 memcpy(&conn->preq[1], &cp, sizeof(cp)); 479 memcpy(&conn->preq[1], &cp, sizeof(cp));
460 480