[PATCH] mpi: Fix NULL ptr dereference in mpi_powm()

2016-11-23 Thread Andrey Ryabinin
Parsing certain certificates (see [1]) triggers NULL-ptr
dereference in mpi_powm():

BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [] mpi_powm+0xf8/0x10b0
...
Call Trace:
 [] _rsa_dec.isra.2+0x66/0x80
 [] rsa_verify+0x103/0x1c0
 [] pkcs1pad_verify+0x1c3/0x220
 [] public_key_verify_signature+0x3fa/0x4d0
 [] x509_check_for_self_signed+0x167/0x1e0
 [] x509_cert_parse+0x27e/0x300
 [] x509_key_preparse+0x3e/0x330
 [] asymmetric_key_preparse+0x6f/0x100
 [] key_create_or_update+0x260/0x5f0
 [] SyS_add_key+0x199/0x2a0
 [] entry_SYSCALL_64_fastpath+0x1e/0xad

This happens because mpi_alloc(0) doesn't allocate the limb space.
Fix this by allocating the result if needed.

Basically, this is a backport of libgcrypt patch [2].

[1] http://seclists.org/fulldisclosure/2016/Nov/76
[2] 
http://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=patch;h=6e1adb05d290aeeb1c230c763970695f4a538526

Fixes: cdec9cb5167a ("crypto: GnuPG based MPI lib - source files (part 1)")
Signed-off-by: Andrey Ryabinin 
Cc: 
---
 lib/mpi/mpi-pow.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c
index 5464c87..9e28d12 100644
--- a/lib/mpi/mpi-pow.c
+++ b/lib/mpi/mpi-pow.c
@@ -64,8 +64,13 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
if (!esize) {
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
 * depending on if MOD equals 1.  */
-   rp[0] = 1;
res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
+   if (res->nlimbs) {
+   if (RESIZE_IF_NEEDED(res, 1) < 0)
+   goto enomem;
+   rp = res->d;
+   rp[0] = 1;
+   }
res->sign = 0;
goto leave;
}
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] X.509: Fix double free in x509_cert_parse()

2016-11-23 Thread Andrey Ryabinin
We shouldn't free cert->pub->key in x509_cert_parse() because
x509_free_certificate() also does this:
BUG: Double free or freeing an invalid pointer
...
Call Trace:
 [] dump_stack+0x63/0x83
 [] kasan_object_err+0x21/0x70
 [] kasan_report_double_free+0x49/0x60
 [] kasan_slab_free+0x9d/0xc0
 [] kfree+0x8a/0x1a0
 [] public_key_free+0x1f/0x30
 [] x509_free_certificate+0x24/0x90
 [] x509_cert_parse+0x2bc/0x300
 [] x509_key_preparse+0x3e/0x330
 [] asymmetric_key_preparse+0x6f/0x100
 [] key_create_or_update+0x260/0x5f0
 [] SyS_add_key+0x199/0x2a0
 [] entry_SYSCALL_64_fastpath+0x1e/0xad
Object at 880110bd1900, in cache kmalloc-512 size: 512

Freed:
PID = 2579
[] save_stack_trace+0x1b/0x20
[] save_stack+0x46/0xd0
[] kasan_slab_free+0x73/0xc0
[] kfree+0x8a/0x1a0
[] x509_cert_parse+0x2a3/0x300
[] x509_key_preparse+0x3e/0x330
[] asymmetric_key_preparse+0x6f/0x100
[] key_create_or_update+0x260/0x5f0
[] SyS_add_key+0x199/0x2a0
[] entry_SYSCALL_64_fastpath+0x1e/0xad

Fixes: db6c43bd2132 ("crypto: KEYS: convert public key and digsig asym to the 
akcipher api")
Signed-off-by: Andrey Ryabinin 
Cc: 
---
 crypto/asymmetric_keys/x509_cert_parser.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/crypto/asymmetric_keys/x509_cert_parser.c 
b/crypto/asymmetric_keys/x509_cert_parser.c
index 865f46e..c80765b 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -133,7 +133,6 @@ struct x509_certificate *x509_cert_parse(const void *data, 
size_t datalen)
return cert;
 
 error_decode:
-   kfree(cert->pub->key);
kfree(ctx);
 error_no_ctx:
x509_free_certificate(cert);
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] crypto: acomp - don't use stack buffer in test_acomp()

2016-11-23 Thread Eric Biggers
With virtually-mapped stacks (CONFIG_VMAP_STACK=y), using the
scatterlist crypto API with stack buffers is not allowed, and with
appropriate debugging options will cause the
'BUG_ON(!virt_addr_valid(buf));' in sg_set_buf() to be triggered.
Use a heap buffer instead.

Fixes: d7db7a882deb ("crypto: acomp - update testmgr with support for acomp")
Signed-off-by: Eric Biggers 
---
 crypto/testmgr.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ded50b6..aca1b7b 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1448,17 +1448,21 @@ static int test_acomp(struct crypto_acomp *tfm, struct 
comp_testvec *ctemplate,
 {
const char *algo = crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm));
unsigned int i;
-   char output[COMP_BUF_SIZE];
+   char *output;
int ret;
struct scatterlist src, dst;
struct acomp_req *req;
struct tcrypt_result result;
 
+   output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
+   if (!output)
+   return -ENOMEM;
+
for (i = 0; i < ctcount; i++) {
unsigned int dlen = COMP_BUF_SIZE;
int ilen = ctemplate[i].inlen;
 
-   memset(output, 0, sizeof(output));
+   memset(output, 0, dlen);
init_completion();
sg_init_one(, ctemplate[i].input, ilen);
sg_init_one(, output, dlen);
@@ -1507,7 +1511,7 @@ static int test_acomp(struct crypto_acomp *tfm, struct 
comp_testvec *ctemplate,
unsigned int dlen = COMP_BUF_SIZE;
int ilen = dtemplate[i].inlen;
 
-   memset(output, 0, sizeof(output));
+   memset(output, 0, dlen);
init_completion();
sg_init_one(, dtemplate[i].input, ilen);
sg_init_one(, output, dlen);
@@ -1555,6 +1559,7 @@ static int test_acomp(struct crypto_acomp *tfm, struct 
comp_testvec *ctemplate,
ret = 0;
 
 out:
+   kfree(output);
return ret;
 }
 
-- 
2.8.0.rc3.226.g39d4020

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html