Bluetooth: Host: Fix checking for sufficient encryption key size

A security vulnerability in the Bluetooth BR/EDR Bluetooth Core
specification versions 1.0 through 5.1 has been identified as
CVE-2019-9506. The Bluetooth BR/EDR encryption key negotiation
protocol is vulnerable to packet injection that could allow an
unauthenticated user to decrease the size of the entropy of the
encryption key, potentially causing information disclosure and/or
escalation of privileges via adjacent access. There is not currently
any knowledge of this being exploited.

From Core spec erratum 11838:

A device shall enforce an encryption key with at least 128-bit
equivalent strength for all services that require Security Mode 4,
Level 4. For all other services that require encryption, a device
should enforce an encryption key with at least 56-bit equivalent
strength, irrespective of whether the remote device supports Secure
Simple Pairing.

After encryption has been enabled, the Host should check the
encryption key size using either the HCI_Read_Encryption_Key_Size
command (see [Vol 2] Part E, Section 7.5.7) or a vendor-specific
method.

Fixes #18658

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2019-08-27 10:11:13 +03:00 committed by Johan Hedberg
commit b763a9be3a
2 changed files with 54 additions and 1 deletions

View file

@ -708,6 +708,9 @@ struct bt_hci_rp_read_rssi {
s8_t rssi;
} __packed;
#define BT_HCI_ENCRYPTION_KEY_SIZE_MIN 7
#define BT_HCI_ENCRYPTION_KEY_SIZE_MAX 16
#define BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE BT_OP(BT_OGF_STATUS, 0x0008)
struct bt_hci_cp_read_encryption_key_size {
u16_t handle;

View file

@ -1838,7 +1838,51 @@ static void conn_req(struct net_buf *buf)
bt_conn_unref(conn);
}
static void update_sec_level_br(struct bt_conn *conn)
static bool br_sufficient_key_size(struct bt_conn *conn)
{
struct bt_hci_cp_read_encryption_key_size *cp;
struct bt_hci_rp_read_encryption_key_size *rp;
struct net_buf *buf, *rsp;
u8_t key_size;
int err;
buf = bt_hci_cmd_create(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE,
sizeof(*cp));
if (!buf) {
BT_ERR("Failed to allocate command buffer");
return false;
}
cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE,
buf, &rsp);
if (err) {
BT_ERR("Failed to read encryption key size (err %d)", err);
return false;
}
if (rsp->len < sizeof(*rp)) {
BT_ERR("Too small command complete for encryption key size");
net_buf_unref(rsp);
return false;
}
rp = (void *)rsp->data;
key_size = rp->key_size;
net_buf_unref(rsp);
BT_DBG("Encryption key size is %u", key_size);
if (conn->sec_level == BT_SECURITY_FIPS) {
return key_size == BT_HCI_ENCRYPTION_KEY_SIZE_MAX;
}
return key_size >= BT_HCI_ENCRYPTION_KEY_SIZE_MIN;
}
static bool update_sec_level_br(struct bt_conn *conn)
{
if (!conn->encrypt) {
conn->sec_level = BT_SECURITY_LOW;
@ -1860,6 +1904,12 @@ static void update_sec_level_br(struct bt_conn *conn)
conn->sec_level = BT_SECURITY_MEDIUM;
}
if (!br_sufficient_key_size(conn)) {
BT_ERR("Encryption key size is not sufficient");
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
return false;
}
if (conn->required_sec_level > conn->sec_level) {
BT_ERR("Failed to set required security level");
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);