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.
Cc: Marcel Holtmann <[email protected]>
Cc: Gustavo Padovan <[email protected]>
Cc: Johan Hedberg <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: [email protected]
Cc: [email protected]
Acked-by: Herbert Xu <[email protected]>
Acked-and-tested-by: Johan Hedberg <[email protected]>
Signed-off-by: Andy Lutomirski <[email protected]>
---
net/bluetooth/smp.c | 67 ++++++++++++++++++++++-------------------------------
1 file changed, 28 insertions(+), 39 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 50976a6481f3..4c1a16a96ae5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -22,9 +22,9 @@
#include <linux/debugfs.h>
#include <linux/scatterlist.h>
+#include <linux/crypto.h>
#include <crypto/b128ops.h>
#include <crypto/hash.h>
-#include <crypto/skcipher.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -88,7 +88,7 @@ struct smp_dev {
u8 min_key_size;
u8 max_key_size;
- struct crypto_skcipher *tfm_aes;
+ struct crypto_cipher *tfm_aes;
struct crypto_shash *tfm_cmac;
};
@@ -127,7 +127,7 @@ struct smp_chan {
u8 dhkey[32];
u8 mackey[16];
- struct crypto_skcipher *tfm_aes;
+ struct crypto_cipher *tfm_aes;
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.
*/
-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];
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] */
swap_buf(k, tmp, 16);
- err = crypto_skcipher_setkey(tfm, tmp, 16);
+ err = crypto_cipher_setkey(tfm, tmp, 16);
if (err) {
BT_ERR("cipher setkey failed: %d", 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] */
swap_buf(r, data, 16);
- sg_init_one(&sg, data, 16);
-
- 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);
+ crypto_cipher_encrypt_one(tfm, data, data);
/* Most significant octet of encryptedData corresponds to data[0] */
swap_buf(data, r, 16);
@@ -406,7 +395,7 @@ static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
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 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;
}
-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])
{
int err;
@@ -471,7 +460,7 @@ static int smp_s1(struct crypto_skcipher *tfm_aes, const u8 k[16],
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])
{
u8 _res[16];
@@ -759,7 +748,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
kzfree(smp->slave_csrk);
kzfree(smp->link_key);
- crypto_free_skcipher(smp->tfm_aes);
+ crypto_free_cipher(smp->tfm_aes);
crypto_free_shash(smp->tfm_cmac);
/* 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)
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)) {
- BT_ERR("Unable to create ECB crypto context");
+ BT_ERR("Unable to create AES crypto context");
kzfree(smp);
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);
if (IS_ERR(smp->tfm_cmac)) {
BT_ERR("Unable to create CMAC crypto context");
- crypto_free_skcipher(smp->tfm_aes);
+ crypto_free_cipher(smp->tfm_aes);
kzfree(smp);
return NULL;
}
@@ -3120,7 +3109,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
{
struct l2cap_chan *chan;
struct smp_dev *smp;
- struct crypto_skcipher *tfm_aes;
+ struct crypto_cipher *tfm_aes;
struct crypto_shash *tfm_cmac;
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)
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)) {
- BT_ERR("Unable to create ECB crypto context");
+ BT_ERR("Unable to create AES crypto context");
kzfree(smp);
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);
if (IS_ERR(tfm_cmac)) {
BT_ERR("Unable to create CMAC crypto context");
- crypto_free_skcipher(tfm_aes);
+ crypto_free_cipher(tfm_aes);
kzfree(smp);
return ERR_CAST(tfm_cmac);
}
@@ -3156,7 +3145,7 @@ create_chan:
chan = l2cap_chan_create();
if (!chan) {
if (smp) {
- crypto_free_skcipher(smp->tfm_aes);
+ crypto_free_cipher(smp->tfm_aes);
crypto_free_shash(smp->tfm_cmac);
kzfree(smp);
}
@@ -3203,7 +3192,7 @@ static void smp_del_chan(struct l2cap_chan *chan)
smp = chan->data;
if (smp) {
chan->data = NULL;
- crypto_free_skcipher(smp->tfm_aes);
+ crypto_free_cipher(smp->tfm_aes);
crypto_free_shash(smp->tfm_cmac);
kzfree(smp);
}
@@ -3440,7 +3429,7 @@ void smp_unregister(struct hci_dev *hdev)
#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] = {
0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
@@ -3460,7 +3449,7 @@ static int __init test_ah(struct crypto_skcipher *tfm_aes)
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] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -3490,7 +3479,7 @@ static int __init test_c1(struct crypto_skcipher *tfm_aes)
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] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -3686,7 +3675,7 @@ static const struct file_operations test_smp_fops = {
.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)
{
ktime_t calltime, delta, rettime;
@@ -3764,27 +3753,27 @@ done:
int __init bt_selftest_smp(void)
{
- struct crypto_skcipher *tfm_aes;
+ struct crypto_cipher *tfm_aes;
struct crypto_shash *tfm_cmac;
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)) {
- BT_ERR("Unable to create ECB crypto context");
+ BT_ERR("Unable to create AES crypto context");
return PTR_ERR(tfm_aes);
}
tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm_cmac)) {
BT_ERR("Unable to create CMAC crypto context");
- crypto_free_skcipher(tfm_aes);
+ crypto_free_cipher(tfm_aes);
return PTR_ERR(tfm_cmac);
}
err = run_selftests(tfm_aes, tfm_cmac);
crypto_free_shash(tfm_cmac);
- crypto_free_skcipher(tfm_aes);
+ crypto_free_cipher(tfm_aes);
return err;
}
--
2.7.4
From: Andy Lutomirski <[email protected]>
Date: Thu, 14 Jul 2016 12:10:45 -0700
> On Mon, Jul 11, 2016 at 1:53 PM, Andy Lutomirski <[email protected]> wrote:
>> 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.
>
> Hi Dave-
>
> It looks like we're delaying virtually mapped stacks to 4.9. That
> means that there's time for this to go in through net-next. Could you
> queue it up?
This needs to go via the bluetooth maintainer, who will surely pass
it properly my way.
Hi Andy,
>> 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.
>
> Hi Dave-
>
> It looks like we're delaying virtually mapped stacks to 4.9. That
> means that there's time for this to go in through net-next. Could you
> queue it up?
it is actually already in net-next since we decided to let git handle any potential merge issue.
Regards
Marcel
On Mon, Jul 11, 2016 at 1:53 PM, Andy Lutomirski <[email protected]> wrote:
> 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.
Hi Dave-
It looks like we're delaying virtually mapped stacks to 4.9. That
means that there's time for this to go in through net-next. Could you
queue it up?
--Andy
>
> Cc: Marcel Holtmann <[email protected]>
> Cc: Gustavo Padovan <[email protected]>
> Cc: Johan Hedberg <[email protected]>
> Cc: "David S. Miller" <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Acked-by: Herbert Xu <[email protected]>
> Acked-and-tested-by: Johan Hedberg <[email protected]>
> Signed-off-by: Andy Lutomirski <[email protected]>
> ---
> net/bluetooth/smp.c | 67 ++++++++++++++++++++++-------------------------------
> 1 file changed, 28 insertions(+), 39 deletions(-)
>
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index 50976a6481f3..4c1a16a96ae5 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -22,9 +22,9 @@
>
> #include <linux/debugfs.h>
> #include <linux/scatterlist.h>
> +#include <linux/crypto.h>
> #include <crypto/b128ops.h>
> #include <crypto/hash.h>
> -#include <crypto/skcipher.h>
>
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
> @@ -88,7 +88,7 @@ struct smp_dev {
> u8 min_key_size;
> u8 max_key_size;
>
> - struct crypto_skcipher *tfm_aes;
> + struct crypto_cipher *tfm_aes;
> struct crypto_shash *tfm_cmac;
> };
>
> @@ -127,7 +127,7 @@ struct smp_chan {
> u8 dhkey[32];
> u8 mackey[16];
>
> - struct crypto_skcipher *tfm_aes;
> + struct crypto_cipher *tfm_aes;
> 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.
> */
>
> -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];
> 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] */
> swap_buf(k, tmp, 16);
>
> - err = crypto_skcipher_setkey(tfm, tmp, 16);
> + err = crypto_cipher_setkey(tfm, tmp, 16);
> if (err) {
> BT_ERR("cipher setkey failed: %d", 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] */
> swap_buf(r, data, 16);
>
> - sg_init_one(&sg, data, 16);
> -
> - 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);
> + crypto_cipher_encrypt_one(tfm, data, data);
>
> /* Most significant octet of encryptedData corresponds to data[0] */
> swap_buf(data, r, 16);
> @@ -406,7 +395,7 @@ static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
> 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 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;
> }
>
> -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])
> {
> int err;
> @@ -471,7 +460,7 @@ static int smp_s1(struct crypto_skcipher *tfm_aes, const u8 k[16],
> 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])
> {
> u8 _res[16];
> @@ -759,7 +748,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
> kzfree(smp->slave_csrk);
> kzfree(smp->link_key);
>
> - crypto_free_skcipher(smp->tfm_aes);
> + crypto_free_cipher(smp->tfm_aes);
> crypto_free_shash(smp->tfm_cmac);
>
> /* 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)
> 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)) {
> - BT_ERR("Unable to create ECB crypto context");
> + BT_ERR("Unable to create AES crypto context");
> kzfree(smp);
> 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);
> if (IS_ERR(smp->tfm_cmac)) {
> BT_ERR("Unable to create CMAC crypto context");
> - crypto_free_skcipher(smp->tfm_aes);
> + crypto_free_cipher(smp->tfm_aes);
> kzfree(smp);
> return NULL;
> }
> @@ -3120,7 +3109,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
> {
> struct l2cap_chan *chan;
> struct smp_dev *smp;
> - struct crypto_skcipher *tfm_aes;
> + struct crypto_cipher *tfm_aes;
> struct crypto_shash *tfm_cmac;
>
> 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)
> 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)) {
> - BT_ERR("Unable to create ECB crypto context");
> + BT_ERR("Unable to create AES crypto context");
> kzfree(smp);
> 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);
> if (IS_ERR(tfm_cmac)) {
> BT_ERR("Unable to create CMAC crypto context");
> - crypto_free_skcipher(tfm_aes);
> + crypto_free_cipher(tfm_aes);
> kzfree(smp);
> return ERR_CAST(tfm_cmac);
> }
> @@ -3156,7 +3145,7 @@ create_chan:
> chan = l2cap_chan_create();
> if (!chan) {
> if (smp) {
> - crypto_free_skcipher(smp->tfm_aes);
> + crypto_free_cipher(smp->tfm_aes);
> crypto_free_shash(smp->tfm_cmac);
> kzfree(smp);
> }
> @@ -3203,7 +3192,7 @@ static void smp_del_chan(struct l2cap_chan *chan)
> smp = chan->data;
> if (smp) {
> chan->data = NULL;
> - crypto_free_skcipher(smp->tfm_aes);
> + crypto_free_cipher(smp->tfm_aes);
> crypto_free_shash(smp->tfm_cmac);
> kzfree(smp);
> }
> @@ -3440,7 +3429,7 @@ void smp_unregister(struct hci_dev *hdev)
>
> #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] = {
> 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
> @@ -3460,7 +3449,7 @@ static int __init test_ah(struct crypto_skcipher *tfm_aes)
> 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] = {
> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> @@ -3490,7 +3479,7 @@ static int __init test_c1(struct crypto_skcipher *tfm_aes)
> 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] = {
> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> @@ -3686,7 +3675,7 @@ static const struct file_operations test_smp_fops = {
> .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)
> {
> ktime_t calltime, delta, rettime;
> @@ -3764,27 +3753,27 @@ done:
>
> int __init bt_selftest_smp(void)
> {
> - struct crypto_skcipher *tfm_aes;
> + struct crypto_cipher *tfm_aes;
> struct crypto_shash *tfm_cmac;
> 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)) {
> - BT_ERR("Unable to create ECB crypto context");
> + BT_ERR("Unable to create AES crypto context");
> return PTR_ERR(tfm_aes);
> }
>
> tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
> if (IS_ERR(tfm_cmac)) {
> BT_ERR("Unable to create CMAC crypto context");
> - crypto_free_skcipher(tfm_aes);
> + crypto_free_cipher(tfm_aes);
> return PTR_ERR(tfm_cmac);
> }
>
> err = run_selftests(tfm_aes, tfm_cmac);
>
> crypto_free_shash(tfm_cmac);
> - crypto_free_skcipher(tfm_aes);
> + crypto_free_cipher(tfm_aes);
>
> return err;
> }
> --
> 2.7.4
>
--
Andy Lutomirski
AMA Capital Management, LLC