Commit 6a77083a authored by Johan Hedberg's avatar Johan Hedberg Committed by Marcel Holtmann

Bluetooth: Add support for LE SC key generation

As the last step of the LE SC pairing process it's time to generate and
distribute keys. The generation part is unique to LE SC and so this
patch adds a dedicated function for it. We also clear the distribution
bits for keys which are not distributed with LE SC, so that the code
shared with legacy SMP will not go ahead and try to distribute them.
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 6433a9a2
...@@ -77,6 +77,7 @@ struct smp_chan { ...@@ -77,6 +77,7 @@ struct smp_chan {
struct smp_ltk *ltk; struct smp_ltk *ltk;
struct smp_ltk *slave_ltk; struct smp_ltk *slave_ltk;
struct smp_irk *remote_irk; struct smp_irk *remote_irk;
u8 *link_key;
unsigned long flags; unsigned long flags;
/* Secure Connections variables */ /* Secure Connections variables */
...@@ -321,6 +322,22 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) ...@@ -321,6 +322,22 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
return err; return err;
} }
static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
const u8 key_id[4], u8 res[16])
{
int err;
BT_DBG("w %16phN key_id %4phN", w, key_id);
err = aes_cmac(tfm_cmac, w, key_id, 4, res);
if (err)
return err;
BT_DBG("res %16phN", res);
return err;
}
static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3]) static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
{ {
u8 _res[16]; u8 _res[16];
...@@ -594,6 +611,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn) ...@@ -594,6 +611,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
kfree(smp->csrk); kfree(smp->csrk);
kfree(smp->slave_csrk); kfree(smp->slave_csrk);
kfree(smp->link_key);
crypto_free_blkcipher(smp->tfm_aes); crypto_free_blkcipher(smp->tfm_aes);
crypto_free_hash(smp->tfm_cmac); crypto_free_hash(smp->tfm_cmac);
...@@ -907,6 +925,37 @@ static void smp_notify_keys(struct l2cap_conn *conn) ...@@ -907,6 +925,37 @@ static void smp_notify_keys(struct l2cap_conn *conn)
bacpy(&smp->slave_ltk->bdaddr, &hcon->dst); bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
mgmt_new_ltk(hdev, smp->slave_ltk, persistent); mgmt_new_ltk(hdev, smp->slave_ltk, persistent);
} }
if (smp->link_key) {
hci_add_link_key(hdev, smp->conn->hcon, &hcon->dst,
smp->link_key, HCI_LK_AUTH_COMBINATION_P256,
0, NULL);
}
}
static void sc_generate_link_key(struct smp_chan *smp)
{
/* These constants are as specified in the core specification.
* In ASCII they spell out to 'tmp1' and 'lebr'.
*/
const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
smp->link_key = kzalloc(16, GFP_KERNEL);
if (!smp->link_key)
return;
if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
kfree(smp->link_key);
smp->link_key = NULL;
return;
}
if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
kfree(smp->link_key);
smp->link_key = NULL;
return;
}
} }
static void smp_allow_key_dist(struct smp_chan *smp) static void smp_allow_key_dist(struct smp_chan *smp)
...@@ -951,6 +1000,14 @@ static void smp_distribute_keys(struct smp_chan *smp) ...@@ -951,6 +1000,14 @@ static void smp_distribute_keys(struct smp_chan *smp)
*keydist &= req->resp_key_dist; *keydist &= req->resp_key_dist;
} }
if (test_bit(SMP_FLAG_SC, &smp->flags)) {
if (*keydist & SMP_DIST_LINK_KEY)
sc_generate_link_key(smp);
/* Clear the keys which are generated but not distributed */
*keydist &= ~SMP_SC_NO_DIST;
}
BT_DBG("keydist 0x%x", *keydist); BT_DBG("keydist 0x%x", *keydist);
if (*keydist & SMP_DIST_ENC_KEY) { if (*keydist & SMP_DIST_ENC_KEY) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment