Commit d3e54a87 authored by Johan Hedberg's avatar Johan Hedberg Committed by Marcel Holtmann
Browse files

Bluetooth: Fix DHKey Check sending order for slave role



According to the LE SC specification the initiating device sends its
DHKey check first and the non-initiating devices sends its DHKey check
as a response to this. It's also important that the non-initiating
device doesn't send the response if it's still waiting for user input.
In order to synchronize all this a new flag is added.

Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 38606f14
Loading
Loading
Loading
Loading
+43 −17
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ enum {
	SMP_FLAG_REMOTE_PK,
	SMP_FLAG_DEBUG_KEY,
	SMP_FLAG_WAIT_USER,
	SMP_FLAG_DHKEY_PENDING,
};

struct smp_chan {
@@ -994,6 +995,29 @@ static void smp_notify_keys(struct l2cap_conn *conn)
	}
}

static void sc_add_ltk(struct smp_chan *smp)
{
	struct hci_conn *hcon = smp->conn->hcon;
	u8 key_type, auth;

	if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
		key_type = SMP_LTK_P256_DEBUG;
	else
		key_type = SMP_LTK_P256;

	if (hcon->pending_sec_level == BT_SECURITY_FIPS)
		auth = 1;
	else
		auth = 0;

	memset(smp->tk + smp->enc_key_size, 0,
	       SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);

	smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
			       key_type, auth, smp->tk, smp->enc_key_size,
			       0, 0);
}

static void sc_generate_link_key(struct smp_chan *smp)
{
	/* These constants are as specified in the core specification.
@@ -1312,12 +1336,10 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
		if (!hcon->out) {
			smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
				     sizeof(smp->prnd), smp->prnd);
			if (smp->passkey_round == 20) {
				sc_dhkey_check(smp);
			if (smp->passkey_round == 20)
				SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
			} else {
			else
				SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
			}
			return 0;
		}

@@ -1394,7 +1416,14 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
		return 0;
	}

	/* Initiator sends DHKey check first */
	if (hcon->out) {
		sc_dhkey_check(smp);
		SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
	} else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) {
		sc_dhkey_check(smp);
		sc_add_ltk(smp);
	}

	return 0;
}
@@ -2262,7 +2291,6 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
	struct smp_chan *smp = chan->data;
	u8 a[7], b[7], *local_addr, *remote_addr;
	u8 io_cap[3], r[16], e[16];
	u8 key_type, auth;
	int err;

	BT_DBG("conn %p", conn);
@@ -2298,19 +2326,17 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
	if (memcmp(check->e, e, 16))
		return SMP_DHKEY_CHECK_FAILED;

	if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
		key_type = SMP_LTK_P256_DEBUG;
	else
		key_type = SMP_LTK_P256;
	if (!hcon->out) {
		if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
			set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags);
			return 0;
		}

	if (hcon->pending_sec_level == BT_SECURITY_FIPS)
		auth = 1;
	else
		auth = 0;
		/* Slave sends DHKey check as response to master */
		sc_dhkey_check(smp);
	}

	smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
			       key_type, auth, smp->tk, smp->enc_key_size,
			       0, 0);
	sc_add_ltk(smp);

	if (hcon->out) {
		hci_le_start_enc(hcon, 0, 0, smp->tk);