[PATCH] BT_SECURITY_HIGH requires 16 digit pin code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The security level BT_SECURITY_HIGH expects secure connection
and a minimum 16 digit pin code used for bonding. It's requitred by the
Sim Access Profile.

Patch on behalf of ST-Ericsson SA.

Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@xxxxxxxxx>
---
 lib/hci.h       |    8 +++++++-
 src/dbus-hci.c  |   33 ++++++++++++++++++++++++++++-----
 src/security.c  |   38 ++++++++++++++++++++++++++++++++++----
 3 files changed, 69 insertions(+), 10 deletions(-)
 mode change 100644 => 100755 lib/bluetooth.h
 mode change 100644 => 100755 lib/hci.h
 mode change 100644 => 100755 lib/l2cap.h
 mode change 100644 => 100755 lib/rfcomm.h
 mode change 100644 => 100755 src/btio.c
 mode change 100644 => 100755 src/btio.h
 mode change 100644 => 100755 src/dbus-hci.c
 mode change 100644 => 100755 src/security.c

diff --git a/lib/bluetooth.h b/lib/bluetooth.h
old mode 100644
new mode 100755
diff --git a/lib/hci.h b/lib/hci.h
old mode 100644
new mode 100755
index 512dab9..a313929
--- a/lib/hci.h
+++ b/lib/hci.h
@@ -96,7 +96,7 @@ enum {
 #define HCISETLINKMODE	_IOW('H', 226, int)
 #define HCISETACLMTU	_IOW('H', 227, int)
 #define HCISETSCOMTU	_IOW('H', 228, int)
-
+#define HCISETCONNINFO	_IOW('H', 229, int)
 #define HCIBLOCKADDR	_IOW('H', 230, int)
 #define HCIUNBLOCKADDR	_IOW('H', 231, int)
 
@@ -2326,9 +2326,15 @@ struct hci_conn_info_req {
 	struct hci_conn_info conn_info[0];
 };
 
+struct hci_set_conn_info_req {
+	bdaddr_t bdaddr;
+	uint8_t  pin_len;
+	uint8_t  key_type;
+};
 struct hci_auth_info_req {
 	bdaddr_t bdaddr;
 	uint8_t  type;
+	uint8_t  level;
 };
 
 struct hci_inquiry_req {
diff --git a/lib/l2cap.h b/lib/l2cap.h
old mode 100644
new mode 100755
diff --git a/lib/rfcomm.h b/lib/rfcomm.h
old mode 100644
new mode 100755
diff --git a/src/btio.c b/src/btio.c
old mode 100644
new mode 100755
diff --git a/src/btio.h b/src/btio.h
old mode 100644
new mode 100755
diff --git a/src/dbus-hci.c b/src/dbus-hci.c
old mode 100644
new mode 100755
index 9055ffe..177f536
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -165,6 +165,8 @@ static void pincode_cb(struct agent *agent, DBusError *err,
 {
 	struct btd_adapter *adapter = device_get_adapter(device);
 	pin_code_reply_cp pr;
+	struct hci_auth_info_req ar;
+	struct hci_set_conn_info_req cr;
 	bdaddr_t sba, dba;
 	size_t len;
 	int dev;
@@ -180,13 +182,30 @@ static void pincode_cb(struct agent *agent, DBusError *err,
 	adapter_get_address(adapter, &sba);
 	device_get_address(device, &dba);
 
-	if (err) {
-		hci_send_cmd(dev, OGF_LINK_CTL,
-				OCF_PIN_CODE_NEG_REPLY, 6, &dba);
-		goto done;
-	}
+	if (err)
+		goto reject;
 
 	len = strlen(pincode);
+	memset(&ar, 0, sizeof(ar));
+	bacpy(&ar.bdaddr, &dba);
+	if (ioctl(dev, HCIGETAUTHINFO, (unsigned long) &ar) < 0) {
+		error("Can't get auth info: %s (%d)", strerror(errno), errno);
+		goto reject;
+	}
+
+	if (ar.level == BT_SECURITY_HIGH && len < 16) {
+		error("Not enough secure PIN (expected 16 digit PIN, but got \
+							%d digit).", len);
+		goto reject;
+	}
+
+	bacpy(&cr.bdaddr, &dba);
+	cr.pin_len = len;
+	cr.key_type = 0xff;
+	if (ioctl(dev, HCISETCONNINFO, (unsigned long) &cr) < 0) {
+		error("Can't set conn info: %s (%d)", strerror(errno), errno);
+		goto reject;
+	}
 
 	set_pin_length(&sba, len);
 
@@ -196,7 +215,11 @@ static void pincode_cb(struct agent *agent, DBusError *err,
 	pr.pin_len = len;
 	hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY,
 						PIN_CODE_REPLY_CP_SIZE, &pr);
+	goto done;
 
+reject:
+	hci_send_cmd(dev, OGF_LINK_CTL,
+			OCF_PIN_CODE_NEG_REPLY, 6, &dba);
 done:
 	hci_close_dev(dev);
 }
diff --git a/src/security.c b/src/security.c
old mode 100644
new mode 100755
index 667f1f1..b25d1e4
--- a/src/security.c
+++ b/src/security.c
@@ -309,6 +309,7 @@ static void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
 	char sa[18], da[18];
 	uint8_t type;
 	int err;
+	int pinlen;
 
 	if (!get_adapter_and_device(sba, dba, &adapter, &device, FALSE))
 		device = NULL;
@@ -325,9 +326,11 @@ static void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
 			DBG("HCIGETAUTHINFO failed %s (%d)",
 						strerror(errno), errno);
 		req.type = 0x00;
+		req.level = BT_SECURITY_LOW;
 	}
 
-	DBG("kernel auth requirements = 0x%02x", req.type);
+	DBG("kernel auth requirements = 0x%02x and security level = 0x%02x", \
+				req.type, req.level);
 
 	if (main_opts.debug_keys && device && device_get_debug_key(device, key))
 		type = 0x03;
@@ -341,18 +344,34 @@ static void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
 
 	DBG("link key type = 0x%02x", type);
 
+	pinlen = read_pin_length(sba, dba);
+	DBG("stored link key type = 0x%02x pin_len = %d", type, pinlen);
+
 	/* Don't use unauthenticated combination keys if MITM is
-	 * required */
-	if (type == 0x04 && req.type != 0xff && (req.type & 0x01))
+	 * required and also don't use combination link keys authenticated with
+	 * an PIN code len < 16 if security level BT_SECURITY_HIGH is required*/
+	if ((type == 0x04 && req.type != 0xff && (req.type & 0x01)) ||
+		(type == 0x00 && req.level == BT_SECURITY_HIGH && pinlen < 16))
 		hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY,
 								6, dba);
 	else {
 		link_key_reply_cp lr;
+		struct hci_set_conn_info_req cr;
 
 		memcpy(lr.link_key, key, 16);
 		bacpy(&lr.bdaddr, dba);
 
-		hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_REPLY,
+		bacpy(&cr.bdaddr, dba);
+		cr.pin_len = pinlen;
+		cr.key_type = type;
+
+		if (ioctl(dev, HCISETCONNINFO, (unsigned long) &cr) < 0) {
+			error("Can't set conn info: %s (%d)", strerror(errno),
+									errno);
+			hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY,
+									6, dba);
+		} else
+			hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_REPLY,
 						LINK_KEY_REPLY_CP_SIZE, &lr);
 	}
 }
@@ -523,6 +542,7 @@ static void pin_code_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
 	pin_code_reply_cp pr;
 	struct hci_conn_info_req *cr;
 	struct hci_conn_info *ci;
+	struct hci_auth_info_req ar;
 	char sa[18], da[18], pin[17];
 	int pinlen;
 
@@ -542,10 +562,20 @@ static void pin_code_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
 	}
 	ci = cr->conn_info;
 
+	memset(&ar, 0, sizeof(ar));
+	bacpy(&ar.bdaddr, dba);
+	if (ioctl(dev, HCIGETAUTHINFO, (unsigned long) &ar) < 0) {
+		error("Can't get auth info: %s (%d)", strerror(errno), errno);
+		goto reject;
+	}
 	memset(pin, 0, sizeof(pin));
 	pinlen = read_pin_code(sba, dba, pin);
 
 	if (pinlen > 0) {
+		if (ar.level == BT_SECURITY_HIGH && pinlen < 16) {
+			error("Not 16 digit pin code.");
+			goto reject;
+		}
 		set_pin_length(sba, pinlen);
 		memcpy(pr.pin_code, pin, pinlen);
 		pr.pin_len = pinlen;
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux