aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-03-09 15:19:17 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2014-03-09 15:39:50 -0400
commit7ee4ea3692f20b87b0e0d3884d5b2d22ec1a2df0 (patch)
tree8e3cb5d8a34f9daeb19a97b7d6147d3955b501b1 /net
parent0753c182ef11e27f8f3dea2dc9ca4bcf40019eb5 (diff)
Bluetooth: Add support for handling signature resolving keys
The connection signature resolving key (CSRK) is used for attribute protocol signed write procedures. This change generates a new local key during pairing and requests the peer key as well. Newly generated key and received key will be provided to userspace using the New Signature Resolving Key management event. The Master CSRK can be used for verification of remote signed write PDUs and the Slave CSRK can be used for sending signed write PDUs to the remote device. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/mgmt.c30
-rw-r--r--net/bluetooth/smp.c67
-rw-r--r--net/bluetooth/smp.h2
3 files changed, 94 insertions, 5 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index f2397e7ad385..9c7788914b4e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -108,6 +108,7 @@ static const u16 mgmt_events[] = {
108 MGMT_EV_DEVICE_UNPAIRED, 108 MGMT_EV_DEVICE_UNPAIRED,
109 MGMT_EV_PASSKEY_NOTIFY, 109 MGMT_EV_PASSKEY_NOTIFY,
110 MGMT_EV_NEW_IRK, 110 MGMT_EV_NEW_IRK,
111 MGMT_EV_NEW_CSRK,
111}; 112};
112 113
113#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) 114#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
@@ -5072,6 +5073,35 @@ void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5072 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL); 5073 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5073} 5074}
5074 5075
5076void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk)
5077{
5078 struct mgmt_ev_new_csrk ev;
5079
5080 memset(&ev, 0, sizeof(ev));
5081
5082 /* Devices using resolvable or non-resolvable random addresses
5083 * without providing an indentity resolving key don't require
5084 * to store signature resolving keys. Their addresses will change
5085 * the next time around.
5086 *
5087 * Only when a remote device provides an identity address
5088 * make sure the signature resolving key is stored. So allow
5089 * static random and public addresses here.
5090 */
5091 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5092 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5093 ev.store_hint = 0x00;
5094 else
5095 ev.store_hint = 0x01;
5096
5097 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5098 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5099 ev.key.master = csrk->master;
5100 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5101
5102 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5103}
5104
5075static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, 5105static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5076 u8 data_len) 5106 u8 data_len)
5077{ 5107{
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index f886bcae1b7e..fc652592daf6 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -273,8 +273,8 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
273 u8 local_dist = 0, remote_dist = 0; 273 u8 local_dist = 0, remote_dist = 0;
274 274
275 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { 275 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
276 local_dist = SMP_DIST_ENC_KEY; 276 local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
277 remote_dist = SMP_DIST_ENC_KEY; 277 remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
278 authreq |= SMP_AUTH_BONDING; 278 authreq |= SMP_AUTH_BONDING;
279 } else { 279 } else {
280 authreq &= ~SMP_AUTH_BONDING; 280 authreq &= ~SMP_AUTH_BONDING;
@@ -596,6 +596,9 @@ void smp_chan_destroy(struct l2cap_conn *conn)
596 complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags); 596 complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
597 mgmt_smp_complete(conn->hcon, complete); 597 mgmt_smp_complete(conn->hcon, complete);
598 598
599 kfree(smp->csrk);
600 kfree(smp->slave_csrk);
601
599 /* If pairing failed clean up any keys we might have */ 602 /* If pairing failed clean up any keys we might have */
600 if (!complete) { 603 if (!complete) {
601 if (smp->ltk) { 604 if (smp->ltk) {
@@ -1065,6 +1068,41 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
1065 return 0; 1068 return 0;
1066} 1069}
1067 1070
1071static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
1072{
1073 struct smp_cmd_sign_info *rp = (void *) skb->data;
1074 struct smp_chan *smp = conn->smp_chan;
1075 struct hci_dev *hdev = conn->hcon->hdev;
1076 struct smp_csrk *csrk;
1077
1078 BT_DBG("conn %p", conn);
1079
1080 if (skb->len < sizeof(*rp))
1081 return SMP_UNSPECIFIED;
1082
1083 /* Ignore this PDU if it wasn't requested */
1084 if (!(smp->remote_key_dist & SMP_DIST_SIGN))
1085 return 0;
1086
1087 /* Mark the information as received */
1088 smp->remote_key_dist &= ~SMP_DIST_SIGN;
1089
1090 skb_pull(skb, sizeof(*rp));
1091
1092 hci_dev_lock(hdev);
1093 csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
1094 if (csrk) {
1095 csrk->master = 0x01;
1096 memcpy(csrk->val, rp->csrk, sizeof(csrk->val));
1097 }
1098 smp->csrk = csrk;
1099 if (!(smp->remote_key_dist & SMP_DIST_SIGN))
1100 smp_distribute_keys(conn);
1101 hci_dev_unlock(hdev);
1102
1103 return 0;
1104}
1105
1068int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 1106int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
1069{ 1107{
1070 struct hci_conn *hcon = conn->hcon; 1108 struct hci_conn *hcon = conn->hcon;
@@ -1147,8 +1185,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
1147 break; 1185 break;
1148 1186
1149 case SMP_CMD_SIGN_INFO: 1187 case SMP_CMD_SIGN_INFO:
1150 /* Just ignored */ 1188 reason = smp_cmd_sign_info(conn, skb);
1151 reason = 0;
1152 break; 1189 break;
1153 1190
1154 default: 1191 default:
@@ -1176,6 +1213,18 @@ static void smp_notify_keys(struct l2cap_conn *conn)
1176 if (smp->remote_irk) 1213 if (smp->remote_irk)
1177 mgmt_new_irk(hdev, smp->remote_irk); 1214 mgmt_new_irk(hdev, smp->remote_irk);
1178 1215
1216 if (smp->csrk) {
1217 smp->csrk->bdaddr_type = hcon->dst_type;
1218 bacpy(&smp->csrk->bdaddr, &hcon->dst);
1219 mgmt_new_csrk(hdev, smp->csrk);
1220 }
1221
1222 if (smp->slave_csrk) {
1223 smp->slave_csrk->bdaddr_type = hcon->dst_type;
1224 bacpy(&smp->slave_csrk->bdaddr, &hcon->dst);
1225 mgmt_new_csrk(hdev, smp->slave_csrk);
1226 }
1227
1179 if (smp->ltk) { 1228 if (smp->ltk) {
1180 smp->ltk->bdaddr_type = hcon->dst_type; 1229 smp->ltk->bdaddr_type = hcon->dst_type;
1181 bacpy(&smp->ltk->bdaddr, &hcon->dst); 1230 bacpy(&smp->ltk->bdaddr, &hcon->dst);
@@ -1274,10 +1323,18 @@ int smp_distribute_keys(struct l2cap_conn *conn)
1274 1323
1275 if (*keydist & SMP_DIST_SIGN) { 1324 if (*keydist & SMP_DIST_SIGN) {
1276 struct smp_cmd_sign_info sign; 1325 struct smp_cmd_sign_info sign;
1326 struct smp_csrk *csrk;
1277 1327
1278 /* Send a dummy key */ 1328 /* Generate a new random key */
1279 get_random_bytes(sign.csrk, sizeof(sign.csrk)); 1329 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1280 1330
1331 csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
1332 if (csrk) {
1333 csrk->master = 0x00;
1334 memcpy(csrk->val, sign.csrk, sizeof(csrk->val));
1335 }
1336 smp->slave_csrk = csrk;
1337
1281 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); 1338 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1282 1339
1283 *keydist &= ~SMP_DIST_SIGN; 1340 *keydist &= ~SMP_DIST_SIGN;
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index f55d83617218..f223b9d38b61 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -136,6 +136,8 @@ struct smp_chan {
136 bdaddr_t id_addr; 136 bdaddr_t id_addr;
137 u8 id_addr_type; 137 u8 id_addr_type;
138 u8 irk[16]; 138 u8 irk[16];
139 struct smp_csrk *csrk;
140 struct smp_csrk *slave_csrk;
139 struct smp_ltk *ltk; 141 struct smp_ltk *ltk;
140 struct smp_ltk *slave_ltk; 142 struct smp_ltk *slave_ltk;
141 struct smp_irk *remote_irk; 143 struct smp_irk *remote_irk;