diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/smp.c | 40 |
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 | ||
199 | static void build_pairing_cmd(struct l2cap_conn *conn, | 199 | static 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 | ||
210 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) | 230 | static 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 | ||