Commit defce9e8 authored by Johan Hedberg's avatar Johan Hedberg Committed by Marcel Holtmann

Bluetooth: Make AES crypto context private to SMP

Now that we have per-adapter SMP data thanks to the root SMP L2CAP
channel we can take advantage of it and attach the AES crypto context
(only used for SMP) to it. This means that the smp_irk_matches() and
smp_generate_rpa() function can be converted to internally handle the
AES context.
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 70db83c4
...@@ -302,7 +302,6 @@ struct hci_dev { ...@@ -302,7 +302,6 @@ struct hci_dev {
__u32 req_status; __u32 req_status;
__u32 req_result; __u32 req_result;
struct crypto_blkcipher *tfm_aes;
void *smp_data; void *smp_data;
struct discovery_state discovery; struct discovery_state discovery;
......
...@@ -3234,11 +3234,8 @@ struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa) ...@@ -3234,11 +3234,8 @@ struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
return irk; return irk;
} }
if (!hdev->tfm_aes)
return NULL;
list_for_each_entry(irk, &hdev->identity_resolving_keys, list) { list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
if (smp_irk_matches(hdev->tfm_aes, irk->val, rpa)) { if (smp_irk_matches(hdev, irk->val, rpa)) {
bacpy(&irk->rpa, rpa); bacpy(&irk->rpa, rpa);
return irk; return irk;
} }
...@@ -3887,13 +3884,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, ...@@ -3887,13 +3884,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
!bacmp(&hdev->random_addr, &hdev->rpa)) !bacmp(&hdev->random_addr, &hdev->rpa))
return 0; return 0;
if (!hdev->tfm_aes) { err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
BT_ERR("%s crypto not available to generate RPA",
hdev->name);
return -EOPNOTSUPP;
}
err = smp_generate_rpa(hdev->tfm_aes, hdev->irk, &hdev->rpa);
if (err < 0) { if (err < 0) {
BT_ERR("%s failed to generate new RPA", hdev->name); BT_ERR("%s failed to generate new RPA", hdev->name);
return err; return err;
......
...@@ -139,12 +139,18 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3]) ...@@ -139,12 +139,18 @@ static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
return 0; return 0;
} }
bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16], bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
bdaddr_t *bdaddr)
{ {
struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm;
u8 hash[3]; u8 hash[3];
int err; int err;
if (!chan || !chan->data)
return false;
tfm = 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(tfm, irk, &bdaddr->b[3], hash);
...@@ -154,10 +160,17 @@ bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16], ...@@ -154,10 +160,17 @@ bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
return !memcmp(bdaddr->b, hash, 3); return !memcmp(bdaddr->b, hash, 3);
} }
int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa) int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
{ {
struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm;
int err; int err;
if (!chan || !chan->data)
return -EOPNOTSUPP;
tfm = 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 */
...@@ -1555,25 +1568,25 @@ static const struct l2cap_ops smp_root_chan_ops = { ...@@ -1555,25 +1568,25 @@ static const struct l2cap_ops smp_root_chan_ops = {
int smp_register(struct hci_dev *hdev) int smp_register(struct hci_dev *hdev)
{ {
struct l2cap_chan *chan; struct l2cap_chan *chan;
struct crypto_blkcipher *tfm_aes;
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
CRYPTO_ALG_ASYNC); if (IS_ERR(tfm_aes)) {
if (IS_ERR(hdev->tfm_aes)) { int err = PTR_ERR(tfm_aes);
int err = PTR_ERR(hdev->tfm_aes);
BT_ERR("Unable to create crypto context"); BT_ERR("Unable to create crypto context");
hdev->tfm_aes = NULL;
return err; return err;
} }
chan = l2cap_chan_create(); chan = l2cap_chan_create();
if (!chan) { if (!chan) {
crypto_free_blkcipher(hdev->tfm_aes); crypto_free_blkcipher(tfm_aes);
hdev->tfm_aes = NULL;
return -ENOMEM; return -ENOMEM;
} }
chan->data = tfm_aes;
/* FIXME: Using reserved 0x1f value for now - to be changed to /* FIXME: Using reserved 0x1f value for now - to be changed to
* L2CAP_CID_SMP once all functionality is in place. * L2CAP_CID_SMP once all functionality is in place.
*/ */
...@@ -1596,15 +1609,17 @@ int smp_register(struct hci_dev *hdev) ...@@ -1596,15 +1609,17 @@ int smp_register(struct hci_dev *hdev)
void smp_unregister(struct hci_dev *hdev) void smp_unregister(struct hci_dev *hdev)
{ {
struct l2cap_chan *chan = hdev->smp_data; struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm_aes;
if (!chan) if (!chan)
return; return;
BT_DBG("%s chan %p", hdev->name, chan); BT_DBG("%s chan %p", hdev->name, chan);
if (hdev->tfm_aes) { tfm_aes = chan->data;
crypto_free_blkcipher(hdev->tfm_aes); if (tfm_aes) {
hdev->tfm_aes = NULL; chan->data = NULL;
crypto_free_blkcipher(tfm_aes);
} }
hdev->smp_data = NULL; hdev->smp_data = NULL;
......
...@@ -132,9 +132,8 @@ int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); ...@@ -132,9 +132,8 @@ int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
void smp_chan_destroy(struct l2cap_conn *conn); void smp_chan_destroy(struct l2cap_conn *conn);
bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16], bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr);
bdaddr_t *bdaddr); int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa);
int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa);
int smp_register(struct hci_dev *hdev); int smp_register(struct hci_dev *hdev);
void smp_unregister(struct hci_dev *hdev); void smp_unregister(struct hci_dev *hdev);
......
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