Bluetooth: allocate data for kpp on heap
authorSalvatore Benedetto <salvatore.benedetto@intel.com>
Tue, 25 Apr 2017 15:59:47 +0000 (16:59 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Sun, 30 Apr 2017 10:22:05 +0000 (12:22 +0200)
Bluetooth would crash when computing ECDH keys with kpp
if VMAP_STACK is enabled. Fix by allocating data passed
to kpp on heap.

Fixes: 58771c1c ("Bluetooth: convert smp and selftest to crypto kpp
API")
Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/ecdh_helper.c
net/bluetooth/selftest.c

index b6d9aa15548535a4d99fbba759da90ff7a566f8d..579684bfc3224f51b1131fea4b87ce6e02626ba9 100644 (file)
@@ -59,16 +59,19 @@ bool compute_ecdh_secret(const u8 public_key[64], const u8 private_key[32],
        struct ecdh p;
        struct ecdh_completion result;
        struct scatterlist src, dst;
-       u8 tmp[64];
-       u8 *buf;
+       u8 *tmp, *buf;
        unsigned int buf_len;
        int err = -ENOMEM;
 
+       tmp = kmalloc(64, GFP_KERNEL);
+       if (!tmp)
+               return false;
+
        tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
        if (IS_ERR(tfm)) {
                pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n",
                       PTR_ERR(tfm));
-               return false;
+               goto free_tmp;
        }
 
        req = kpp_request_alloc(tfm, GFP_KERNEL);
@@ -128,6 +131,8 @@ free_req:
        kpp_request_free(req);
 free_kpp:
        crypto_free_kpp(tfm);
+free_tmp:
+       kfree(tmp);
        return (err == 0);
 }
 
@@ -138,18 +143,21 @@ bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32])
        struct ecdh p;
        struct ecdh_completion result;
        struct scatterlist dst;
-       u8 tmp[64];
-       u8 *buf;
+       u8 *tmp, *buf;
        unsigned int buf_len;
        int err = -ENOMEM;
        const unsigned short max_tries = 16;
        unsigned short tries = 0;
 
+       tmp = kmalloc(64, GFP_KERNEL);
+       if (!tmp)
+               return false;
+
        tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
        if (IS_ERR(tfm)) {
                pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n",
                       PTR_ERR(tfm));
-               return false;
+               goto free_tmp;
        }
 
        req = kpp_request_alloc(tfm, GFP_KERNEL);
@@ -219,5 +227,7 @@ free_req:
        kpp_request_free(req);
 free_kpp:
        crypto_free_kpp(tfm);
+free_tmp:
+       kfree(tmp);
        return (err == 0);
 }
index efef2815646e56fd8ffff06e7cf06a92ec816118..ee92c925ecc5d3ac42bc041f60924da80672e1b8 100644 (file)
@@ -142,18 +142,30 @@ static int __init test_ecdh_sample(const u8 priv_a[32], const u8 priv_b[32],
                                   const u8 pub_a[64], const u8 pub_b[64],
                                   const u8 dhkey[32])
 {
-       u8 dhkey_a[32], dhkey_b[32];
+       u8 *tmp, *dhkey_a, *dhkey_b;
+       int ret = 0;
+
+       tmp = kmalloc(64, GFP_KERNEL);
+       if (!tmp)
+               return -EINVAL;
+
+       dhkey_a = &tmp[0];
+       dhkey_b = &tmp[32];
 
        compute_ecdh_secret(pub_b, priv_a, dhkey_a);
        compute_ecdh_secret(pub_a, priv_b, dhkey_b);
 
-       if (memcmp(dhkey_a, dhkey, 32))
-               return -EINVAL;
+       if (memcmp(dhkey_a, dhkey, 32)) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        if (memcmp(dhkey_b, dhkey, 32))
-               return -EINVAL;
+               ret = -EINVAL;
 
-       return 0;
+out:
+       kfree(dhkey_a);
+       return ret;
 }
 
 static char test_ecdh_buffer[32];