aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnderson Briglia <anderson.briglia@openbossa.org>2011-06-09 17:50:46 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-06-13 14:48:25 -0400
commit7d24ddcc1140d2f796436e476c8d69469610588b (patch)
treec2bb98242fb3e8e9b441ce92fccfabea3a7bf492
parentf01ead315785768cdb6e928646f90a47640bcdd9 (diff)
Bluetooth: Add SMP confirmation checks methods
This patch includes support for generating and sending the random value used to produce the confirmation value. Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r--include/net/bluetooth/l2cap.h1
-rw-r--r--net/bluetooth/smp.c97
2 files changed, 84 insertions, 14 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index b03d9c4dfc78..01c993b6b263 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -399,6 +399,7 @@ struct l2cap_conn {
399 __u8 prsp[7]; /* SMP Pairing Response */ 399 __u8 prsp[7]; /* SMP Pairing Response */
400 __u8 prnd[16]; /* SMP Pairing Random */ 400 __u8 prnd[16]; /* SMP Pairing Random */
401 __u8 pcnf[16]; /* SMP Pairing Confirm */ 401 __u8 pcnf[16]; /* SMP Pairing Confirm */
402 __u8 tk[16]; /* SMP Temporary Key */
402 403
403 struct list_head chan_l; 404 struct list_head chan_l;
404 rwlock_t chan_lock; 405 rwlock_t chan_lock;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index fa22f4aa3b04..7a9a195c27d3 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -198,6 +198,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
198 rp->resp_key_dist = 0x00; 198 rp->resp_key_dist = 0x00;
199 rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM); 199 rp->auth_req &= (SMP_AUTH_BONDING | SMP_AUTH_MITM);
200 200
201 /* Just works */
202 memset(conn->tk, 0, sizeof(conn->tk));
203
201 conn->prsp[0] = SMP_CMD_PAIRING_RSP; 204 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
202 memcpy(&conn->prsp[1], rp, sizeof(*rp)); 205 memcpy(&conn->prsp[1], rp, sizeof(*rp));
203 206
@@ -208,54 +211,120 @@ static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
208{ 211{
209 struct smp_cmd_pairing *rp = (void *) skb->data; 212 struct smp_cmd_pairing *rp = (void *) skb->data;
210 struct smp_cmd_pairing_confirm cp; 213 struct smp_cmd_pairing_confirm cp;
214 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
215 int ret;
216 u8 res[16];
211 217
212 BT_DBG("conn %p", conn); 218 BT_DBG("conn %p", conn);
213 219
214 memset(&cp, 0, sizeof(cp)); 220 /* Just works */
221 memset(conn->tk, 0, sizeof(conn->tk));
215 222
216 conn->prsp[0] = SMP_CMD_PAIRING_RSP; 223 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
217 memcpy(&conn->prsp[1], rp, sizeof(*rp)); 224 memcpy(&conn->prsp[1], rp, sizeof(*rp));
218 skb_pull(skb, sizeof(*rp)); 225 skb_pull(skb, sizeof(*rp));
219 226
227 ret = smp_rand(conn->prnd);
228 if (ret)
229 return;
230
231 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
232 conn->src, conn->hcon->dst_type, conn->dst, res);
233 if (ret)
234 return;
235
236 swap128(res, cp.confirm_val);
237
220 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); 238 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
221} 239}
222 240
223static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, 241static void smp_cmd_pairing_confirm(struct l2cap_conn *conn,
224 struct sk_buff *skb) 242 struct sk_buff *skb)
225{ 243{
244 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
245
226 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 246 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
227 247
228 if (conn->hcon->out) { 248 memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
229 struct smp_cmd_pairing_random random; 249 skb_pull(skb, sizeof(conn->pcnf));
230 250
231 memset(&random, 0, sizeof(random)); 251 if (conn->hcon->out) {
252 u8 random[16];
232 253
254 swap128(conn->prnd, random);
233 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), 255 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
234 &random); 256 random);
235 } else { 257 } else {
236 struct smp_cmd_pairing_confirm confirm; 258 struct smp_cmd_pairing_confirm cp;
259 int ret;
260 u8 res[16];
237 261
238 memset(&confirm, 0, sizeof(confirm)); 262 ret = smp_rand(conn->prnd);
263 if (ret)
264 return;
239 265
240 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm), 266 ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
241 &confirm); 267 conn->hcon->dst_type, conn->dst,
268 0, conn->src, res);
269 if (ret)
270 return;
271
272 swap128(res, cp.confirm_val);
273
274 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
242 } 275 }
243} 276}
244 277
245static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 278static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
246{ 279{
247 struct smp_cmd_pairing_random cp; 280 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
281 int ret;
282 u8 key[16], res[16], random[16], confirm[16], buf[128];
283
284 swap128(skb->data, random);
285 skb_pull(skb, sizeof(random));
286
287 if (conn->hcon->out)
288 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
289 conn->src, conn->hcon->dst_type, conn->dst,
290 res);
291 else
292 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
293 conn->hcon->dst_type, conn->dst, 0, conn->src,
294 res);
295 if (ret)
296 return;
248 297
249 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); 298 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
250 299
251 skb_pull(skb, sizeof(cp)); 300 swap128(res, confirm);
301
302 if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
303 struct smp_cmd_pairing_fail cp;
304
305 BT_ERR("Pairing failed (confirmation values mismatch)");
306 cp.reason = SMP_CONFIRM_FAILED;
307 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(cp), &cp);
308 return;
309 }
252 310
253 if (conn->hcon->out) { 311 if (conn->hcon->out) {
254 /* FIXME: start encryption */ 312 smp_s1(tfm, conn->tk, random, conn->prnd, key);
313
314 hex_dump_to_buffer(key, sizeof(key), 16, 1, buf,
315 sizeof(buf), 0);
316 BT_DBG("key %s", buf);
255 } else { 317 } else {
256 memset(&cp, 0, sizeof(cp)); 318 u8 r[16];
319
320 swap128(conn->prnd, r);
321 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
322
323 smp_s1(tfm, conn->tk, conn->prnd, random, key);
257 324
258 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp); 325 hex_dump_to_buffer(key, sizeof(key), 16, 1, buf,
326 sizeof(buf), 0);
327 BT_DBG("key %s", buf);
259 } 328 }
260} 329}
261 330