Bluetooth: SMP: Add support for encryption key size reduction
This allows to pair with devices that use reduced encryption key size. Encryption key size is stored with keys for future use. LTKs are kept in full form (16 bytes) and are reduced only when used. As master: < ACL Data TX: Handle 64 flags 0x00 dlen 11 SMP: Pairing Request (0x01) len 6 IO capability: NoInputNoOutput (0x03) OOB data: Authentication data not present (0x00) Authentication requirement: Bonding, No MITM, Legacy, No Keypresses (0x01) Max encryption key size: 16 Initiator key distribution: EncKey Sign (0x05) Responder key distribution: EncKey IdKey Sign (0x07) > ACL Data RX: Handle 64 flags 0x02 dlen 11 SMP: Pairing Response (0x02) len 6 IO capability: KeyboardDisplay (0x04) OOB data: Authentication data not present (0x00) Authentication requirement: No bonding, No MITM, Legacy, No Keypresses (0x00) Max encryption key size: 7 Initiator key distribution: <none> (0x00) Responder key distribution: <none> (0x00) ... < HCI Command: LE Start Encryption (0x08|0x0019) plen 28 Handle: 64 Random number: 0x0000000000000000 Encrypted diversifier: 0x0000 Long term key: df3cff52a981d6000000000000000000 As slave: > ACL Data RX: Handle 64 flags 0x02 dlen 11 SMP: Pairing Request (0x01) len 6 IO capability: KeyboardDisplay (0x04) OOB data: Authentication data not present (0x00) Authentication requirement: No bonding, No MITM, Legacy, No Keypresses (0x00) Max encryption key size: 7 Initiator key distribution: <none> (0x00) Responder key distribution: <none> (0x00) < ACL Data TX: Handle 64 flags 0x00 dlen 11 SMP: Pairing Response (0x02) len 6 IO capability: NoInputNoOutput (0x03) OOB data: Authentication data not present (0x00) Authentication requirement: No bonding, No MITM, Legacy, No Keypresses (0x00) Max encryption key size: 16 Initiator key distribution: <none> (0x00) Responder key distribution: <none> (0x00) ... > HCI Event: LE Meta Event (0x3e) plen 13 LE Long Term Key Request (0x05) Handle: 64 Random number: 0x0000000000000000 Encrypted diversifier: 0x0000 < HCI Command: LE Long Term Key Request Reply (0x08|0x001a) plen 18 Handle: 64 Long term key: 701b431a9e17bb000000000000000000 Change-Id: Ibc70aa01c040aff0d39410d273d6880d35aa5ae0 Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com>
This commit is contained in:
parent
36d5294f8c
commit
e896804811
5 changed files with 39 additions and 8 deletions
|
@ -179,7 +179,7 @@ int bt_conn_security(struct bt_conn *conn, bt_security_t sec)
|
||||||
err = bt_conn_le_start_encryption(conn, keys->ltk.rand,
|
err = bt_conn_le_start_encryption(conn, keys->ltk.rand,
|
||||||
keys->ltk.ediv,
|
keys->ltk.ediv,
|
||||||
keys->ltk.val,
|
keys->ltk.val,
|
||||||
sizeof(keys->ltk.val));
|
keys->enc_size);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -812,7 +812,14 @@ static void le_ltk_request(struct bt_buf *buf)
|
||||||
|
|
||||||
cp = bt_buf_add(buf, sizeof(*cp));
|
cp = bt_buf_add(buf, sizeof(*cp));
|
||||||
cp->handle = evt->handle;
|
cp->handle = evt->handle;
|
||||||
memcpy(cp->ltk, conn->keys->slave_ltk.val, 16);
|
|
||||||
|
/* use only enc_size bytes of key for encryption */
|
||||||
|
memcpy(cp->ltk, conn->keys->slave_ltk.val,
|
||||||
|
conn->keys->enc_size);
|
||||||
|
if (conn->keys->enc_size < sizeof(cp->ltk)) {
|
||||||
|
memset(cp->ltk + conn->keys->enc_size, 0,
|
||||||
|
sizeof(cp->ltk) - conn->keys->enc_size);
|
||||||
|
}
|
||||||
|
|
||||||
bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf);
|
bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -54,6 +54,7 @@ struct bt_keys {
|
||||||
bt_addr_le_t addr;
|
bt_addr_le_t addr;
|
||||||
int keys;
|
int keys;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
uint8_t enc_size;
|
||||||
|
|
||||||
struct bt_ltk slave_ltk;
|
struct bt_ltk slave_ltk;
|
||||||
struct bt_ltk ltk;
|
struct bt_ltk ltk;
|
||||||
|
|
|
@ -663,7 +663,7 @@ static uint8_t smp_pairing_req(struct bt_conn *conn, struct bt_buf *buf)
|
||||||
rsp->auth_req = get_auth(req->auth_req);
|
rsp->auth_req = get_auth(req->auth_req);
|
||||||
rsp->io_capability = bt_smp_io_capa;
|
rsp->io_capability = bt_smp_io_capa;
|
||||||
rsp->oob_flag = BT_SMP_OOB_NOT_PRESENT;
|
rsp->oob_flag = BT_SMP_OOB_NOT_PRESENT;
|
||||||
rsp->max_key_size = req->max_key_size;
|
rsp->max_key_size = BT_SMP_MAX_ENC_KEY_SIZE;
|
||||||
rsp->init_key_dist = (req->init_key_dist & RECV_KEYS);
|
rsp->init_key_dist = (req->init_key_dist & RECV_KEYS);
|
||||||
rsp->resp_key_dist = (req->resp_key_dist & SEND_KEYS);
|
rsp->resp_key_dist = (req->resp_key_dist & SEND_KEYS);
|
||||||
|
|
||||||
|
@ -884,6 +884,20 @@ static uint8_t get_keys_type(uint8_t method)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t get_encryption_key_size(struct bt_smp *smp)
|
||||||
|
{
|
||||||
|
struct bt_smp_pairing *req, *rsp;
|
||||||
|
|
||||||
|
req = (struct bt_smp_pairing *)&smp->preq[1];
|
||||||
|
rsp = (struct bt_smp_pairing *)&smp->prsp[1];
|
||||||
|
|
||||||
|
/* The smaller value of the initiating and responding devices maximum
|
||||||
|
* encryption key length parameters shall be used as the encryption key
|
||||||
|
* size.
|
||||||
|
*/
|
||||||
|
return min(req->max_key_size, rsp->max_key_size);
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t smp_pairing_random(struct bt_conn *conn, struct bt_buf *buf)
|
static uint8_t smp_pairing_random(struct bt_conn *conn, struct bt_buf *buf)
|
||||||
{
|
{
|
||||||
struct bt_smp_pairing_random *req = (void *)buf->data;
|
struct bt_smp_pairing_random *req = (void *)buf->data;
|
||||||
|
@ -928,9 +942,11 @@ static uint8_t smp_pairing_random(struct bt_conn *conn, struct bt_buf *buf)
|
||||||
* security level upon encryption
|
* security level upon encryption
|
||||||
*/
|
*/
|
||||||
keys->type = get_keys_type(smp->method);
|
keys->type = get_keys_type(smp->method);
|
||||||
|
keys->enc_size = get_encryption_key_size(smp);
|
||||||
|
|
||||||
/* Rand and EDiv are 0 for the STK */
|
/* Rand and EDiv are 0 for the STK */
|
||||||
if (bt_conn_le_start_encryption(conn, 0, 0, stk, sizeof(stk))) {
|
if (bt_conn_le_start_encryption(conn, 0, 0, stk,
|
||||||
|
keys->enc_size)) {
|
||||||
BT_ERR("Failed to start encryption\n");
|
BT_ERR("Failed to start encryption\n");
|
||||||
return BT_SMP_ERR_UNSPECIFIED;
|
return BT_SMP_ERR_UNSPECIFIED;
|
||||||
}
|
}
|
||||||
|
@ -959,6 +975,7 @@ static uint8_t smp_pairing_random(struct bt_conn *conn, struct bt_buf *buf)
|
||||||
* security level upon encryption
|
* security level upon encryption
|
||||||
*/
|
*/
|
||||||
keys->type = get_keys_type(smp->method);
|
keys->type = get_keys_type(smp->method);
|
||||||
|
keys->enc_size = get_encryption_key_size(smp);
|
||||||
|
|
||||||
/* Rand and EDiv are 0 for the STK */
|
/* Rand and EDiv are 0 for the STK */
|
||||||
keys->slave_ltk.rand = 0;
|
keys->slave_ltk.rand = 0;
|
||||||
|
@ -1023,6 +1040,7 @@ static void bt_smp_distribute_keys(struct bt_conn *conn)
|
||||||
* on local distribution only.
|
* on local distribution only.
|
||||||
*/
|
*/
|
||||||
keys->type = get_keys_type(smp->method);
|
keys->type = get_keys_type(smp->method);
|
||||||
|
keys->enc_size = get_encryption_key_size(smp);
|
||||||
|
|
||||||
if (smp->local_dist & BT_SMP_DIST_ENC_KEY) {
|
if (smp->local_dist & BT_SMP_DIST_ENC_KEY) {
|
||||||
struct bt_smp_encrypt_info *info;
|
struct bt_smp_encrypt_info *info;
|
||||||
|
@ -1044,7 +1062,13 @@ static void bt_smp_distribute_keys(struct bt_conn *conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
info = bt_buf_add(buf, sizeof(*info));
|
info = bt_buf_add(buf, sizeof(*info));
|
||||||
memcpy(info->ltk, keys->slave_ltk.val, sizeof(info->ltk));
|
|
||||||
|
/* distributed only enc_size bytes of key */
|
||||||
|
memcpy(info->ltk, keys->slave_ltk.val, keys->enc_size);
|
||||||
|
if (keys->enc_size < sizeof(info->ltk)) {
|
||||||
|
memset(info->ltk + keys->enc_size, 0,
|
||||||
|
sizeof(info->ltk) - keys->enc_size);
|
||||||
|
}
|
||||||
|
|
||||||
bt_l2cap_send(conn, BT_L2CAP_CID_SMP, buf);
|
bt_l2cap_send(conn, BT_L2CAP_CID_SMP, buf);
|
||||||
|
|
||||||
|
@ -1319,8 +1343,7 @@ static uint8_t smp_security_request(struct bt_conn *conn, struct bt_buf *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bt_conn_le_start_encryption(conn, keys->ltk.rand, keys->ltk.ediv,
|
if (bt_conn_le_start_encryption(conn, keys->ltk.rand, keys->ltk.ediv,
|
||||||
keys->ltk.val,
|
keys->ltk.val, keys->enc_size) < 0) {
|
||||||
sizeof(keys->ltk.val)) < 0) {
|
|
||||||
return BT_SMP_ERR_UNSPECIFIED;
|
return BT_SMP_ERR_UNSPECIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct bt_smp_hdr {
|
||||||
#define BT_SMP_OOB_NOT_PRESENT 0x00
|
#define BT_SMP_OOB_NOT_PRESENT 0x00
|
||||||
#define BT_SMP_OOB_PRESENT 0x01
|
#define BT_SMP_OOB_PRESENT 0x01
|
||||||
|
|
||||||
#define BT_SMP_MIN_ENC_KEY_SIZE 16
|
#define BT_SMP_MIN_ENC_KEY_SIZE 7
|
||||||
#define BT_SMP_MAX_ENC_KEY_SIZE 16
|
#define BT_SMP_MAX_ENC_KEY_SIZE 16
|
||||||
|
|
||||||
#define BT_SMP_DIST_ENC_KEY 0x01
|
#define BT_SMP_DIST_ENC_KEY 0x01
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue