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:
parent
7d29296047
commit
b763a9be3a
2 changed files with 54 additions and 1 deletions
|
@ -708,6 +708,9 @@ struct bt_hci_rp_read_rssi {
|
||||||
s8_t rssi;
|
s8_t rssi;
|
||||||
} __packed;
|
} __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)
|
#define BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE BT_OP(BT_OGF_STATUS, 0x0008)
|
||||||
struct bt_hci_cp_read_encryption_key_size {
|
struct bt_hci_cp_read_encryption_key_size {
|
||||||
u16_t handle;
|
u16_t handle;
|
||||||
|
|
|
@ -1838,7 +1838,51 @@ static void conn_req(struct net_buf *buf)
|
||||||
bt_conn_unref(conn);
|
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) {
|
if (!conn->encrypt) {
|
||||||
conn->sec_level = BT_SECURITY_LOW;
|
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;
|
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) {
|
if (conn->required_sec_level > conn->sec_level) {
|
||||||
BT_ERR("Failed to set required security level");
|
BT_ERR("Failed to set required security level");
|
||||||
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
|
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue