aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/smp.c
diff options
context:
space:
mode:
authorVinicius Costa Gomes <vinicius.gomes@openbossa.org>2011-07-07 17:59:34 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-07-08 16:07:43 -0400
commit7034b911af1aa571995b56db3ed71a25daf00373 (patch)
tree89325f75fef679c8d6657ee6d971aa36823cc962 /net/bluetooth/smp.c
parentfadd192e81b0a8d8086531b8c11bd88b311b68c2 (diff)
Bluetooth: Add support for SMP phase 3 (key distribution)
This adds support for generating and distributing all the keys specified in the third phase of SMP. This will make possible to re-establish secure connections, resolve private addresses and sign commands. For now, the values generated are random. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r--net/bluetooth/smp.c114
1 files changed, 112 insertions, 2 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index ba55bd4b5dda..82443b95f24e 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -202,8 +202,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
202 cmd->io_capability = conn->hcon->io_capability; 202 cmd->io_capability = conn->hcon->io_capability;
203 cmd->oob_flag = SMP_OOB_NOT_PRESENT; 203 cmd->oob_flag = SMP_OOB_NOT_PRESENT;
204 cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE; 204 cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
205 cmd->init_key_dist = 0x00; 205 cmd->init_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
206 cmd->resp_key_dist = 0x00; 206 cmd->resp_key_dist = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
207 cmd->auth_req = authreq; 207 cmd->auth_req = authreq;
208} 208}
209 209
@@ -474,6 +474,26 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
474 return 0; 474 return 0;
475} 475}
476 476
477static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
478{
479 BT_DBG("conn %p", conn);
480 /* FIXME: store the ltk */
481 return 0;
482}
483
484static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
485{
486 struct smp_cmd_pairing *paircmd = (void *) &conn->prsp[1];
487 u8 keydist = paircmd->init_key_dist;
488
489 BT_DBG("keydist 0x%x", keydist);
490 /* FIXME: store ediv and rand */
491
492 smp_distribute_keys(conn, 1);
493
494 return 0;
495}
496
477int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 497int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
478{ 498{
479 __u8 code = skb->data[0]; 499 __u8 code = skb->data[0];
@@ -521,10 +541,20 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
521 break; 541 break;
522 542
523 case SMP_CMD_ENCRYPT_INFO: 543 case SMP_CMD_ENCRYPT_INFO:
544 reason = smp_cmd_encrypt_info(conn, skb);
545 break;
546
524 case SMP_CMD_MASTER_IDENT: 547 case SMP_CMD_MASTER_IDENT:
548 reason = smp_cmd_master_ident(conn, skb);
549 break;
550
525 case SMP_CMD_IDENT_INFO: 551 case SMP_CMD_IDENT_INFO:
526 case SMP_CMD_IDENT_ADDR_INFO: 552 case SMP_CMD_IDENT_ADDR_INFO:
527 case SMP_CMD_SIGN_INFO: 553 case SMP_CMD_SIGN_INFO:
554 /* Just ignored */
555 reason = 0;
556 break;
557
528 default: 558 default:
529 BT_DBG("Unknown command code 0x%2.2x", code); 559 BT_DBG("Unknown command code 0x%2.2x", code);
530 560
@@ -541,3 +571,83 @@ done:
541 kfree_skb(skb); 571 kfree_skb(skb);
542 return err; 572 return err;
543} 573}
574
575int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
576{
577 struct smp_cmd_pairing *req, *rsp;
578 __u8 *keydist;
579
580 BT_DBG("conn %p force %d", conn, force);
581
582 if (IS_ERR(conn->hcon->hdev->tfm))
583 return PTR_ERR(conn->hcon->hdev->tfm);
584
585 rsp = (void *) &conn->prsp[1];
586
587 /* The responder sends its keys first */
588 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
589 return 0;
590
591 req = (void *) &conn->preq[1];
592
593 if (conn->hcon->out) {
594 keydist = &rsp->init_key_dist;
595 *keydist &= req->init_key_dist;
596 } else {
597 keydist = &rsp->resp_key_dist;
598 *keydist &= req->resp_key_dist;
599 }
600
601
602 BT_DBG("keydist 0x%x", *keydist);
603
604 if (*keydist & SMP_DIST_ENC_KEY) {
605 struct smp_cmd_encrypt_info enc;
606 struct smp_cmd_master_ident ident;
607 __le16 ediv;
608
609 get_random_bytes(enc.ltk, sizeof(enc.ltk));
610 get_random_bytes(&ediv, sizeof(ediv));
611 get_random_bytes(ident.rand, sizeof(ident.rand));
612
613 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
614
615 ident.ediv = cpu_to_le16(ediv);
616
617 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
618
619 *keydist &= ~SMP_DIST_ENC_KEY;
620 }
621
622 if (*keydist & SMP_DIST_ID_KEY) {
623 struct smp_cmd_ident_addr_info addrinfo;
624 struct smp_cmd_ident_info idinfo;
625
626 /* Send a dummy key */
627 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
628
629 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
630
631 /* Just public address */
632 memset(&addrinfo, 0, sizeof(addrinfo));
633 bacpy(&addrinfo.bdaddr, conn->src);
634
635 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
636 &addrinfo);
637
638 *keydist &= ~SMP_DIST_ID_KEY;
639 }
640
641 if (*keydist & SMP_DIST_SIGN) {
642 struct smp_cmd_sign_info sign;
643
644 /* Send a dummy key */
645 get_random_bytes(sign.csrk, sizeof(sign.csrk));
646
647 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
648
649 *keydist &= ~SMP_DIST_SIGN;
650 }
651
652 return 0;
653}