Commit 88a479d9 authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Johan Hedberg

Bluetooth: Create SMP device structure for local crypto context

Every Bluetooth Low Energy controller requires a local crypto context
to handle the resolvable private addresses. At the moment this is just
a single crypto context, but for out-of-band data generation it will
require an additional. To facility this, create a struct smp_dev that
will hold all the extra information. This patch is just the refactoring
in preparation for future changes.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 276812ec
...@@ -73,6 +73,10 @@ enum { ...@@ -73,6 +73,10 @@ enum {
SMP_FLAG_OOB, SMP_FLAG_OOB,
}; };
struct smp_dev {
struct crypto_blkcipher *tfm_aes;
};
struct smp_chan { struct smp_chan {
struct l2cap_conn *conn; struct l2cap_conn *conn;
struct delayed_work security_timer; struct delayed_work security_timer;
...@@ -478,18 +482,18 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], ...@@ -478,18 +482,18 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
const bdaddr_t *bdaddr) const bdaddr_t *bdaddr)
{ {
struct l2cap_chan *chan = hdev->smp_data; struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm; struct smp_dev *smp;
u8 hash[3]; u8 hash[3];
int err; int err;
if (!chan || !chan->data) if (!chan || !chan->data)
return false; return false;
tfm = chan->data; smp = chan->data;
BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk); BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
err = smp_ah(tfm, irk, &bdaddr->b[3], hash); err = smp_ah(smp->tfm_aes, irk, &bdaddr->b[3], hash);
if (err) if (err)
return false; return false;
...@@ -499,20 +503,20 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], ...@@ -499,20 +503,20 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
{ {
struct l2cap_chan *chan = hdev->smp_data; struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm; struct smp_dev *smp;
int err; int err;
if (!chan || !chan->data) if (!chan || !chan->data)
return -EOPNOTSUPP; return -EOPNOTSUPP;
tfm = chan->data; smp = chan->data;
get_random_bytes(&rpa->b[3], 3); get_random_bytes(&rpa->b[3], 3);
rpa->b[5] &= 0x3f; /* Clear two most significant bits */ rpa->b[5] &= 0x3f; /* Clear two most significant bits */
rpa->b[5] |= 0x40; /* Set second most significant bit */ rpa->b[5] |= 0x40; /* Set second most significant bit */
err = smp_ah(tfm, irk, &rpa->b[3], rpa->b); err = smp_ah(smp->tfm_aes, irk, &rpa->b[3], rpa->b);
if (err < 0) if (err < 0)
return err; return err;
...@@ -2930,27 +2934,36 @@ static const struct l2cap_ops smp_root_chan_ops = { ...@@ -2930,27 +2934,36 @@ static const struct l2cap_ops smp_root_chan_ops = {
static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
{ {
struct l2cap_chan *chan; struct l2cap_chan *chan;
struct crypto_blkcipher *tfm_aes; struct smp_dev *smp;
struct crypto_blkcipher *tfm_aes;
if (cid == L2CAP_CID_SMP_BREDR) { if (cid == L2CAP_CID_SMP_BREDR) {
tfm_aes = NULL; smp = NULL;
goto create_chan; goto create_chan;
} }
tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 0); smp = kzalloc(sizeof(*smp), GFP_KERNEL);
if (!smp)
return ERR_PTR(-ENOMEM);
tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm_aes)) { if (IS_ERR(tfm_aes)) {
BT_ERR("Unable to create crypto context"); BT_ERR("Unable to create ECB crypto context");
kzfree(smp);
return ERR_CAST(tfm_aes); return ERR_CAST(tfm_aes);
} }
smp->tfm_aes = tfm_aes;
create_chan: create_chan:
chan = l2cap_chan_create(); chan = l2cap_chan_create();
if (!chan) { if (!chan) {
crypto_free_blkcipher(tfm_aes); crypto_free_blkcipher(smp->tfm_aes);
kzfree(smp);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
chan->data = tfm_aes; chan->data = smp;
l2cap_add_scid(chan, cid); l2cap_add_scid(chan, cid);
...@@ -2983,14 +2996,16 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) ...@@ -2983,14 +2996,16 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
static void smp_del_chan(struct l2cap_chan *chan) static void smp_del_chan(struct l2cap_chan *chan)
{ {
struct crypto_blkcipher *tfm_aes; struct smp_dev *smp;
BT_DBG("chan %p", chan); BT_DBG("chan %p", chan);
tfm_aes = chan->data; smp = chan->data;
if (tfm_aes) { if (smp) {
chan->data = NULL; chan->data = NULL;
crypto_free_blkcipher(tfm_aes); if (smp->tfm_aes)
crypto_free_blkcipher(smp->tfm_aes);
kzfree(smp);
} }
l2cap_chan_put(chan); l2cap_chan_put(chan);
......
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