return irk;
}
- if (!hdev->tfm_aes)
- return NULL;
-
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);
return irk;
}
!bacmp(&hdev->random_addr, &hdev->rpa))
return 0;
- if (!hdev->tfm_aes) {
- BT_ERR("%s crypto not available to generate RPA",
- hdev->name);
- return -EOPNOTSUPP;
- }
-
- err = smp_generate_rpa(hdev->tfm_aes, hdev->irk, &hdev->rpa);
+ err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
if (err < 0) {
BT_ERR("%s failed to generate new RPA", hdev->name);
return err;
return 0;
}
-bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
- bdaddr_t *bdaddr)
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
{
+ struct l2cap_chan *chan = hdev->smp_data;
+ struct crypto_blkcipher *tfm;
u8 hash[3];
int err;
+ if (!chan || !chan->data)
+ return false;
+
+ tfm = chan->data;
+
BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
err = smp_ah(tfm, irk, &bdaddr->b[3], hash);
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;
+ if (!chan || !chan->data)
+ return -EOPNOTSUPP;
+
+ tfm = chan->data;
+
get_random_bytes(&rpa->b[3], 3);
rpa->b[5] &= 0x3f; /* Clear two most significant bits */
int smp_register(struct hci_dev *hdev)
{
struct l2cap_chan *chan;
+ struct crypto_blkcipher *tfm_aes;
BT_DBG("%s", hdev->name);
- hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0,
- CRYPTO_ALG_ASYNC);
- if (IS_ERR(hdev->tfm_aes)) {
- int err = PTR_ERR(hdev->tfm_aes);
+ tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm_aes)) {
+ int err = PTR_ERR(tfm_aes);
BT_ERR("Unable to create crypto context");
- hdev->tfm_aes = NULL;
return err;
}
chan = l2cap_chan_create();
if (!chan) {
- crypto_free_blkcipher(hdev->tfm_aes);
- hdev->tfm_aes = NULL;
+ crypto_free_blkcipher(tfm_aes);
return -ENOMEM;
}
+ chan->data = tfm_aes;
+
/* FIXME: Using reserved 0x1f value for now - to be changed to
* L2CAP_CID_SMP once all functionality is in place.
*/
void smp_unregister(struct hci_dev *hdev)
{
struct l2cap_chan *chan = hdev->smp_data;
+ struct crypto_blkcipher *tfm_aes;
if (!chan)
return;
BT_DBG("%s chan %p", hdev->name, chan);
- if (hdev->tfm_aes) {
- crypto_free_blkcipher(hdev->tfm_aes);
- hdev->tfm_aes = NULL;
+ tfm_aes = chan->data;
+ if (tfm_aes) {
+ chan->data = NULL;
+ crypto_free_blkcipher(tfm_aes);
}
hdev->smp_data = NULL;
void smp_chan_destroy(struct l2cap_conn *conn);
-bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
- bdaddr_t *bdaddr);
-int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa);
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr);
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa);
int smp_register(struct hci_dev *hdev);
void smp_unregister(struct hci_dev *hdev);