Skip to content
Permalink
Browse files

Bluetooth: SMP: Fix peripheral security request with authenticated keys

The call to bt_conn_security will send a SMP security request for
peripheral, and for central it will initiate LL encryption.
A call to bt_conn_security with no IO capabilities but authenticated
keys has been distributed, would succeed on central side, but fail on
peripheral side with error code -22.

The keys could have been either:
 - Preprogrammed
 - IO capabilities may have changed.
 - OOB bonding may been used.

Fix so that Peripheral can send a security request if the bond
information is already established.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
  • Loading branch information...
joerchan authored and carlescufi committed Jul 24, 2019
1 parent 4eb8517 commit c2ee00f7374a587b81ce570cd92f4a84af619c34
Showing with 35 additions and 26 deletions.
  1. +1 −25 subsys/bluetooth/host/conn.c
  2. +33 −1 subsys/bluetooth/host/smp.c
  3. +1 −0 subsys/bluetooth/host/smp.h
@@ -1005,33 +1005,9 @@ static int start_security(struct bt_conn *conn)
#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_SMP)
case BT_HCI_ROLE_MASTER:
{
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256,
conn->id, &conn->le.dst);
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK,
conn->id,
&conn->le.dst);
}
}

if (!conn->le.keys ||
!(conn->le.keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) {
return bt_smp_send_pairing_req(conn);
}

if (conn->required_sec_level > BT_SECURITY_MEDIUM &&
!(conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) {
if (!bt_smp_keys_check(conn)) {
return bt_smp_send_pairing_req(conn);
}

if (conn->required_sec_level > BT_SECURITY_HIGH &&
!(conn->le.keys->flags & BT_KEYS_AUTHENTICATED) &&
!(conn->le.keys->keys & BT_KEYS_LTK_P256) &&
!(conn->le.keys->enc_size == BT_SMP_MAX_ENC_KEY_SIZE)) {
return bt_smp_send_pairing_req(conn);
}

/* LE SC LTK and legacy master LTK are stored in same place */
return bt_conn_le_start_encryption(conn,
conn->le.keys->ltk.rand,
@@ -2384,7 +2384,7 @@ int bt_smp_send_security_req(struct bt_conn *conn)
}

/* early verify if required sec level if reachable */
if (!sec_level_reachable(conn)) {
if (!(sec_level_reachable(conn) || bt_smp_keys_check(conn))) {
return -EINVAL;
}

@@ -4845,6 +4845,38 @@ bool bt_smp_get_tk(struct bt_conn *conn, u8_t *tk)
return true;
}

bool bt_smp_keys_check(struct bt_conn *conn)
{
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256,
conn->id, &conn->le.dst);
if (!conn->le.keys) {
conn->le.keys = bt_keys_find(BT_KEYS_LTK,
conn->id,
&conn->le.dst);
}
}

if (!conn->le.keys ||
!(conn->le.keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) {
return false;
}

if (conn->required_sec_level > BT_SECURITY_MEDIUM &&
!(conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) {
return false;
}

if (conn->required_sec_level > BT_SECURITY_HIGH &&
!(conn->le.keys->flags & BT_KEYS_AUTHENTICATED) &&
!(conn->le.keys->keys & BT_KEYS_LTK_P256) &&
!(conn->le.keys->enc_size == BT_SMP_MAX_ENC_KEY_SIZE)) {
return false;
}

return true;
}

static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
{
int i;
@@ -127,6 +127,7 @@ int bt_smp_send_pairing_req(struct bt_conn *conn);
int bt_smp_send_security_req(struct bt_conn *conn);
void bt_smp_update_keys(struct bt_conn *conn);
bool bt_smp_get_tk(struct bt_conn *conn, u8_t *tk);
bool bt_smp_keys_check(struct bt_conn *conn);

int bt_smp_br_send_pairing_req(struct bt_conn *conn);

0 comments on commit c2ee00f

Please sign in to comment.
You can’t perform that action at this time.