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:
Szymon Janc 2015-10-07 12:33:45 +02:00 committed by Anas Nashif
commit e896804811
5 changed files with 39 additions and 8 deletions

View file

@ -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,
keys->ltk.ediv,
keys->ltk.val,
sizeof(keys->ltk.val));
keys->enc_size);
goto done;
}

View file

@ -812,7 +812,14 @@ static void le_ltk_request(struct bt_buf *buf)
cp = bt_buf_add(buf, sizeof(*cp));
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);
} else {

View file

@ -54,6 +54,7 @@ struct bt_keys {
bt_addr_le_t addr;
int keys;
uint8_t type;
uint8_t enc_size;
struct bt_ltk slave_ltk;
struct bt_ltk ltk;

View file

@ -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->io_capability = bt_smp_io_capa;
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->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)
{
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
*/
keys->type = get_keys_type(smp->method);
keys->enc_size = get_encryption_key_size(smp);
/* 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");
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
*/
keys->type = get_keys_type(smp->method);
keys->enc_size = get_encryption_key_size(smp);
/* Rand and EDiv are 0 for the STK */
keys->slave_ltk.rand = 0;
@ -1023,6 +1040,7 @@ static void bt_smp_distribute_keys(struct bt_conn *conn)
* on local distribution only.
*/
keys->type = get_keys_type(smp->method);
keys->enc_size = get_encryption_key_size(smp);
if (smp->local_dist & BT_SMP_DIST_ENC_KEY) {
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));
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);
@ -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,
keys->ltk.val,
sizeof(keys->ltk.val)) < 0) {
keys->ltk.val, keys->enc_size) < 0) {
return BT_SMP_ERR_UNSPECIFIED;
}

View file

@ -47,7 +47,7 @@ struct bt_smp_hdr {
#define BT_SMP_OOB_NOT_PRESENT 0x00
#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_DIST_ENC_KEY 0x01