* [PATCH v2] crypto: hmac - require that the underlying hash algorithm is unkeyed
@ 2017-11-29 2:01 Eric Biggers
2017-11-29 5:24 ` Herbert Xu
0 siblings, 1 reply; 2+ messages in thread
From: Eric Biggers @ 2017-11-29 2:01 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: David S . Miller, linux-kernel, Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
Because the HMAC template didn't check that its underlying hash
algorithm is unkeyed, trying to use "hmac(hmac(sha3-512-generic))"
through AF_ALG or through KEYCTL_DH_COMPUTE resulted in the inner HMAC
being used without having been keyed, resulting in sha3_update() being
called without sha3_init(), causing a stack buffer overflow.
This is a very old bug, but it seems to have only started causing real
problems when SHA-3 support was added (requires CONFIG_CRYPTO_SHA3)
because the innermost hash's state is ->import()ed from a zeroed buffer,
and it just so happens that other hash algorithms are fine with that,
but SHA-3 is not. However, there could be arch or hardware-dependent
hash algorithms also affected; I couldn't test everything.
Fix the bug by introducing a function crypto_shash_alg_has_setkey()
which tests whether a shash algorithm is keyed. Then update the HMAC
template to require that its underlying hash algorithm is unkeyed.
Here is a reproducer:
#include <linux/if_alg.h>
#include <sys/socket.h>
int main()
{
int algfd;
struct sockaddr_alg addr = {
.salg_type = "hash",
.salg_name = "hmac(hmac(sha3-512-generic))",
};
char key[4096] = { 0 };
algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
bind(algfd, (const struct sockaddr *)&addr, sizeof(addr));
setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
}
Here was the KASAN report from syzbot:
BUG: KASAN: stack-out-of-bounds in memcpy include/linux/string.h:341 [inline]
BUG: KASAN: stack-out-of-bounds in sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161
Write of size 4096 at addr ffff8801cca07c40 by task syzkaller076574/3044
CPU: 1 PID: 3044 Comm: syzkaller076574 Not tainted 4.14.0-mm1+ #25
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:17 [inline]
dump_stack+0x194/0x257 lib/dump_stack.c:53
print_address_description+0x73/0x250 mm/kasan/report.c:252
kasan_report_error mm/kasan/report.c:351 [inline]
kasan_report+0x25b/0x340 mm/kasan/report.c:409
check_memory_region_inline mm/kasan/kasan.c:260 [inline]
check_memory_region+0x137/0x190 mm/kasan/kasan.c:267
memcpy+0x37/0x50 mm/kasan/kasan.c:303
memcpy include/linux/string.h:341 [inline]
sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161
crypto_shash_update+0xcb/0x220 crypto/shash.c:109
shash_finup_unaligned+0x2a/0x60 crypto/shash.c:151
crypto_shash_finup+0xc4/0x120 crypto/shash.c:165
hmac_finup+0x182/0x330 crypto/hmac.c:152
crypto_shash_finup+0xc4/0x120 crypto/shash.c:165
shash_digest_unaligned+0x9e/0xd0 crypto/shash.c:172
crypto_shash_digest+0xc4/0x120 crypto/shash.c:186
hmac_setkey+0x36a/0x690 crypto/hmac.c:66
crypto_shash_setkey+0xad/0x190 crypto/shash.c:64
shash_async_setkey+0x47/0x60 crypto/shash.c:207
crypto_ahash_setkey+0xaf/0x180 crypto/ahash.c:200
hash_setkey+0x40/0x90 crypto/algif_hash.c:446
alg_setkey crypto/af_alg.c:221 [inline]
alg_setsockopt+0x2a1/0x350 crypto/af_alg.c:254
SYSC_setsockopt net/socket.c:1851 [inline]
SyS_setsockopt+0x189/0x360 net/socket.c:1830
entry_SYSCALL_64_fastpath+0x1f/0x96
Reported-by: syzbot <syzkaller@googlegroups.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/hmac.c | 6 +++++-
crypto/shash.c | 5 +++--
include/crypto/internal/hash.h | 8 ++++++++
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 92871dc2a63e..e74730224f0a 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -195,11 +195,15 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
salg = shash_attr_alg(tb[1], 0, 0);
if (IS_ERR(salg))
return PTR_ERR(salg);
+ alg = &salg->base;
+ /* The underlying hash algorithm must be unkeyed */
err = -EINVAL;
+ if (crypto_shash_alg_has_setkey(salg))
+ goto out_put_alg;
+
ds = salg->digestsize;
ss = salg->statesize;
- alg = &salg->base;
if (ds > alg->cra_blocksize ||
ss < alg->cra_blocksize)
goto out_put_alg;
diff --git a/crypto/shash.c b/crypto/shash.c
index 325a14da5827..e849d3ee2e27 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -25,11 +25,12 @@
static const struct crypto_type crypto_shash_type;
-static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen)
+int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
+ unsigned int keylen)
{
return -ENOSYS;
}
+EXPORT_SYMBOL_GPL(shash_no_setkey);
static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
unsigned int keylen)
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index f0b44c16e88f..c2bae8da642c 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -82,6 +82,14 @@ int ahash_register_instance(struct crypto_template *tmpl,
struct ahash_instance *inst);
void ahash_free_instance(struct crypto_instance *inst);
+int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
+ unsigned int keylen);
+
+static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg)
+{
+ return alg->setkey != shash_no_setkey;
+}
+
int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn,
struct hash_alg_common *alg,
struct crypto_instance *inst);
--
2.15.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] crypto: hmac - require that the underlying hash algorithm is unkeyed
2017-11-29 2:01 [PATCH v2] crypto: hmac - require that the underlying hash algorithm is unkeyed Eric Biggers
@ 2017-11-29 5:24 ` Herbert Xu
0 siblings, 0 replies; 2+ messages in thread
From: Herbert Xu @ 2017-11-29 5:24 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, David S . Miller, linux-kernel, Eric Biggers, stable
On Tue, Nov 28, 2017 at 06:01:38PM -0800, Eric Biggers wrote:
> From: Eric Biggers <ebiggers@google.com>
>
> Because the HMAC template didn't check that its underlying hash
> algorithm is unkeyed, trying to use "hmac(hmac(sha3-512-generic))"
> through AF_ALG or through KEYCTL_DH_COMPUTE resulted in the inner HMAC
> being used without having been keyed, resulting in sha3_update() being
> called without sha3_init(), causing a stack buffer overflow.
>
> This is a very old bug, but it seems to have only started causing real
> problems when SHA-3 support was added (requires CONFIG_CRYPTO_SHA3)
> because the innermost hash's state is ->import()ed from a zeroed buffer,
> and it just so happens that other hash algorithms are fine with that,
> but SHA-3 is not. However, there could be arch or hardware-dependent
> hash algorithms also affected; I couldn't test everything.
>
> Fix the bug by introducing a function crypto_shash_alg_has_setkey()
> which tests whether a shash algorithm is keyed. Then update the HMAC
> template to require that its underlying hash algorithm is unkeyed.
>
> Here is a reproducer:
>
> #include <linux/if_alg.h>
> #include <sys/socket.h>
>
> int main()
> {
> int algfd;
> struct sockaddr_alg addr = {
> .salg_type = "hash",
> .salg_name = "hmac(hmac(sha3-512-generic))",
> };
> char key[4096] = { 0 };
>
> algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
> bind(algfd, (const struct sockaddr *)&addr, sizeof(addr));
> setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
> }
>
> Here was the KASAN report from syzbot:
>
> BUG: KASAN: stack-out-of-bounds in memcpy include/linux/string.h:341 [inline]
> BUG: KASAN: stack-out-of-bounds in sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161
> Write of size 4096 at addr ffff8801cca07c40 by task syzkaller076574/3044
>
> CPU: 1 PID: 3044 Comm: syzkaller076574 Not tainted 4.14.0-mm1+ #25
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> Call Trace:
> __dump_stack lib/dump_stack.c:17 [inline]
> dump_stack+0x194/0x257 lib/dump_stack.c:53
> print_address_description+0x73/0x250 mm/kasan/report.c:252
> kasan_report_error mm/kasan/report.c:351 [inline]
> kasan_report+0x25b/0x340 mm/kasan/report.c:409
> check_memory_region_inline mm/kasan/kasan.c:260 [inline]
> check_memory_region+0x137/0x190 mm/kasan/kasan.c:267
> memcpy+0x37/0x50 mm/kasan/kasan.c:303
> memcpy include/linux/string.h:341 [inline]
> sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161
> crypto_shash_update+0xcb/0x220 crypto/shash.c:109
> shash_finup_unaligned+0x2a/0x60 crypto/shash.c:151
> crypto_shash_finup+0xc4/0x120 crypto/shash.c:165
> hmac_finup+0x182/0x330 crypto/hmac.c:152
> crypto_shash_finup+0xc4/0x120 crypto/shash.c:165
> shash_digest_unaligned+0x9e/0xd0 crypto/shash.c:172
> crypto_shash_digest+0xc4/0x120 crypto/shash.c:186
> hmac_setkey+0x36a/0x690 crypto/hmac.c:66
> crypto_shash_setkey+0xad/0x190 crypto/shash.c:64
> shash_async_setkey+0x47/0x60 crypto/shash.c:207
> crypto_ahash_setkey+0xaf/0x180 crypto/ahash.c:200
> hash_setkey+0x40/0x90 crypto/algif_hash.c:446
> alg_setkey crypto/af_alg.c:221 [inline]
> alg_setsockopt+0x2a1/0x350 crypto/af_alg.c:254
> SYSC_setsockopt net/socket.c:1851 [inline]
> SyS_setsockopt+0x189/0x360 net/socket.c:1830
> entry_SYSCALL_64_fastpath+0x1f/0x96
>
> Reported-by: syzbot <syzkaller@googlegroups.com>
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Eric Biggers <ebiggers@google.com>
Patch applied. Thanks.
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-11-29 5:24 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-29 2:01 [PATCH v2] crypto: hmac - require that the underlying hash algorithm is unkeyed Eric Biggers
2017-11-29 5:24 ` Herbert Xu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).