* [PATCH 0/4] crypto: dh - input validation fixes
@ 2017-11-01 22:25 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
This series fixes several corner cases in the Diffie-Hellman key
exchange implementations:
- With CONFIG_DEBUG_SG=y and the software DH implementation, setting 'p'
to 0 caused a BUG_ON().
- Both the software and QAT DH implementations had a double-free bug in
the case where 'g' could not be allocated.
- With the QAT DH implementation, setting 'g' or 'key' larger than 'p'
caused a buffer underflow.
Note that in kernels configured with CONFIG_KEY_DH_OPERATIONS=y, these
bugs are reachable by unprivileged users via KEYCTL_DH_COMPUTE.
Eric Biggers (4):
crypto: dh - fix double free of ctx->p
crypto: dh - don't permit 'p' to be 0
crypto: qat - fix double free of ctx->p
crypto: dh - don't permit 'key' or 'g' size longer than 'p'
crypto/dh.c | 18 +++++++++---------
crypto/dh_helper.c | 16 ++++++++++++++++
drivers/crypto/qat/qat_common/qat_asym_algs.c | 15 ++++++++-------
3 files changed, 33 insertions(+), 16 deletions(-)
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 0/4] crypto: dh - input validation fixes
@ 2017-11-01 22:25 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers
From: Eric Biggers <ebiggers@google.com>
This series fixes several corner cases in the Diffie-Hellman key
exchange implementations:
- With CONFIG_DEBUG_SG=y and the software DH implementation, setting 'p'
to 0 caused a BUG_ON().
- Both the software and QAT DH implementations had a double-free bug in
the case where 'g' could not be allocated.
- With the QAT DH implementation, setting 'g' or 'key' larger than 'p'
caused a buffer underflow.
Note that in kernels configured with CONFIG_KEY_DH_OPERATIONS=y, these
bugs are reachable by unprivileged users via KEYCTL_DH_COMPUTE.
Eric Biggers (4):
crypto: dh - fix double free of ctx->p
crypto: dh - don't permit 'p' to be 0
crypto: qat - fix double free of ctx->p
crypto: dh - don't permit 'key' or 'g' size longer than 'p'
crypto/dh.c | 18 +++++++++---------
crypto/dh_helper.c | 16 ++++++++++++++++
drivers/crypto/qat/qat_common/qat_asym_algs.c | 15 ++++++++-------
3 files changed, 33 insertions(+), 16 deletions(-)
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 1/4] crypto: dh - fix double free of ctx->p
2017-11-01 22:25 ` Eric Biggers
@ 2017-11-01 22:25 ` Eric Biggers
-1 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
When setting the secret with the software Diffie-Hellman implementation,
if allocating 'g' failed (e.g. if it was longer than
MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and
once later when the crypto_kpp tfm was destroyed. Fix it by using
dh_free_ctx() in the error paths, as that sets the pointers to NULL.
KASAN report:
MPI: mpi too large (32760 bits)
==================================================================
BUG: KASAN: use-after-free in mpi_free+0x131/0x170
Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367
CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
dump_stack+0xb3/0x10b
? mpi_free+0x131/0x170
print_address_description+0x79/0x2a0
? mpi_free+0x131/0x170
kasan_report+0x236/0x340
? akcipher_register_instance+0x90/0x90
__asan_report_load4_noabort+0x14/0x20
mpi_free+0x131/0x170
? akcipher_register_instance+0x90/0x90
dh_exit_tfm+0x3d/0x140
crypto_kpp_exit_tfm+0x52/0x70
crypto_destroy_tfm+0xb3/0x250
__keyctl_dh_compute+0x640/0xe90
? kasan_slab_free+0x12f/0x180
? dh_data_from_key+0x240/0x240
? key_create_or_update+0x1ee/0xb20
? key_instantiate_and_link+0x440/0x440
? lock_contended+0xee0/0xee0
? kfree+0xcf/0x210
? SyS_add_key+0x268/0x340
keyctl_dh_compute+0xb3/0xf1
? __keyctl_dh_compute+0xe90/0xe90
? SyS_add_key+0x26d/0x340
? entry_SYSCALL_64_fastpath+0x5/0xbe
? trace_hardirqs_on_caller+0x3f4/0x560
SyS_keyctl+0x72/0x2c0
entry_SYSCALL_64_fastpath+0x1f/0xbe
RIP: 0033:0x43ccf9
RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa
RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9
RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017
RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936
R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000
R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000
Allocated by task 367:
save_stack_trace+0x16/0x20
kasan_kmalloc+0xeb/0x180
kmem_cache_alloc_trace+0x114/0x300
mpi_alloc+0x4b/0x230
mpi_read_raw_data+0xbe/0x360
dh_set_secret+0x1dc/0x460
__keyctl_dh_compute+0x623/0xe90
keyctl_dh_compute+0xb3/0xf1
SyS_keyctl+0x72/0x2c0
entry_SYSCALL_64_fastpath+0x1f/0xbe
Freed by task 367:
save_stack_trace+0x16/0x20
kasan_slab_free+0xab/0x180
kfree+0xb5/0x210
mpi_free+0xcb/0x170
dh_set_secret+0x2d7/0x460
__keyctl_dh_compute+0x623/0xe90
keyctl_dh_compute+0xb3/0xf1
SyS_keyctl+0x72/0x2c0
entry_SYSCALL_64_fastpath+0x1f/0xbe
Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation")
Cc: <stable@vger.kernel.org> # v4.8+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/dh.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/crypto/dh.c b/crypto/dh.c
index b1032a5c1bfa..b488f1782ced 100644
--- a/crypto/dh.c
+++ b/crypto/dh.c
@@ -71,10 +71,8 @@ static int dh_set_params(struct dh_ctx *ctx, struct dh *params)
return -EINVAL;
ctx->g = mpi_read_raw_data(params->g, params->g_size);
- if (!ctx->g) {
- mpi_free(ctx->p);
+ if (!ctx->g)
return -EINVAL;
- }
return 0;
}
@@ -89,18 +87,20 @@ static int dh_set_secret(struct crypto_kpp *tfm, const void *buf,
dh_free_ctx(ctx);
if (crypto_dh_decode_key(buf, len, ¶ms) < 0)
- return -EINVAL;
+ goto err_free_ctx;
if (dh_set_params(ctx, ¶ms) < 0)
- return -EINVAL;
+ goto err_free_ctx;
ctx->xa = mpi_read_raw_data(params.key, params.key_size);
- if (!ctx->xa) {
- dh_clear_params(ctx);
- return -EINVAL;
- }
+ if (!ctx->xa)
+ goto err_free_ctx;
return 0;
+
+err_free_ctx:
+ dh_free_ctx(ctx);
+ return -EINVAL;
}
static int dh_compute_value(struct kpp_request *req)
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 1/4] crypto: dh - fix double free of ctx->p
@ 2017-11-01 22:25 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
When setting the secret with the software Diffie-Hellman implementation,
if allocating 'g' failed (e.g. if it was longer than
MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and
once later when the crypto_kpp tfm was destroyed. Fix it by using
dh_free_ctx() in the error paths, as that sets the pointers to NULL.
KASAN report:
MPI: mpi too large (32760 bits)
=================================
BUG: KASAN: use-after-free in mpi_free+0x131/0x170
Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367
CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
dump_stack+0xb3/0x10b
? mpi_free+0x131/0x170
print_address_description+0x79/0x2a0
? mpi_free+0x131/0x170
kasan_report+0x236/0x340
? akcipher_register_instance+0x90/0x90
__asan_report_load4_noabort+0x14/0x20
mpi_free+0x131/0x170
? akcipher_register_instance+0x90/0x90
dh_exit_tfm+0x3d/0x140
crypto_kpp_exit_tfm+0x52/0x70
crypto_destroy_tfm+0xb3/0x250
__keyctl_dh_compute+0x640/0xe90
? kasan_slab_free+0x12f/0x180
? dh_data_from_key+0x240/0x240
? key_create_or_update+0x1ee/0xb20
? key_instantiate_and_link+0x440/0x440
? lock_contended+0xee0/0xee0
? kfree+0xcf/0x210
? SyS_add_key+0x268/0x340
keyctl_dh_compute+0xb3/0xf1
? __keyctl_dh_compute+0xe90/0xe90
? SyS_add_key+0x26d/0x340
? entry_SYSCALL_64_fastpath+0x5/0xbe
? trace_hardirqs_on_caller+0x3f4/0x560
SyS_keyctl+0x72/0x2c0
entry_SYSCALL_64_fastpath+0x1f/0xbe
RIP: 0033:0x43ccf9
RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa
RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9
RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017
RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936
R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000
R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000
Allocated by task 367:
save_stack_trace+0x16/0x20
kasan_kmalloc+0xeb/0x180
kmem_cache_alloc_trace+0x114/0x300
mpi_alloc+0x4b/0x230
mpi_read_raw_data+0xbe/0x360
dh_set_secret+0x1dc/0x460
__keyctl_dh_compute+0x623/0xe90
keyctl_dh_compute+0xb3/0xf1
SyS_keyctl+0x72/0x2c0
entry_SYSCALL_64_fastpath+0x1f/0xbe
Freed by task 367:
save_stack_trace+0x16/0x20
kasan_slab_free+0xab/0x180
kfree+0xb5/0x210
mpi_free+0xcb/0x170
dh_set_secret+0x2d7/0x460
__keyctl_dh_compute+0x623/0xe90
keyctl_dh_compute+0xb3/0xf1
SyS_keyctl+0x72/0x2c0
entry_SYSCALL_64_fastpath+0x1f/0xbe
Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation")
Cc: <stable@vger.kernel.org> # v4.8+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/dh.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/crypto/dh.c b/crypto/dh.c
index b1032a5c1bfa..b488f1782ced 100644
--- a/crypto/dh.c
+++ b/crypto/dh.c
@@ -71,10 +71,8 @@ static int dh_set_params(struct dh_ctx *ctx, struct dh *params)
return -EINVAL;
ctx->g = mpi_read_raw_data(params->g, params->g_size);
- if (!ctx->g) {
- mpi_free(ctx->p);
+ if (!ctx->g)
return -EINVAL;
- }
return 0;
}
@@ -89,18 +87,20 @@ static int dh_set_secret(struct crypto_kpp *tfm, const void *buf,
dh_free_ctx(ctx);
if (crypto_dh_decode_key(buf, len, ¶ms) < 0)
- return -EINVAL;
+ goto err_free_ctx;
if (dh_set_params(ctx, ¶ms) < 0)
- return -EINVAL;
+ goto err_free_ctx;
ctx->xa = mpi_read_raw_data(params.key, params.key_size);
- if (!ctx->xa) {
- dh_clear_params(ctx);
- return -EINVAL;
- }
+ if (!ctx->xa)
+ goto err_free_ctx;
return 0;
+
+err_free_ctx:
+ dh_free_ctx(ctx);
+ return -EINVAL;
}
static int dh_compute_value(struct kpp_request *req)
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 2/4] crypto: dh - don't permit 'p' to be 0
2017-11-01 22:25 ` Eric Biggers
@ 2017-11-01 22:25 ` Eric Biggers
-1 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
If 'p' is 0 for the software Diffie-Hellman implementation, then
dh_max_size() returns 0. In the case of KEYCTL_DH_COMPUTE, this causes
ZERO_SIZE_POINTER to be passed to sg_init_one(), which with
CONFIG_DEBUG_SG=y triggers the 'BUG_ON(!virt_addr_valid(buf));' in
sg_set_buf().
Fix this by making crypto_dh_decode_key() reject 0 for 'p'. p=0 makes
no sense for any DH implementation because 'p' is supposed to be a prime
number. Moreover, 'mod 0' is not mathematically defined.
Bug report:
kernel BUG at ./include/linux/scatterlist.h:140!
invalid opcode: 0000 [#1] SMP KASAN
CPU: 0 PID: 27112 Comm: syz-executor2 Not tainted 4.14.0-rc7-00010-gf5dbb5d0ce32-dirty #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.3-20171021_125229-anatol 04/01/2014
task: ffff88006caac0c0 task.stack: ffff88006c7c8000
RIP: 0010:sg_set_buf include/linux/scatterlist.h:140 [inline]
RIP: 0010:sg_init_one+0x1b3/0x240 lib/scatterlist.c:156
RSP: 0018:ffff88006c7cfb08 EFLAGS: 00010216
RAX: 0000000000010000 RBX: ffff88006c7cfe30 RCX: 00000000000064ee
RDX: ffffffff81cf64c3 RSI: ffffc90000d72000 RDI: ffffffff92e937e0
RBP: ffff88006c7cfb30 R08: ffffed000d8f9fab R09: ffff88006c7cfd30
R10: 0000000000000005 R11: ffffed000d8f9faa R12: ffff88006c7cfd30
R13: 0000000000000000 R14: 0000000000000010 R15: ffff88006c7cfc50
FS: 00007fce190fa700(0000) GS:ffff88003ea00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fffc6b33db8 CR3: 000000003cf64000 CR4: 00000000000006f0
Call Trace:
__keyctl_dh_compute+0xa95/0x19b0 security/keys/dh.c:360
keyctl_dh_compute+0xac/0x100 security/keys/dh.c:434
SYSC_keyctl security/keys/keyctl.c:1745 [inline]
SyS_keyctl+0x72/0x2c0 security/keys/keyctl.c:1641
entry_SYSCALL_64_fastpath+0x1f/0xbe
RIP: 0033:0x4585c9
RSP: 002b:00007fce190f9bd8 EFLAGS: 00000216 ORIG_RAX: 00000000000000fa
RAX: ffffffffffffffda RBX: 0000000000738020 RCX: 00000000004585c9
RDX: 000000002000d000 RSI: 0000000020000ff4 RDI: 0000000000000017
RBP: 0000000000000046 R08: 0000000020008000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000216 R12: 00007fff6e610cde
R13: 00007fff6e610cdf R14: 00007fce190fa700 R15: 0000000000000000
Code: 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 33 5b 45 89 6c 24 14 41 5c 41 5d 41 5e 41 5f 5d c3 e8 fd 8f 68 ff <0f> 0b e8 f6 8f 68 ff 0f 0b e8 ef 8f 68 ff 0f 0b e8 e8 8f 68 ff 20
RIP: sg_set_buf include/linux/scatterlist.h:140 [inline] RSP: ffff88006c7cfb08
RIP: sg_init_one+0x1b3/0x240 lib/scatterlist.c:156 RSP: ffff88006c7cfb08
Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation")
Cc: <stable@vger.kernel.org> # v4.8+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/dh_helper.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c
index 8ba8a3f82620..708ae20d2d3c 100644
--- a/crypto/dh_helper.c
+++ b/crypto/dh_helper.c
@@ -90,6 +90,14 @@ int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
params->p = (void *)(ptr + params->key_size);
params->g = (void *)(ptr + params->key_size + params->p_size);
+ /*
+ * Don't permit 'p' to be 0. It's not a prime number, and it's subject
+ * to corner cases such as 'mod 0' being undefined or
+ * crypto_kpp_maxsize() returning 0.
+ */
+ if (memchr_inv(params->p, 0, params->p_size) == NULL)
+ return -EINVAL;
+
return 0;
}
EXPORT_SYMBOL_GPL(crypto_dh_decode_key);
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 2/4] crypto: dh - don't permit 'p' to be 0
@ 2017-11-01 22:25 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
If 'p' is 0 for the software Diffie-Hellman implementation, then
dh_max_size() returns 0. In the case of KEYCTL_DH_COMPUTE, this causes
ZERO_SIZE_POINTER to be passed to sg_init_one(), which with
CONFIG_DEBUG_SG=y triggers the 'BUG_ON(!virt_addr_valid(buf));' in
sg_set_buf().
Fix this by making crypto_dh_decode_key() reject 0 for 'p'. p=0 makes
no sense for any DH implementation because 'p' is supposed to be a prime
number. Moreover, 'mod 0' is not mathematically defined.
Bug report:
kernel BUG at ./include/linux/scatterlist.h:140!
invalid opcode: 0000 [#1] SMP KASAN
CPU: 0 PID: 27112 Comm: syz-executor2 Not tainted 4.14.0-rc7-00010-gf5dbb5d0ce32-dirty #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.3-20171021_125229-anatol 04/01/2014
task: ffff88006caac0c0 task.stack: ffff88006c7c8000
RIP: 0010:sg_set_buf include/linux/scatterlist.h:140 [inline]
RIP: 0010:sg_init_one+0x1b3/0x240 lib/scatterlist.c:156
RSP: 0018:ffff88006c7cfb08 EFLAGS: 00010216
RAX: 0000000000010000 RBX: ffff88006c7cfe30 RCX: 00000000000064ee
RDX: ffffffff81cf64c3 RSI: ffffc90000d72000 RDI: ffffffff92e937e0
RBP: ffff88006c7cfb30 R08: ffffed000d8f9fab R09: ffff88006c7cfd30
R10: 0000000000000005 R11: ffffed000d8f9faa R12: ffff88006c7cfd30
R13: 0000000000000000 R14: 0000000000000010 R15: ffff88006c7cfc50
FS: 00007fce190fa700(0000) GS:ffff88003ea00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fffc6b33db8 CR3: 000000003cf64000 CR4: 00000000000006f0
Call Trace:
__keyctl_dh_compute+0xa95/0x19b0 security/keys/dh.c:360
keyctl_dh_compute+0xac/0x100 security/keys/dh.c:434
SYSC_keyctl security/keys/keyctl.c:1745 [inline]
SyS_keyctl+0x72/0x2c0 security/keys/keyctl.c:1641
entry_SYSCALL_64_fastpath+0x1f/0xbe
RIP: 0033:0x4585c9
RSP: 002b:00007fce190f9bd8 EFLAGS: 00000216 ORIG_RAX: 00000000000000fa
RAX: ffffffffffffffda RBX: 0000000000738020 RCX: 00000000004585c9
RDX: 000000002000d000 RSI: 0000000020000ff4 RDI: 0000000000000017
RBP: 0000000000000046 R08: 0000000020008000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000216 R12: 00007fff6e610cde
R13: 00007fff6e610cdf R14: 00007fce190fa700 R15: 0000000000000000
Code: 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 33 5b 45 89 6c 24 14 41 5c 41 5d 41 5e 41 5f 5d c3 e8 fd 8f 68 ff <0f> 0b e8 f6 8f 68 ff 0f 0b e8 ef 8f 68 ff 0f 0b e8 e8 8f 68 ff 20
RIP: sg_set_buf include/linux/scatterlist.h:140 [inline] RSP: ffff88006c7cfb08
RIP: sg_init_one+0x1b3/0x240 lib/scatterlist.c:156 RSP: ffff88006c7cfb08
Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation")
Cc: <stable@vger.kernel.org> # v4.8+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/dh_helper.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c
index 8ba8a3f82620..708ae20d2d3c 100644
--- a/crypto/dh_helper.c
+++ b/crypto/dh_helper.c
@@ -90,6 +90,14 @@ int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
params->p = (void *)(ptr + params->key_size);
params->g = (void *)(ptr + params->key_size + params->p_size);
+ /*
+ * Don't permit 'p' to be 0. It's not a prime number, and it's subject
+ * to corner cases such as 'mod 0' being undefined or
+ * crypto_kpp_maxsize() returning 0.
+ */
+ if (memchr_inv(params->p, 0, params->p_size) = NULL)
+ return -EINVAL;
+
return 0;
}
EXPORT_SYMBOL_GPL(crypto_dh_decode_key);
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 3/4] crypto: qat - fix double free of ctx->p
2017-11-01 22:25 ` Eric Biggers
@ 2017-11-01 22:25 ` Eric Biggers
-1 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
When setting the secret with the "qat-dh" Diffie-Hellman implementation,
if allocating 'g' failed, then 'p' was freed twice: once immediately,
and once later when the crypto_kpp tfm was destroyed. Fix it by using
qat_dh_clear_ctx() in the error paths, as that sets the pointers to
NULL.
Fixes: c9839143ebbf ("crypto: qat - Add DH support")
Cc: <stable@vger.kernel.org> # v4.8+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
drivers/crypto/qat/qat_common/qat_asym_algs.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
index 6f5dd68449c6..7655fdb499de 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -462,11 +462,8 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
}
ctx->g = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
- if (!ctx->g) {
- dma_free_coherent(dev, ctx->p_size, ctx->p, ctx->dma_p);
- ctx->p = NULL;
+ if (!ctx->g)
return -ENOMEM;
- }
memcpy(ctx->g + (ctx->p_size - params->g_size), params->g,
params->g_size);
@@ -507,18 +504,22 @@ static int qat_dh_set_secret(struct crypto_kpp *tfm, const void *buf,
ret = qat_dh_set_params(ctx, ¶ms);
if (ret < 0)
- return ret;
+ goto err_clear_ctx;
ctx->xa = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_xa,
GFP_KERNEL);
if (!ctx->xa) {
- qat_dh_clear_ctx(dev, ctx);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_clear_ctx;
}
memcpy(ctx->xa + (ctx->p_size - params.key_size), params.key,
params.key_size);
return 0;
+
+err_clear_ctx:
+ qat_dh_clear_ctx(dev, ctx);
+ return ret;
}
static unsigned int qat_dh_max_size(struct crypto_kpp *tfm)
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 3/4] crypto: qat - fix double free of ctx->p
@ 2017-11-01 22:25 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
When setting the secret with the "qat-dh" Diffie-Hellman implementation,
if allocating 'g' failed, then 'p' was freed twice: once immediately,
and once later when the crypto_kpp tfm was destroyed. Fix it by using
qat_dh_clear_ctx() in the error paths, as that sets the pointers to
NULL.
Fixes: c9839143ebbf ("crypto: qat - Add DH support")
Cc: <stable@vger.kernel.org> # v4.8+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
drivers/crypto/qat/qat_common/qat_asym_algs.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
index 6f5dd68449c6..7655fdb499de 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -462,11 +462,8 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
}
ctx->g = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
- if (!ctx->g) {
- dma_free_coherent(dev, ctx->p_size, ctx->p, ctx->dma_p);
- ctx->p = NULL;
+ if (!ctx->g)
return -ENOMEM;
- }
memcpy(ctx->g + (ctx->p_size - params->g_size), params->g,
params->g_size);
@@ -507,18 +504,22 @@ static int qat_dh_set_secret(struct crypto_kpp *tfm, const void *buf,
ret = qat_dh_set_params(ctx, ¶ms);
if (ret < 0)
- return ret;
+ goto err_clear_ctx;
ctx->xa = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_xa,
GFP_KERNEL);
if (!ctx->xa) {
- qat_dh_clear_ctx(dev, ctx);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_clear_ctx;
}
memcpy(ctx->xa + (ctx->p_size - params.key_size), params.key,
params.key_size);
return 0;
+
+err_clear_ctx:
+ qat_dh_clear_ctx(dev, ctx);
+ return ret;
}
static unsigned int qat_dh_max_size(struct crypto_kpp *tfm)
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 4/4] crypto: dh - don't permit 'key' or 'g' size longer than 'p'
2017-11-01 22:25 ` Eric Biggers
@ 2017-11-01 22:25 ` Eric Biggers
-1 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
The "qat-dh" DH implementation assumes that 'key' and 'g' can be copied
into a buffer with size 'p_size'. However it was never checked that
that was actually the case, which allowed users to cause a buffer
underflow via KEYCTL_DH_COMPUTE.
Fix this by updating crypto_dh_decode_key() to verify this precondition
for all DH implementations.
Fixes: c9839143ebbf ("crypto: qat - Add DH support")
Cc: <stable@vger.kernel.org> # v4.8+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/dh_helper.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c
index 708ae20d2d3c..7f00c771fe8d 100644
--- a/crypto/dh_helper.c
+++ b/crypto/dh_helper.c
@@ -83,6 +83,14 @@ int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
if (secret.len != crypto_dh_key_len(params))
return -EINVAL;
+ /*
+ * Don't permit the buffer for 'key' or 'g' to be larger than 'p', since
+ * some drivers assume otherwise.
+ */
+ if (params->key_size > params->p_size ||
+ params->g_size > params->p_size)
+ return -EINVAL;
+
/* Don't allocate memory. Set pointers to data within
* the given buffer
*/
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 4/4] crypto: dh - don't permit 'key' or 'g' size longer than 'p'
@ 2017-11-01 22:25 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-01 22:25 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
The "qat-dh" DH implementation assumes that 'key' and 'g' can be copied
into a buffer with size 'p_size'. However it was never checked that
that was actually the case, which allowed users to cause a buffer
underflow via KEYCTL_DH_COMPUTE.
Fix this by updating crypto_dh_decode_key() to verify this precondition
for all DH implementations.
Fixes: c9839143ebbf ("crypto: qat - Add DH support")
Cc: <stable@vger.kernel.org> # v4.8+
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/dh_helper.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c
index 708ae20d2d3c..7f00c771fe8d 100644
--- a/crypto/dh_helper.c
+++ b/crypto/dh_helper.c
@@ -83,6 +83,14 @@ int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
if (secret.len != crypto_dh_key_len(params))
return -EINVAL;
+ /*
+ * Don't permit the buffer for 'key' or 'g' to be larger than 'p', since
+ * some drivers assume otherwise.
+ */
+ if (params->key_size > params->p_size ||
+ params->g_size > params->p_size)
+ return -EINVAL;
+
/* Don't allocate memory. Set pointers to data within
* the given buffer
*/
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] crypto: dh - fix double free of ctx->p
2017-11-01 22:25 ` Eric Biggers
@ 2017-11-02 10:55 ` Tudor Ambarus
-1 siblings, 0 replies; 22+ messages in thread
From: Tudor Ambarus @ 2017-11-02 10:55 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: keyrings, Mat Martineau, Salvatore Benedetto, Stephan Mueller,
Eric Biggers, stable
Hi, Eric,
On 11/02/2017 12:25 AM, Eric Biggers wrote:
> When setting the secret with the software Diffie-Hellman implementation,
> if allocating 'g' failed (e.g. if it was longer than
> MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and
> once later when the crypto_kpp tfm was destroyed. Fix it by using
> dh_free_ctx() in the error paths, as that sets the pointers to NULL.
Other solution would be to have just an one-line patch that sets p to
NULL after freeing it. The benefit of just setting p to NULL and not
using dh_free_ctx() is that you'll spare some cpu cycles. If g fails,
g and a will already be NULL, so freeing them and set them to NULL is
redundant.
However, if you decide to always use dh_free_ctx(), you'll have to get
rid of dh_clear_params(), because it will be used just in dh_free_ctx().
You can copy dh_clear_params() body to dh_free_ctx().
Cheers,
ta
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] crypto: dh - fix double free of ctx->p
@ 2017-11-02 10:55 ` Tudor Ambarus
0 siblings, 0 replies; 22+ messages in thread
From: Tudor Ambarus @ 2017-11-02 10:55 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: keyrings, Mat Martineau, Salvatore Benedetto, Stephan Mueller,
Eric Biggers, stable
Hi, Eric,
On 11/02/2017 12:25 AM, Eric Biggers wrote:
> When setting the secret with the software Diffie-Hellman implementation,
> if allocating 'g' failed (e.g. if it was longer than
> MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and
> once later when the crypto_kpp tfm was destroyed. Fix it by using
> dh_free_ctx() in the error paths, as that sets the pointers to NULL.
Other solution would be to have just an one-line patch that sets p to
NULL after freeing it. The benefit of just setting p to NULL and not
using dh_free_ctx() is that you'll spare some cpu cycles. If g fails,
g and a will already be NULL, so freeing them and set them to NULL is
redundant.
However, if you decide to always use dh_free_ctx(), you'll have to get
rid of dh_clear_params(), because it will be used just in dh_free_ctx().
You can copy dh_clear_params() body to dh_free_ctx().
Cheers,
ta
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/4] crypto: dh - don't permit 'p' to be 0
2017-11-01 22:25 ` Eric Biggers
@ 2017-11-02 11:40 ` Tudor Ambarus
-1 siblings, 0 replies; 22+ messages in thread
From: Tudor Ambarus @ 2017-11-02 11:40 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: keyrings, Mat Martineau, Salvatore Benedetto, Stephan Mueller,
Eric Biggers, stable
Hi, Eric,
On 11/02/2017 12:25 AM, Eric Biggers wrote:
> If 'p' is 0 for the software Diffie-Hellman implementation, then
> dh_max_size() returns 0.
dh_set_secret() returns -EINVAL if p_len < 1536, see
dh_check_params_length(). What am I missing?
Cheers,
ta
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/4] crypto: dh - don't permit 'p' to be 0
@ 2017-11-02 11:40 ` Tudor Ambarus
0 siblings, 0 replies; 22+ messages in thread
From: Tudor Ambarus @ 2017-11-02 11:40 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: keyrings, Mat Martineau, Salvatore Benedetto, Stephan Mueller,
Eric Biggers, stable
Hi, Eric,
On 11/02/2017 12:25 AM, Eric Biggers wrote:
> If 'p' is 0 for the software Diffie-Hellman implementation, then
> dh_max_size() returns 0.
dh_set_secret() returns -EINVAL if p_len < 1536, see
dh_check_params_length(). What am I missing?
Cheers,
ta
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] crypto: dh - fix double free of ctx->p
2017-11-02 10:55 ` Tudor Ambarus
@ 2017-11-02 17:30 ` Eric Biggers
-1 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-02 17:30 UTC (permalink / raw)
To: Tudor Ambarus
Cc: linux-crypto, Herbert Xu, keyrings, Mat Martineau,
Salvatore Benedetto, Stephan Mueller, Eric Biggers, stable
Hi Tudor,
On Thu, Nov 02, 2017 at 12:55:56PM +0200, Tudor Ambarus wrote:
> Hi, Eric,
>
> On 11/02/2017 12:25 AM, Eric Biggers wrote:
> >When setting the secret with the software Diffie-Hellman implementation,
> >if allocating 'g' failed (e.g. if it was longer than
> >MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and
> >once later when the crypto_kpp tfm was destroyed. Fix it by using
> >dh_free_ctx() in the error paths, as that sets the pointers to NULL.
>
> Other solution would be to have just an one-line patch that sets p to
> NULL after freeing it. The benefit of just setting p to NULL and not
> using dh_free_ctx() is that you'll spare some cpu cycles. If g fails,
> g and a will already be NULL, so freeing them and set them to NULL is
> redundant.
>
> However, if you decide to always use dh_free_ctx(), you'll have to get
> rid of dh_clear_params(), because it will be used just in dh_free_ctx().
> You can copy dh_clear_params() body to dh_free_ctx().
>
This is on an error path, so a few cycles don't matter. I would much rather
have the simpler code, with less chance to introduce exploitable bugs.
Yes, I should inline dh_clear_params() into dh_free_ctx().
Eric
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] crypto: dh - fix double free of ctx->p
@ 2017-11-02 17:30 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-02 17:30 UTC (permalink / raw)
To: Tudor Ambarus
Cc: linux-crypto, Herbert Xu, keyrings, Mat Martineau,
Salvatore Benedetto, Stephan Mueller, Eric Biggers, stable
Hi Tudor,
On Thu, Nov 02, 2017 at 12:55:56PM +0200, Tudor Ambarus wrote:
> Hi, Eric,
>
> On 11/02/2017 12:25 AM, Eric Biggers wrote:
> >When setting the secret with the software Diffie-Hellman implementation,
> >if allocating 'g' failed (e.g. if it was longer than
> >MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and
> >once later when the crypto_kpp tfm was destroyed. Fix it by using
> >dh_free_ctx() in the error paths, as that sets the pointers to NULL.
>
> Other solution would be to have just an one-line patch that sets p to
> NULL after freeing it. The benefit of just setting p to NULL and not
> using dh_free_ctx() is that you'll spare some cpu cycles. If g fails,
> g and a will already be NULL, so freeing them and set them to NULL is
> redundant.
>
> However, if you decide to always use dh_free_ctx(), you'll have to get
> rid of dh_clear_params(), because it will be used just in dh_free_ctx().
> You can copy dh_clear_params() body to dh_free_ctx().
>
This is on an error path, so a few cycles don't matter. I would much rather
have the simpler code, with less chance to introduce exploitable bugs.
Yes, I should inline dh_clear_params() into dh_free_ctx().
Eric
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/4] crypto: dh - don't permit 'p' to be 0
2017-11-02 11:40 ` Tudor Ambarus
@ 2017-11-02 17:31 ` Eric Biggers
-1 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-02 17:31 UTC (permalink / raw)
To: Tudor Ambarus
Cc: linux-crypto, Herbert Xu, keyrings, Mat Martineau,
Salvatore Benedetto, Stephan Mueller, Eric Biggers, stable
On Thu, Nov 02, 2017 at 01:40:51PM +0200, Tudor Ambarus wrote:
> Hi, Eric,
>
> On 11/02/2017 12:25 AM, Eric Biggers wrote:
> >If 'p' is 0 for the software Diffie-Hellman implementation, then
> >dh_max_size() returns 0.
>
> dh_set_secret() returns -EINVAL if p_len < 1536, see
> dh_check_params_length(). What am I missing?
>
> Cheers,
> ta
You pass a buffer containing 0's, not a buffer of length 0. The buffer is
interpreted as an arbitrary precision integer, so any length buffer filled with
0's has the mathematical value 0.
Eric
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/4] crypto: dh - don't permit 'p' to be 0
@ 2017-11-02 17:31 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-02 17:31 UTC (permalink / raw)
To: Tudor Ambarus
Cc: linux-crypto, Herbert Xu, keyrings, Mat Martineau,
Salvatore Benedetto, Stephan Mueller, Eric Biggers, stable
On Thu, Nov 02, 2017 at 01:40:51PM +0200, Tudor Ambarus wrote:
> Hi, Eric,
>
> On 11/02/2017 12:25 AM, Eric Biggers wrote:
> >If 'p' is 0 for the software Diffie-Hellman implementation, then
> >dh_max_size() returns 0.
>
> dh_set_secret() returns -EINVAL if p_len < 1536, see
> dh_check_params_length(). What am I missing?
>
> Cheers,
> ta
You pass a buffer containing 0's, not a buffer of length 0. The buffer is
interpreted as an arbitrary precision integer, so any length buffer filled with
0's has the mathematical value 0.
Eric
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 3/4] crypto: qat - fix double free of ctx->p
2017-11-01 22:25 ` Eric Biggers
@ 2017-11-02 17:34 ` Eric Biggers
-1 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-02 17:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
On Wed, Nov 01, 2017 at 03:25:16PM -0700, Eric Biggers wrote:
> From: Eric Biggers <ebiggers@google.com>
>
> When setting the secret with the "qat-dh" Diffie-Hellman implementation,
> if allocating 'g' failed, then 'p' was freed twice: once immediately,
> and once later when the crypto_kpp tfm was destroyed. Fix it by using
> qat_dh_clear_ctx() in the error paths, as that sets the pointers to
> NULL.
>
> Fixes: c9839143ebbf ("crypto: qat - Add DH support")
> Cc: <stable@vger.kernel.org> # v4.8+
> Signed-off-by: Eric Biggers <ebiggers@google.com>
> ---
> drivers/crypto/qat/qat_common/qat_asym_algs.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
> index 6f5dd68449c6..7655fdb499de 100644
> --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
> +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
> @@ -462,11 +462,8 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
> }
>
> ctx->g = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
> - if (!ctx->g) {
> - dma_free_coherent(dev, ctx->p_size, ctx->p, ctx->dma_p);
> - ctx->p = NULL;
> + if (!ctx->g)
Sorry, I misread this code (and I didn't have the hardware to test this driver);
there is actually no bug here because it sets ctx->p to NULL.
I think we should still do this patch to simplify the code, but I'll update the
description to reflect that it's not actually fixing anything.
Eric
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 3/4] crypto: qat - fix double free of ctx->p
@ 2017-11-02 17:34 ` Eric Biggers
0 siblings, 0 replies; 22+ messages in thread
From: Eric Biggers @ 2017-11-02 17:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: keyrings, Tudor-Dan Ambarus, Mat Martineau, Salvatore Benedetto,
Stephan Mueller, Eric Biggers, stable
On Wed, Nov 01, 2017 at 03:25:16PM -0700, Eric Biggers wrote:
> From: Eric Biggers <ebiggers@google.com>
>
> When setting the secret with the "qat-dh" Diffie-Hellman implementation,
> if allocating 'g' failed, then 'p' was freed twice: once immediately,
> and once later when the crypto_kpp tfm was destroyed. Fix it by using
> qat_dh_clear_ctx() in the error paths, as that sets the pointers to
> NULL.
>
> Fixes: c9839143ebbf ("crypto: qat - Add DH support")
> Cc: <stable@vger.kernel.org> # v4.8+
> Signed-off-by: Eric Biggers <ebiggers@google.com>
> ---
> drivers/crypto/qat/qat_common/qat_asym_algs.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
> index 6f5dd68449c6..7655fdb499de 100644
> --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
> +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
> @@ -462,11 +462,8 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
> }
>
> ctx->g = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
> - if (!ctx->g) {
> - dma_free_coherent(dev, ctx->p_size, ctx->p, ctx->dma_p);
> - ctx->p = NULL;
> + if (!ctx->g)
Sorry, I misread this code (and I didn't have the hardware to test this driver);
there is actually no bug here because it sets ctx->p to NULL.
I think we should still do this patch to simplify the code, but I'll update the
description to reflect that it's not actually fixing anything.
Eric
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/4] crypto: dh - don't permit 'p' to be 0
2017-11-01 22:25 ` Eric Biggers
@ 2017-11-03 6:23 ` Tudor Ambarus
-1 siblings, 0 replies; 22+ messages in thread
From: Tudor Ambarus @ 2017-11-03 6:23 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: keyrings, Mat Martineau, Salvatore Benedetto, Stephan Mueller,
Eric Biggers, stable
On 11/02/2017 12:25 AM, Eric Biggers wrote:
> From: Eric Biggers <ebiggers@google.com>
>
> If 'p' is 0 for the software Diffie-Hellman implementation, then
> dh_max_size() returns 0. In the case of KEYCTL_DH_COMPUTE, this causes
> ZERO_SIZE_POINTER to be passed to sg_init_one(), which with
> CONFIG_DEBUG_SG=y triggers the 'BUG_ON(!virt_addr_valid(buf));' in
> sg_set_buf().
>
> Fix this by making crypto_dh_decode_key() reject 0 for 'p'. p=0 makes
> no sense for any DH implementation because 'p' is supposed to be a prime
> number. Moreover, 'mod 0' is not mathematically defined.
>
> Bug report:
>
> kernel BUG at ./include/linux/scatterlist.h:140!
> invalid opcode: 0000 [#1] SMP KASAN
> CPU: 0 PID: 27112 Comm: syz-executor2 Not tainted 4.14.0-rc7-00010-gf5dbb5d0ce32-dirty #7
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.3-20171021_125229-anatol 04/01/2014
> task: ffff88006caac0c0 task.stack: ffff88006c7c8000
> RIP: 0010:sg_set_buf include/linux/scatterlist.h:140 [inline]
> RIP: 0010:sg_init_one+0x1b3/0x240 lib/scatterlist.c:156
> RSP: 0018:ffff88006c7cfb08 EFLAGS: 00010216
> RAX: 0000000000010000 RBX: ffff88006c7cfe30 RCX: 00000000000064ee
> RDX: ffffffff81cf64c3 RSI: ffffc90000d72000 RDI: ffffffff92e937e0
> RBP: ffff88006c7cfb30 R08: ffffed000d8f9fab R09: ffff88006c7cfd30
> R10: 0000000000000005 R11: ffffed000d8f9faa R12: ffff88006c7cfd30
> R13: 0000000000000000 R14: 0000000000000010 R15: ffff88006c7cfc50
> FS: 00007fce190fa700(0000) GS:ffff88003ea00000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007fffc6b33db8 CR3: 000000003cf64000 CR4: 00000000000006f0
> Call Trace:
> __keyctl_dh_compute+0xa95/0x19b0 security/keys/dh.c:360
> keyctl_dh_compute+0xac/0x100 security/keys/dh.c:434
> SYSC_keyctl security/keys/keyctl.c:1745 [inline]
> SyS_keyctl+0x72/0x2c0 security/keys/keyctl.c:1641
> entry_SYSCALL_64_fastpath+0x1f/0xbe
> RIP: 0033:0x4585c9
> RSP: 002b:00007fce190f9bd8 EFLAGS: 00000216 ORIG_RAX: 00000000000000fa
> RAX: ffffffffffffffda RBX: 0000000000738020 RCX: 00000000004585c9
> RDX: 000000002000d000 RSI: 0000000020000ff4 RDI: 0000000000000017
> RBP: 0000000000000046 R08: 0000000020008000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000216 R12: 00007fff6e610cde
> R13: 00007fff6e610cdf R14: 00007fce190fa700 R15: 0000000000000000
> Code: 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 33 5b 45 89 6c 24 14 41 5c 41 5d 41 5e 41 5f 5d c3 e8 fd 8f 68 ff <0f> 0b e8 f6 8f 68 ff 0f 0b e8 ef 8f 68 ff 0f 0b e8 e8 8f 68 ff 20
> RIP: sg_set_buf include/linux/scatterlist.h:140 [inline] RSP: ffff88006c7cfb08
> RIP: sg_init_one+0x1b3/0x240 lib/scatterlist.c:156 RSP: ffff88006c7cfb08
>
> Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation")
> Cc: <stable@vger.kernel.org> # v4.8+
> Signed-off-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/4] crypto: dh - don't permit 'p' to be 0
@ 2017-11-03 6:23 ` Tudor Ambarus
0 siblings, 0 replies; 22+ messages in thread
From: Tudor Ambarus @ 2017-11-03 6:23 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: keyrings, Mat Martineau, Salvatore Benedetto, Stephan Mueller,
Eric Biggers, stable
On 11/02/2017 12:25 AM, Eric Biggers wrote:
> From: Eric Biggers <ebiggers@google.com>
>
> If 'p' is 0 for the software Diffie-Hellman implementation, then
> dh_max_size() returns 0. In the case of KEYCTL_DH_COMPUTE, this causes
> ZERO_SIZE_POINTER to be passed to sg_init_one(), which with
> CONFIG_DEBUG_SG=y triggers the 'BUG_ON(!virt_addr_valid(buf));' in
> sg_set_buf().
>
> Fix this by making crypto_dh_decode_key() reject 0 for 'p'. p=0 makes
> no sense for any DH implementation because 'p' is supposed to be a prime
> number. Moreover, 'mod 0' is not mathematically defined.
>
> Bug report:
>
> kernel BUG at ./include/linux/scatterlist.h:140!
> invalid opcode: 0000 [#1] SMP KASAN
> CPU: 0 PID: 27112 Comm: syz-executor2 Not tainted 4.14.0-rc7-00010-gf5dbb5d0ce32-dirty #7
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.3-20171021_125229-anatol 04/01/2014
> task: ffff88006caac0c0 task.stack: ffff88006c7c8000
> RIP: 0010:sg_set_buf include/linux/scatterlist.h:140 [inline]
> RIP: 0010:sg_init_one+0x1b3/0x240 lib/scatterlist.c:156
> RSP: 0018:ffff88006c7cfb08 EFLAGS: 00010216
> RAX: 0000000000010000 RBX: ffff88006c7cfe30 RCX: 00000000000064ee
> RDX: ffffffff81cf64c3 RSI: ffffc90000d72000 RDI: ffffffff92e937e0
> RBP: ffff88006c7cfb30 R08: ffffed000d8f9fab R09: ffff88006c7cfd30
> R10: 0000000000000005 R11: ffffed000d8f9faa R12: ffff88006c7cfd30
> R13: 0000000000000000 R14: 0000000000000010 R15: ffff88006c7cfc50
> FS: 00007fce190fa700(0000) GS:ffff88003ea00000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007fffc6b33db8 CR3: 000000003cf64000 CR4: 00000000000006f0
> Call Trace:
> __keyctl_dh_compute+0xa95/0x19b0 security/keys/dh.c:360
> keyctl_dh_compute+0xac/0x100 security/keys/dh.c:434
> SYSC_keyctl security/keys/keyctl.c:1745 [inline]
> SyS_keyctl+0x72/0x2c0 security/keys/keyctl.c:1641
> entry_SYSCALL_64_fastpath+0x1f/0xbe
> RIP: 0033:0x4585c9
> RSP: 002b:00007fce190f9bd8 EFLAGS: 00000216 ORIG_RAX: 00000000000000fa
> RAX: ffffffffffffffda RBX: 0000000000738020 RCX: 00000000004585c9
> RDX: 000000002000d000 RSI: 0000000020000ff4 RDI: 0000000000000017
> RBP: 0000000000000046 R08: 0000000020008000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000216 R12: 00007fff6e610cde
> R13: 00007fff6e610cdf R14: 00007fce190fa700 R15: 0000000000000000
> Code: 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 33 5b 45 89 6c 24 14 41 5c 41 5d 41 5e 41 5f 5d c3 e8 fd 8f 68 ff <0f> 0b e8 f6 8f 68 ff 0f 0b e8 ef 8f 68 ff 0f 0b e8 e8 8f 68 ff 20
> RIP: sg_set_buf include/linux/scatterlist.h:140 [inline] RSP: ffff88006c7cfb08
> RIP: sg_init_one+0x1b3/0x240 lib/scatterlist.c:156 RSP: ffff88006c7cfb08
>
> Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation")
> Cc: <stable@vger.kernel.org> # v4.8+
> Signed-off-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2017-11-03 6:23 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-01 22:25 [PATCH 0/4] crypto: dh - input validation fixes Eric Biggers
2017-11-01 22:25 ` Eric Biggers
2017-11-01 22:25 ` [PATCH 1/4] crypto: dh - fix double free of ctx->p Eric Biggers
2017-11-01 22:25 ` Eric Biggers
2017-11-02 10:55 ` Tudor Ambarus
2017-11-02 10:55 ` Tudor Ambarus
2017-11-02 17:30 ` Eric Biggers
2017-11-02 17:30 ` Eric Biggers
2017-11-01 22:25 ` [PATCH 2/4] crypto: dh - don't permit 'p' to be 0 Eric Biggers
2017-11-01 22:25 ` Eric Biggers
2017-11-02 11:40 ` Tudor Ambarus
2017-11-02 11:40 ` Tudor Ambarus
2017-11-02 17:31 ` Eric Biggers
2017-11-02 17:31 ` Eric Biggers
2017-11-03 6:23 ` Tudor Ambarus
2017-11-03 6:23 ` Tudor Ambarus
2017-11-01 22:25 ` [PATCH 3/4] crypto: qat - fix double free of ctx->p Eric Biggers
2017-11-01 22:25 ` Eric Biggers
2017-11-02 17:34 ` Eric Biggers
2017-11-02 17:34 ` Eric Biggers
2017-11-01 22:25 ` [PATCH 4/4] crypto: dh - don't permit 'key' or 'g' size longer than 'p' Eric Biggers
2017-11-01 22:25 ` Eric Biggers
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.