mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
Bluetooth: Switch SMP to crypto_cipher_encrypt_one()
SMP does ECB crypto on stack buffers. This is complicated and fragile, and it will not work if the stack is virtually allocated. Switch to the crypto_cipher interface, which is simpler and safer. Signed-off-by: Andy Lutomirski <luto@kernel.org> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Acked-by: Johan Hedberg <johan.hedberg@intel.com> Tested-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
a90a6e55f3
commit
a4770e1117
1 changed files with 28 additions and 39 deletions
|
@ -22,9 +22,9 @@
|
||||||
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
|
#include <linux/crypto.h>
|
||||||
#include <crypto/b128ops.h>
|
#include <crypto/b128ops.h>
|
||||||
#include <crypto/hash.h>
|
#include <crypto/hash.h>
|
||||||
#include <crypto/skcipher.h>
|
|
||||||
|
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
#include <net/bluetooth/hci_core.h>
|
#include <net/bluetooth/hci_core.h>
|
||||||
|
@ -88,7 +88,7 @@ struct smp_dev {
|
||||||
u8 min_key_size;
|
u8 min_key_size;
|
||||||
u8 max_key_size;
|
u8 max_key_size;
|
||||||
|
|
||||||
struct crypto_skcipher *tfm_aes;
|
struct crypto_cipher *tfm_aes;
|
||||||
struct crypto_shash *tfm_cmac;
|
struct crypto_shash *tfm_cmac;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ struct smp_chan {
|
||||||
u8 dhkey[32];
|
u8 dhkey[32];
|
||||||
u8 mackey[16];
|
u8 mackey[16];
|
||||||
|
|
||||||
struct crypto_skcipher *tfm_aes;
|
struct crypto_cipher *tfm_aes;
|
||||||
struct crypto_shash *tfm_cmac;
|
struct crypto_shash *tfm_cmac;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -361,10 +361,8 @@ static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16],
|
||||||
* s1 and ah.
|
* s1 and ah.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
|
static int smp_e(struct crypto_cipher *tfm, const u8 *k, u8 *r)
|
||||||
{
|
{
|
||||||
SKCIPHER_REQUEST_ON_STACK(req, tfm);
|
|
||||||
struct scatterlist sg;
|
|
||||||
uint8_t tmp[16], data[16];
|
uint8_t tmp[16], data[16];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -378,7 +376,7 @@ static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
|
||||||
/* The most significant octet of key corresponds to k[0] */
|
/* The most significant octet of key corresponds to k[0] */
|
||||||
swap_buf(k, tmp, 16);
|
swap_buf(k, tmp, 16);
|
||||||
|
|
||||||
err = crypto_skcipher_setkey(tfm, tmp, 16);
|
err = crypto_cipher_setkey(tfm, tmp, 16);
|
||||||
if (err) {
|
if (err) {
|
||||||
BT_ERR("cipher setkey failed: %d", err);
|
BT_ERR("cipher setkey failed: %d", err);
|
||||||
return err;
|
return err;
|
||||||
|
@ -387,16 +385,7 @@ static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
|
||||||
/* Most significant octet of plaintextData corresponds to data[0] */
|
/* Most significant octet of plaintextData corresponds to data[0] */
|
||||||
swap_buf(r, data, 16);
|
swap_buf(r, data, 16);
|
||||||
|
|
||||||
sg_init_one(&sg, data, 16);
|
crypto_cipher_encrypt_one(tfm, data, data);
|
||||||
|
|
||||||
skcipher_request_set_tfm(req, tfm);
|
|
||||||
skcipher_request_set_callback(req, 0, NULL, NULL);
|
|
||||||
skcipher_request_set_crypt(req, &sg, &sg, 16, NULL);
|
|
||||||
|
|
||||||
err = crypto_skcipher_encrypt(req);
|
|
||||||
skcipher_request_zero(req);
|
|
||||||
if (err)
|
|
||||||
BT_ERR("Encrypt data error %d", err);
|
|
||||||
|
|
||||||
/* Most significant octet of encryptedData corresponds to data[0] */
|
/* Most significant octet of encryptedData corresponds to data[0] */
|
||||||
swap_buf(data, r, 16);
|
swap_buf(data, r, 16);
|
||||||
|
@ -406,7 +395,7 @@ static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smp_c1(struct crypto_skcipher *tfm_aes, const u8 k[16],
|
static int smp_c1(struct crypto_cipher *tfm_aes, const u8 k[16],
|
||||||
const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
|
const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
|
||||||
const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
|
const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
|
||||||
{
|
{
|
||||||
|
@ -455,7 +444,7 @@ static int smp_c1(struct crypto_skcipher *tfm_aes, const u8 k[16],
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smp_s1(struct crypto_skcipher *tfm_aes, const u8 k[16],
|
static int smp_s1(struct crypto_cipher *tfm_aes, const u8 k[16],
|
||||||
const u8 r1[16], const u8 r2[16], u8 _r[16])
|
const u8 r1[16], const u8 r2[16], u8 _r[16])
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -471,7 +460,7 @@ static int smp_s1(struct crypto_skcipher *tfm_aes, const u8 k[16],
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smp_ah(struct crypto_skcipher *tfm, const u8 irk[16],
|
static int smp_ah(struct crypto_cipher *tfm, const u8 irk[16],
|
||||||
const u8 r[3], u8 res[3])
|
const u8 r[3], u8 res[3])
|
||||||
{
|
{
|
||||||
u8 _res[16];
|
u8 _res[16];
|
||||||
|
@ -759,7 +748,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
|
||||||
kzfree(smp->slave_csrk);
|
kzfree(smp->slave_csrk);
|
||||||
kzfree(smp->link_key);
|
kzfree(smp->link_key);
|
||||||
|
|
||||||
crypto_free_skcipher(smp->tfm_aes);
|
crypto_free_cipher(smp->tfm_aes);
|
||||||
crypto_free_shash(smp->tfm_cmac);
|
crypto_free_shash(smp->tfm_cmac);
|
||||||
|
|
||||||
/* Ensure that we don't leave any debug key around if debug key
|
/* Ensure that we don't leave any debug key around if debug key
|
||||||
|
@ -1359,9 +1348,9 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
|
||||||
if (!smp)
|
if (!smp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
smp->tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
|
smp->tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(smp->tfm_aes)) {
|
if (IS_ERR(smp->tfm_aes)) {
|
||||||
BT_ERR("Unable to create ECB crypto context");
|
BT_ERR("Unable to create AES crypto context");
|
||||||
kzfree(smp);
|
kzfree(smp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1369,7 +1358,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
|
||||||
smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
|
smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
|
||||||
if (IS_ERR(smp->tfm_cmac)) {
|
if (IS_ERR(smp->tfm_cmac)) {
|
||||||
BT_ERR("Unable to create CMAC crypto context");
|
BT_ERR("Unable to create CMAC crypto context");
|
||||||
crypto_free_skcipher(smp->tfm_aes);
|
crypto_free_cipher(smp->tfm_aes);
|
||||||
kzfree(smp);
|
kzfree(smp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3120,7 +3109,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
|
||||||
{
|
{
|
||||||
struct l2cap_chan *chan;
|
struct l2cap_chan *chan;
|
||||||
struct smp_dev *smp;
|
struct smp_dev *smp;
|
||||||
struct crypto_skcipher *tfm_aes;
|
struct crypto_cipher *tfm_aes;
|
||||||
struct crypto_shash *tfm_cmac;
|
struct crypto_shash *tfm_cmac;
|
||||||
|
|
||||||
if (cid == L2CAP_CID_SMP_BREDR) {
|
if (cid == L2CAP_CID_SMP_BREDR) {
|
||||||
|
@ -3132,9 +3121,9 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
|
||||||
if (!smp)
|
if (!smp)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
|
tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(tfm_aes)) {
|
if (IS_ERR(tfm_aes)) {
|
||||||
BT_ERR("Unable to create ECB crypto context");
|
BT_ERR("Unable to create AES crypto context");
|
||||||
kzfree(smp);
|
kzfree(smp);
|
||||||
return ERR_CAST(tfm_aes);
|
return ERR_CAST(tfm_aes);
|
||||||
}
|
}
|
||||||
|
@ -3142,7 +3131,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
|
||||||
tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
|
tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
|
||||||
if (IS_ERR(tfm_cmac)) {
|
if (IS_ERR(tfm_cmac)) {
|
||||||
BT_ERR("Unable to create CMAC crypto context");
|
BT_ERR("Unable to create CMAC crypto context");
|
||||||
crypto_free_skcipher(tfm_aes);
|
crypto_free_cipher(tfm_aes);
|
||||||
kzfree(smp);
|
kzfree(smp);
|
||||||
return ERR_CAST(tfm_cmac);
|
return ERR_CAST(tfm_cmac);
|
||||||
}
|
}
|
||||||
|
@ -3156,7 +3145,7 @@ create_chan:
|
||||||
chan = l2cap_chan_create();
|
chan = l2cap_chan_create();
|
||||||
if (!chan) {
|
if (!chan) {
|
||||||
if (smp) {
|
if (smp) {
|
||||||
crypto_free_skcipher(smp->tfm_aes);
|
crypto_free_cipher(smp->tfm_aes);
|
||||||
crypto_free_shash(smp->tfm_cmac);
|
crypto_free_shash(smp->tfm_cmac);
|
||||||
kzfree(smp);
|
kzfree(smp);
|
||||||
}
|
}
|
||||||
|
@ -3203,7 +3192,7 @@ static void smp_del_chan(struct l2cap_chan *chan)
|
||||||
smp = chan->data;
|
smp = chan->data;
|
||||||
if (smp) {
|
if (smp) {
|
||||||
chan->data = NULL;
|
chan->data = NULL;
|
||||||
crypto_free_skcipher(smp->tfm_aes);
|
crypto_free_cipher(smp->tfm_aes);
|
||||||
crypto_free_shash(smp->tfm_cmac);
|
crypto_free_shash(smp->tfm_cmac);
|
||||||
kzfree(smp);
|
kzfree(smp);
|
||||||
}
|
}
|
||||||
|
@ -3440,7 +3429,7 @@ void smp_unregister(struct hci_dev *hdev)
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_BT_SELFTEST_SMP)
|
#if IS_ENABLED(CONFIG_BT_SELFTEST_SMP)
|
||||||
|
|
||||||
static int __init test_ah(struct crypto_skcipher *tfm_aes)
|
static int __init test_ah(struct crypto_cipher *tfm_aes)
|
||||||
{
|
{
|
||||||
const u8 irk[16] = {
|
const u8 irk[16] = {
|
||||||
0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
|
0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
|
||||||
|
@ -3460,7 +3449,7 @@ static int __init test_ah(struct crypto_skcipher *tfm_aes)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init test_c1(struct crypto_skcipher *tfm_aes)
|
static int __init test_c1(struct crypto_cipher *tfm_aes)
|
||||||
{
|
{
|
||||||
const u8 k[16] = {
|
const u8 k[16] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
@ -3490,7 +3479,7 @@ static int __init test_c1(struct crypto_skcipher *tfm_aes)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init test_s1(struct crypto_skcipher *tfm_aes)
|
static int __init test_s1(struct crypto_cipher *tfm_aes)
|
||||||
{
|
{
|
||||||
const u8 k[16] = {
|
const u8 k[16] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
@ -3686,7 +3675,7 @@ static const struct file_operations test_smp_fops = {
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init run_selftests(struct crypto_skcipher *tfm_aes,
|
static int __init run_selftests(struct crypto_cipher *tfm_aes,
|
||||||
struct crypto_shash *tfm_cmac)
|
struct crypto_shash *tfm_cmac)
|
||||||
{
|
{
|
||||||
ktime_t calltime, delta, rettime;
|
ktime_t calltime, delta, rettime;
|
||||||
|
@ -3764,27 +3753,27 @@ done:
|
||||||
|
|
||||||
int __init bt_selftest_smp(void)
|
int __init bt_selftest_smp(void)
|
||||||
{
|
{
|
||||||
struct crypto_skcipher *tfm_aes;
|
struct crypto_cipher *tfm_aes;
|
||||||
struct crypto_shash *tfm_cmac;
|
struct crypto_shash *tfm_cmac;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
|
tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(tfm_aes)) {
|
if (IS_ERR(tfm_aes)) {
|
||||||
BT_ERR("Unable to create ECB crypto context");
|
BT_ERR("Unable to create AES crypto context");
|
||||||
return PTR_ERR(tfm_aes);
|
return PTR_ERR(tfm_aes);
|
||||||
}
|
}
|
||||||
|
|
||||||
tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
|
tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||||
if (IS_ERR(tfm_cmac)) {
|
if (IS_ERR(tfm_cmac)) {
|
||||||
BT_ERR("Unable to create CMAC crypto context");
|
BT_ERR("Unable to create CMAC crypto context");
|
||||||
crypto_free_skcipher(tfm_aes);
|
crypto_free_cipher(tfm_aes);
|
||||||
return PTR_ERR(tfm_cmac);
|
return PTR_ERR(tfm_cmac);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = run_selftests(tfm_aes, tfm_cmac);
|
err = run_selftests(tfm_aes, tfm_cmac);
|
||||||
|
|
||||||
crypto_free_shash(tfm_cmac);
|
crypto_free_shash(tfm_cmac);
|
||||||
crypto_free_skcipher(tfm_aes);
|
crypto_free_cipher(tfm_aes);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue