aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_conn.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-01-15 15:58:04 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 00:14:25 -0500
commit8c1b235594fbab9a13240a1dac12ea9fd99b6440 (patch)
treeeb137a23e0fd8199144a4c3e36902af411e44269 /net/bluetooth/hci_conn.c
parentc89b6e6bda4c8021195778f47567d0cc9dbfe7ec (diff)
Bluetooth: Add enhanced security model for Simple Pairing
The current security model is based around the flags AUTH, ENCRYPT and SECURE. Starting with support for the Bluetooth 2.1 specification this is no longer sufficient. The different security levels are now defined as SDP, LOW, MEDIUM and SECURE. Previously it was possible to set each security independently, but this actually doesn't make a lot of sense. For Bluetooth the encryption depends on a previous successful authentication. Also you can only update your existing link key if you successfully created at least one before. And of course the update of link keys without having proper encryption in place is a security issue. The new security levels from the Bluetooth 2.1 specification are now used internally. All old settings are mapped to the new values and this way it ensures that old applications still work. The only limitation is that it is no longer possible to set authentication without also enabling encryption. No application should have done this anyway since this is actually a security issue. Without encryption the integrity of the authentication can't be guaranteed. As default for a new L2CAP or RFCOMM connection, the LOW security level is used. The only exception here are the service discovery sessions on PSM 1 where SDP level is used. To have similar security strength as with a Bluetooth 2.0 and before combination key, the MEDIUM level should be used. This is according to the Bluetooth specification. The MEDIUM level will not require any kind of man-in-the-middle (MITM) protection. Only the HIGH security level will require this. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r--net/bluetooth/hci_conn.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index a4a789f24c8d..98f97a1e9bbb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -325,7 +325,7 @@ EXPORT_SYMBOL(hci_get_route);
325 325
326/* Create SCO or ACL connection. 326/* Create SCO or ACL connection.
327 * Device _must_ be locked */ 327 * Device _must_ be locked */
328struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type) 328struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
329{ 329{
330 struct hci_conn *acl; 330 struct hci_conn *acl;
331 struct hci_conn *sco; 331 struct hci_conn *sco;
@@ -340,6 +340,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
340 hci_conn_hold(acl); 340 hci_conn_hold(acl);
341 341
342 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { 342 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
343 acl->sec_level = sec_level;
343 acl->auth_type = auth_type; 344 acl->auth_type = auth_type;
344 hci_acl_connect(acl); 345 hci_acl_connect(acl);
345 } 346 }
@@ -385,16 +386,17 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
385EXPORT_SYMBOL(hci_conn_check_link_mode); 386EXPORT_SYMBOL(hci_conn_check_link_mode);
386 387
387/* Authenticate remote device */ 388/* Authenticate remote device */
388int hci_conn_auth(struct hci_conn *conn) 389static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level)
389{ 390{
390 BT_DBG("conn %p", conn); 391 BT_DBG("conn %p", conn);
391 392
392 if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { 393 if (sec_level > conn->sec_level)
393 if (!(conn->auth_type & 0x01)) { 394 conn->link_mode &= ~HCI_LM_AUTH;
394 conn->auth_type |= 0x01; 395
395 conn->link_mode &= ~HCI_LM_AUTH; 396 conn->sec_level = sec_level;
396 } 397
397 } 398 if (sec_level == BT_SECURITY_HIGH)
399 conn->auth_type |= 0x01;
398 400
399 if (conn->link_mode & HCI_LM_AUTH) 401 if (conn->link_mode & HCI_LM_AUTH)
400 return 1; 402 return 1;
@@ -405,31 +407,42 @@ int hci_conn_auth(struct hci_conn *conn)
405 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, 407 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
406 sizeof(cp), &cp); 408 sizeof(cp), &cp);
407 } 409 }
410
408 return 0; 411 return 0;
409} 412}
410EXPORT_SYMBOL(hci_conn_auth);
411 413
412/* Enable encryption */ 414/* Enable security */
413int hci_conn_encrypt(struct hci_conn *conn) 415int hci_conn_security(struct hci_conn *conn, __u8 sec_level)
414{ 416{
415 BT_DBG("conn %p", conn); 417 BT_DBG("conn %p", conn);
416 418
419 if (sec_level == BT_SECURITY_SDP)
420 return 1;
421
422 if (sec_level == BT_SECURITY_LOW) {
423 if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0)
424 return hci_conn_auth(conn, sec_level);
425 else
426 return 1;
427 }
428
417 if (conn->link_mode & HCI_LM_ENCRYPT) 429 if (conn->link_mode & HCI_LM_ENCRYPT)
418 return hci_conn_auth(conn); 430 return hci_conn_auth(conn, sec_level);
419 431
420 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) 432 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
421 return 0; 433 return 0;
422 434
423 if (hci_conn_auth(conn)) { 435 if (hci_conn_auth(conn, sec_level)) {
424 struct hci_cp_set_conn_encrypt cp; 436 struct hci_cp_set_conn_encrypt cp;
425 cp.handle = cpu_to_le16(conn->handle); 437 cp.handle = cpu_to_le16(conn->handle);
426 cp.encrypt = 1; 438 cp.encrypt = 1;
427 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, 439 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
428 sizeof(cp), &cp); 440 sizeof(cp), &cp);
429 } 441 }
442
430 return 0; 443 return 0;
431} 444}
432EXPORT_SYMBOL(hci_conn_encrypt); 445EXPORT_SYMBOL(hci_conn_security);
433 446
434/* Change link key */ 447/* Change link key */
435int hci_conn_change_link_key(struct hci_conn *conn) 448int hci_conn_change_link_key(struct hci_conn *conn)
@@ -442,12 +455,13 @@ int hci_conn_change_link_key(struct hci_conn *conn)
442 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, 455 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
443 sizeof(cp), &cp); 456 sizeof(cp), &cp);
444 } 457 }
458
445 return 0; 459 return 0;
446} 460}
447EXPORT_SYMBOL(hci_conn_change_link_key); 461EXPORT_SYMBOL(hci_conn_change_link_key);
448 462
449/* Switch role */ 463/* Switch role */
450int hci_conn_switch_role(struct hci_conn *conn, uint8_t role) 464int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
451{ 465{
452 BT_DBG("conn %p", conn); 466 BT_DBG("conn %p", conn);
453 467
@@ -460,6 +474,7 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
460 cp.role = role; 474 cp.role = role;
461 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp); 475 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
462 } 476 }
477
463 return 0; 478 return 0;
464} 479}
465EXPORT_SYMBOL(hci_conn_switch_role); 480EXPORT_SYMBOL(hci_conn_switch_role);