Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: SMP: Add support for H7 crypto function and CT2 auth flag
@ 2016-12-07 19:55 Johan Hedberg
  2016-12-08  6:09 ` Marcel Holtmann
  0 siblings, 1 reply; 2+ messages in thread
From: Johan Hedberg @ 2016-12-07 19:55 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

Bluetooth 5.0 introduces a new H7 key generation function that's used
when both sides of the pairing set the CT2 authentication flag to 1.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/smp.c | 83 ++++++++++++++++++++++++++++++++++++++++++-----------
 net/bluetooth/smp.h |  1 +
 2 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 43faf2aea2ab..069436767d0e 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -57,7 +57,7 @@
 #define SMP_TIMEOUT	msecs_to_jiffies(30000)
 
 #define AUTH_REQ_MASK(dev)	(hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \
-				 0x1f : 0x07)
+				 0x3f : 0x07)
 #define KEY_DIST_MASK		0x07
 
 /* Maximum message length that can be passed to aes_cmac */
@@ -76,6 +76,7 @@ enum {
 	SMP_FLAG_DHKEY_PENDING,
 	SMP_FLAG_REMOTE_OOB,
 	SMP_FLAG_LOCAL_OOB,
+	SMP_FLAG_CT2,
 };
 
 struct smp_dev {
@@ -357,6 +358,22 @@ static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16],
 	return err;
 }
 
+static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16],
+		  const u8 salt[16], u8 res[16])
+{
+	int err;
+
+	SMP_DBG("w %16phN salt %16phN", w, salt);
+
+	err = aes_cmac(tfm_cmac, salt, w, 16, res);
+	if (err)
+		return err;
+
+	SMP_DBG("res %16phN", res);
+
+	return err;
+}
+
 /* The following functions map to the legacy SMP crypto functions e, c1,
  * s1 and ah.
  */
@@ -1130,20 +1147,30 @@ static void sc_add_ltk(struct smp_chan *smp)
 
 static void sc_generate_link_key(struct smp_chan *smp)
 {
-	/* These constants are as specified in the core specification.
-	 * In ASCII they spell out to 'tmp1' and 'lebr'.
-	 */
-	const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
+	/* From core spec. Spells out in ASCII as 'lebr'. */
 	const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
 
 	smp->link_key = kzalloc(16, GFP_KERNEL);
 	if (!smp->link_key)
 		return;
 
-	if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
-		kzfree(smp->link_key);
-		smp->link_key = NULL;
-		return;
+	if (test_bit(SMP_FLAG_CT2, &smp->flags)) {
+		const u8 salt[16] = { 0x31, 0x70, 0x6d, 0x74 };
+
+		if (smp_h7(smp->tfm_cmac, smp->tk, salt, smp->link_key)) {
+			kzfree(smp->link_key);
+			smp->link_key = NULL;
+			return;
+		}
+	} else {
+		/* From core spec. Spells out in ASCII as 'tmp1'. */
+		const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
+
+		if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
+			kzfree(smp->link_key);
+			smp->link_key = NULL;
+			return;
+		}
 	}
 
 	if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
@@ -1169,10 +1196,7 @@ static void smp_allow_key_dist(struct smp_chan *smp)
 
 static void sc_generate_ltk(struct smp_chan *smp)
 {
-	/* These constants are as specified in the core specification.
-	 * In ASCII they spell out to 'tmp2' and 'brle'.
-	 */
-	const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
+	/* From core spec. Spells out in ASCII as 'brle'. */
 	const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
 	struct hci_conn *hcon = smp->conn->hcon;
 	struct hci_dev *hdev = hcon->hdev;
@@ -1187,8 +1211,18 @@ static void sc_generate_ltk(struct smp_chan *smp)
 	if (key->type == HCI_LK_DEBUG_COMBINATION)
 		set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
 
-	if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
-		return;
+	if (test_bit(SMP_FLAG_CT2, &smp->flags)) {
+		const u8 salt[16] = { 0x32, 0x70, 0x6d, 0x74 };
+
+		if (smp_h7(smp->tfm_cmac, key->val, salt, smp->tk))
+			return;
+	} else {
+		/* From core spec. Spells out in ASCII as 'tmp2'. */
+		const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
+
+		if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
+			return;
+	}
 
 	if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk))
 		return;
@@ -1669,6 +1703,7 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
 	if (!rsp) {
 		memset(req, 0, sizeof(*req));
 
+		req->auth_req        = SMP_AUTH_CT2;
 		req->init_key_dist   = local_dist;
 		req->resp_key_dist   = remote_dist;
 		req->max_key_size    = conn->hcon->enc_key_size;
@@ -1680,6 +1715,7 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
 
 	memset(rsp, 0, sizeof(*rsp));
 
+	rsp->auth_req        = SMP_AUTH_CT2;
 	rsp->max_key_size    = conn->hcon->enc_key_size;
 	rsp->init_key_dist   = req->init_key_dist & remote_dist;
 	rsp->resp_key_dist   = req->resp_key_dist & local_dist;
@@ -1744,6 +1780,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
 		build_bredr_pairing_cmd(smp, req, &rsp);
 
+		if (req->auth_req & SMP_AUTH_CT2)
+			set_bit(SMP_FLAG_CT2, &smp->flags);
+
 		key_size = min(req->max_key_size, rsp.max_key_size);
 		if (check_enc_key_size(conn, key_size))
 			return SMP_ENC_KEY_SIZE;
@@ -1761,9 +1800,13 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
 	build_pairing_cmd(conn, req, &rsp, auth);
 
-	if (rsp.auth_req & SMP_AUTH_SC)
+	if (rsp.auth_req & SMP_AUTH_SC) {
 		set_bit(SMP_FLAG_SC, &smp->flags);
 
+		if (rsp.auth_req & SMP_AUTH_CT2)
+			set_bit(SMP_FLAG_CT2, &smp->flags);
+	}
+
 	if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
 		sec_level = BT_SECURITY_MEDIUM;
 	else
@@ -1917,6 +1960,9 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 	 */
 	smp->remote_key_dist &= rsp->resp_key_dist;
 
+	if ((req->auth_req & SMP_AUTH_CT2) && (auth & SMP_AUTH_CT2))
+		set_bit(SMP_FLAG_CT2, &smp->flags);
+
 	/* For BR/EDR this means we're done and can start phase 3 */
 	if (conn->hcon->type == ACL_LINK) {
 		/* Clear bits which are generated but not distributed */
@@ -2312,8 +2358,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 
 	authreq = seclevel_to_authreq(sec_level);
 
-	if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED))
+	if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED)) {
 		authreq |= SMP_AUTH_SC;
+		if (hci_dev_test_flag(hcon->hdev, HCI_SSP_ENABLED))
+			authreq |= SMP_AUTH_CT2;
+	}
 
 	/* Require MITM if IO Capability allows or the security level
 	 * requires it.
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index ffcc70b6b199..0ff6247eaa6c 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -57,6 +57,7 @@ struct smp_cmd_pairing {
 #define SMP_AUTH_MITM		0x04
 #define SMP_AUTH_SC		0x08
 #define SMP_AUTH_KEYPRESS	0x10
+#define SMP_AUTH_CT2		0x20
 
 #define SMP_CMD_PAIRING_CONFIRM	0x03
 struct smp_cmd_pairing_confirm {
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] Bluetooth: SMP: Add support for H7 crypto function and CT2 auth flag
  2016-12-07 19:55 [PATCH] Bluetooth: SMP: Add support for H7 crypto function and CT2 auth flag Johan Hedberg
@ 2016-12-08  6:09 ` Marcel Holtmann
  0 siblings, 0 replies; 2+ messages in thread
From: Marcel Holtmann @ 2016-12-08  6:09 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> Bluetooth 5.0 introduces a new H7 key generation function that's used
> when both sides of the pairing set the CT2 authentication flag to 1.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/smp.c | 83 ++++++++++++++++++++++++++++++++++++++++++-----------
> net/bluetooth/smp.h |  1 +
> 2 files changed, 67 insertions(+), 17 deletions(-)
> 
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index 43faf2aea2ab..069436767d0e 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -57,7 +57,7 @@
> #define SMP_TIMEOUT	msecs_to_jiffies(30000)
> 
> #define AUTH_REQ_MASK(dev)	(hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \
> -				 0x1f : 0x07)
> +				 0x3f : 0x07)
> #define KEY_DIST_MASK		0x07
> 
> /* Maximum message length that can be passed to aes_cmac */
> @@ -76,6 +76,7 @@ enum {
> 	SMP_FLAG_DHKEY_PENDING,
> 	SMP_FLAG_REMOTE_OOB,
> 	SMP_FLAG_LOCAL_OOB,
> +	SMP_FLAG_CT2,
> };
> 
> struct smp_dev {
> @@ -357,6 +358,22 @@ static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16],
> 	return err;
> }
> 
> +static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16],
> +		  const u8 salt[16], u8 res[16])
> +{
> +	int err;
> +
> +	SMP_DBG("w %16phN salt %16phN", w, salt);
> +
> +	err = aes_cmac(tfm_cmac, salt, w, 16, res);
> +	if (err)
> +		return err;
> +
> +	SMP_DBG("res %16phN", res);
> +
> +	return err;
> +}
> +
> /* The following functions map to the legacy SMP crypto functions e, c1,
>  * s1 and ah.
>  */
> @@ -1130,20 +1147,30 @@ static void sc_add_ltk(struct smp_chan *smp)
> 
> static void sc_generate_link_key(struct smp_chan *smp)
> {
> -	/* These constants are as specified in the core specification.
> -	 * In ASCII they spell out to 'tmp1' and 'lebr'.
> -	 */
> -	const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
> +	/* From core spec. Spells out in ASCII as 'lebr'. */
> 	const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
> 
> 	smp->link_key = kzalloc(16, GFP_KERNEL);
> 	if (!smp->link_key)
> 		return;
> 
> -	if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
> -		kzfree(smp->link_key);
> -		smp->link_key = NULL;
> -		return;
> +	if (test_bit(SMP_FLAG_CT2, &smp->flags)) {
> +		const u8 salt[16] = { 0x31, 0x70, 0x6d, 0x74 };

I think this one needs a comment. Especially since we only use 4 octets out of the 16 in the array.

> +
> +		if (smp_h7(smp->tfm_cmac, smp->tk, salt, smp->link_key)) {
> +			kzfree(smp->link_key);
> +			smp->link_key = NULL;
> +			return;
> +		}
> +	} else {
> +		/* From core spec. Spells out in ASCII as 'tmp1'. */
> +		const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
> +
> +		if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
> +			kzfree(smp->link_key);
> +			smp->link_key = NULL;
> +			return;
> +		}
> 	}
> 
> 	if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
> @@ -1169,10 +1196,7 @@ static void smp_allow_key_dist(struct smp_chan *smp)
> 
> static void sc_generate_ltk(struct smp_chan *smp)
> {
> -	/* These constants are as specified in the core specification.
> -	 * In ASCII they spell out to 'tmp2' and 'brle'.
> -	 */
> -	const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
> +	/* From core spec. Spells out in ASCII as 'brle'. */
> 	const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
> 	struct hci_conn *hcon = smp->conn->hcon;
> 	struct hci_dev *hdev = hcon->hdev;
> @@ -1187,8 +1211,18 @@ static void sc_generate_ltk(struct smp_chan *smp)
> 	if (key->type == HCI_LK_DEBUG_COMBINATION)
> 		set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
> 
> -	if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
> -		return;
> +	if (test_bit(SMP_FLAG_CT2, &smp->flags)) {
> +		const u8 salt[16] = { 0x32, 0x70, 0x6d, 0x74 };

Same as above, we document where the magic comes from everywhere else. And if it is zero padded, we should mention that.

> +
> +		if (smp_h7(smp->tfm_cmac, key->val, salt, smp->tk))
> +			return;
> +	} else {
> +		/* From core spec. Spells out in ASCII as 'tmp2'. */
> +		const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
> +
> +		if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
> +			return;
> +	}
> 
> 	if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk))
> 		return;
> @@ -1669,6 +1703,7 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
> 	if (!rsp) {
> 		memset(req, 0, sizeof(*req));
> 
> +		req->auth_req        = SMP_AUTH_CT2;
> 		req->init_key_dist   = local_dist;
> 		req->resp_key_dist   = remote_dist;
> 		req->max_key_size    = conn->hcon->enc_key_size;
> @@ -1680,6 +1715,7 @@ static void build_bredr_pairing_cmd(struct smp_chan *smp,
> 
> 	memset(rsp, 0, sizeof(*rsp));
> 
> +	rsp->auth_req        = SMP_AUTH_CT2;
> 	rsp->max_key_size    = conn->hcon->enc_key_size;
> 	rsp->init_key_dist   = req->init_key_dist & remote_dist;
> 	rsp->resp_key_dist   = req->resp_key_dist & local_dist;
> @@ -1744,6 +1780,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
> 
> 		build_bredr_pairing_cmd(smp, req, &rsp);
> 
> +		if (req->auth_req & SMP_AUTH_CT2)
> +			set_bit(SMP_FLAG_CT2, &smp->flags);
> +
> 		key_size = min(req->max_key_size, rsp.max_key_size);
> 		if (check_enc_key_size(conn, key_size))
> 			return SMP_ENC_KEY_SIZE;
> @@ -1761,9 +1800,13 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
> 
> 	build_pairing_cmd(conn, req, &rsp, auth);
> 
> -	if (rsp.auth_req & SMP_AUTH_SC)
> +	if (rsp.auth_req & SMP_AUTH_SC) {
> 		set_bit(SMP_FLAG_SC, &smp->flags);
> 
> +		if (rsp.auth_req & SMP_AUTH_CT2)
> +			set_bit(SMP_FLAG_CT2, &smp->flags);
> +	}
> +
> 	if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
> 		sec_level = BT_SECURITY_MEDIUM;
> 	else
> @@ -1917,6 +1960,9 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
> 	 */
> 	smp->remote_key_dist &= rsp->resp_key_dist;
> 
> +	if ((req->auth_req & SMP_AUTH_CT2) && (auth & SMP_AUTH_CT2))
> +		set_bit(SMP_FLAG_CT2, &smp->flags);
> +
> 	/* For BR/EDR this means we're done and can start phase 3 */
> 	if (conn->hcon->type == ACL_LINK) {
> 		/* Clear bits which are generated but not distributed */
> @@ -2312,8 +2358,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
> 
> 	authreq = seclevel_to_authreq(sec_level);
> 
> -	if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED))
> +	if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED)) {
> 		authreq |= SMP_AUTH_SC;
> +		if (hci_dev_test_flag(hcon->hdev, HCI_SSP_ENABLED))
> +			authreq |= SMP_AUTH_CT2;
> +	}
> 
> 	/* Require MITM if IO Capability allows or the security level
> 	 * requires it.
> diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
> index ffcc70b6b199..0ff6247eaa6c 100644
> --- a/net/bluetooth/smp.h
> +++ b/net/bluetooth/smp.h
> @@ -57,6 +57,7 @@ struct smp_cmd_pairing {
> #define SMP_AUTH_MITM		0x04
> #define SMP_AUTH_SC		0x08
> #define SMP_AUTH_KEYPRESS	0x10
> +#define SMP_AUTH_CT2		0x20
> 
> #define SMP_CMD_PAIRING_CONFIRM	0x03
> struct smp_cmd_pairing_confirm {

Regards

Marcel


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2016-12-08  6:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-07 19:55 [PATCH] Bluetooth: SMP: Add support for H7 crypto function and CT2 auth flag Johan Hedberg
2016-12-08  6:09 ` Marcel Holtmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox