Bluetooth: SMP: Add support for LTK derivation from LinkKey

This allows to derive LTK from Link Key using H6 function.

Jira: ZEP-625

Change-Id: Ife1e0d770f196174b6d7fc5e8074d76af49934cb
Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com>
This commit is contained in:
Szymon Janc 2016-09-09 16:09:09 +02:00 committed by Johan Hedberg
commit 68592f06f6

View file

@ -564,6 +564,21 @@ static int smp_g2(const uint8_t u[32], const uint8_t v[32],
return 0;
}
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);
}
#if defined(CONFIG_BLUETOOTH_BREDR)
static int smp_h6(const uint8_t w[16], const uint8_t key_id[4], uint8_t res[16])
{
@ -704,7 +719,61 @@ static void smp_br_init(struct bt_smp *smp)
static void smp_br_derive_ltk(struct bt_smp *smp)
{
/* TODO */
/* constants as specified in Core Spec Vol.3 Part H 2.4.2.5 */
static const uint8_t tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
static const uint8_t brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
struct bt_conn *conn = smp->chan.chan.conn;
struct bt_keys_link_key *link_key = conn->br.link_key;
struct bt_keys *keys;
bt_addr_le_t addr;
uint8_t ilk[16];
BT_DBG("");
if (!link_key) {
return;
}
#if defined(CONFIG_BLUETOOTH_SMP_FORCE_BREDR)
if (conn->encrypt != 0x02) {
BT_WARN("Using P192 Link Key for P256 LTK derivation");
}
#endif
/*
* For dualmode devices LE address is same as BR/EDR address and is of
* public type.
*/
bt_addr_copy(&addr.a, &conn->br.dst);
addr.type = BT_ADDR_LE_PUBLIC;
keys = bt_keys_get_type(BT_KEYS_LTK_P256, &addr);
if (!keys) {
BT_ERR("No keys space for %s", bt_addr_le_str(&addr));
return;
}
if (smp_h6(link_key->val, tmp2, ilk)) {
bt_keys_clear(keys);
return;
}
if (smp_h6(ilk, brle, keys->ltk.val)) {
bt_keys_clear(keys);
return;
}
keys->ltk.ediv = 0;
keys->ltk.rand = 0;
keys->enc_size = get_encryption_key_size(smp);
if (atomic_test_bit(link_key->flags, BT_LINK_KEY_AUTHENTICATED)) {
atomic_set_bit(keys->flags, BT_KEYS_AUTHENTICATED);
} else {
atomic_clear_bit(keys->flags, BT_KEYS_AUTHENTICATED);
}
BT_DBG("LTK derived from LinkKey");
}
static void smp_br_distribute_keys(struct bt_smp *smp)
@ -1245,21 +1314,6 @@ static uint8_t smp_send_pairing_random(struct bt_smp *smp)
return 0;
}
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);
}
#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
static void xor_128(const uint8_t p[16], const uint8_t q[16], uint8_t r[16])
{