summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJaganath Kanakkassery <jaganathx.kanakkassery@intel.com>2016-10-03 21:03:52 +0530
committerJohan Hedberg <johan.hedberg@intel.com>2016-10-21 07:47:31 +0300
commit96c1169e4dc69968f4ad85e47d2a1cac59a988f4 (patch)
treee3b663161da94ecea4d4818a3bdc206e8cfc7900 /net
parenta1c139eb848dce148270353f330d190cbbf99e9a (diff)
Bluetooth: RFCOMM: Handle security for incoming connections
Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/rfcomm.c85
-rw-r--r--net/bluetooth/rfcomm_internal.h1
2 files changed, 86 insertions, 0 deletions
diff --git a/net/bluetooth/rfcomm.c b/net/bluetooth/rfcomm.c
index e65ef98ce..b23e376b2 100644
--- a/net/bluetooth/rfcomm.c
+++ b/net/bluetooth/rfcomm.c
@@ -524,6 +524,47 @@ static void rfcomm_dlc_connected(struct bt_rfcomm_dlc *dlc)
}
}
+enum security_result {
+ RFCOMM_SECURITY_PASSED,
+ RFCOMM_SECURITY_REJECT,
+ RFCOMM_SECURITY_PENDING
+};
+
+static enum security_result rfcomm_dlc_security(struct bt_rfcomm_dlc *dlc)
+{
+ struct bt_conn *conn = dlc->session->br_chan.chan.conn;
+
+ BT_DBG("dlc %p", dlc);
+
+ /* If current security level is greater than or equal to required
+ * security level then return SUCCESS.
+ * For SSP devices the current security will be atleast MEDIUM
+ * since L2CAP is enforcing it
+ */
+ if (conn->sec_level >= dlc->required_sec_level) {
+ return RFCOMM_SECURITY_PASSED;
+ }
+
+ if (!bt_conn_security(conn, dlc->required_sec_level)) {
+ /* If Security elevation is initiated or in progress */
+ return RFCOMM_SECURITY_PENDING;
+ }
+
+ /* Security request failed */
+ return RFCOMM_SECURITY_REJECT;
+}
+
+static void rfcomm_dlc_drop(struct bt_rfcomm_dlc *dlc)
+{
+ BT_DBG("dlc %p", dlc);
+
+ if (!dlc->initiator) {
+ rfcomm_send_dm(dlc->session, dlc->dlci);
+ }
+ rfcomm_dlcs_remove_dlci(dlc->session->dlcs, dlc->dlci);
+ rfcomm_dlc_destroy(dlc);
+}
+
static void rfcomm_handle_sabm(struct bt_rfcomm_session *session, uint8_t dlci)
{
if (!dlci) {
@@ -536,6 +577,7 @@ static void rfcomm_handle_sabm(struct bt_rfcomm_session *session, uint8_t dlci)
session->state = BT_RFCOMM_STATE_CONNECTED;
} else {
struct bt_rfcomm_dlc *dlc;
+ enum security_result result;
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
if (!dlc) {
@@ -546,6 +588,20 @@ static void rfcomm_handle_sabm(struct bt_rfcomm_session *session, uint8_t dlci)
}
}
+ result = rfcomm_dlc_security(dlc);
+ switch (result) {
+ case RFCOMM_SECURITY_PENDING:
+ dlc->state = BT_RFCOMM_STATE_SECURITY_PENDING;
+ /* TODO: Start an auth timer */
+ return;
+ case RFCOMM_SECURITY_PASSED:
+ break;
+ case RFCOMM_SECURITY_REJECT:
+ default:
+ rfcomm_dlc_drop(dlc);
+ return;
+ }
+
if (rfcomm_send_ua(session, dlci) < 0) {
return;
}
@@ -868,6 +924,34 @@ static void rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
}
}
+static void rfcomm_encrypt_change(struct bt_l2cap_chan *chan,
+ uint8_t hci_status)
+{
+ struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
+ struct bt_conn *conn = chan->conn;
+ struct bt_rfcomm_dlc *dlc;
+
+ BT_DBG("session %p status 0x%02x encr 0x%02x", session, hci_status,
+ conn->encrypt);
+
+ for (dlc = session->dlcs; dlc; dlc = dlc->_next) {
+ if (dlc->state != BT_RFCOMM_STATE_SECURITY_PENDING) {
+ continue;
+ }
+
+ if (hci_status || !conn->encrypt ||
+ conn->sec_level < dlc->required_sec_level) {
+ rfcomm_dlc_drop(dlc);
+ continue;
+ }
+
+ if (!dlc->initiator) {
+ rfcomm_send_ua(session, dlc->dlci);
+ rfcomm_dlc_connected(dlc);
+ }
+ }
+}
+
static int rfcomm_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
{
int i;
@@ -875,6 +959,7 @@ static int rfcomm_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
.connected = rfcomm_connected,
.disconnected = rfcomm_disconnected,
.recv = rfcomm_recv,
+ .encrypt_change = rfcomm_encrypt_change,
};
BT_DBG("conn %p handle %u", conn, conn->handle);
diff --git a/net/bluetooth/rfcomm_internal.h b/net/bluetooth/rfcomm_internal.h
index c0bca1ebe..2da3e2d18 100644
--- a/net/bluetooth/rfcomm_internal.h
+++ b/net/bluetooth/rfcomm_internal.h
@@ -33,6 +33,7 @@ struct bt_rfcomm_session {
enum {
BT_RFCOMM_STATE_IDLE,
BT_RFCOMM_STATE_INIT,
+ BT_RFCOMM_STATE_SECURITY_PENDING,
BT_RFCOMM_STATE_CONNECTED,
BT_RFCOMM_STATE_CONFIG,
BT_RFCOMM_STATE_DISCONNECTED,