From patchwork Thu Feb 1 16:06:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kleber Sacilotto de Souza X-Patchwork-Id: 868280 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 3zXQ310Ygrz9t4B; Fri, 2 Feb 2018 03:06:21 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1ehHNR-0003kX-8D; Thu, 01 Feb 2018 16:06:17 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1ehHNP-0003k6-7U for kernel-team@lists.ubuntu.com; Thu, 01 Feb 2018 16:06:15 +0000 Received: from mail-wm0-f69.google.com ([74.125.82.69]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1ehHNP-0007Oi-0Z for kernel-team@lists.ubuntu.com; Thu, 01 Feb 2018 16:06:15 +0000 Received: by mail-wm0-f69.google.com with SMTP id z83so1980620wmc.5 for ; Thu, 01 Feb 2018 08:06:15 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=sYDkLMkw2M/22eZqnLll6xrAsSU+ai5XjJ9oD9O3fng=; b=tkdTPvcYbixPcpi8I6rlyRgqNShjm6OrDhxNTRAdEg4lPQMeJwp8Rk8sw4jkJzBKUf ZCVIG7Brw/CTDDNpFrdvCs+QWPqS6b31fNknh8PdBMZOkaeZi19sGj4qVxsi3cQeTC+P eNSvuLqHqO2fVroyx66QNDqplEZOOuU6qauIpWIjbIaTY9f3UE56JZiiXPUTzhZ6KWSW ALmw9J9aOG/UokD6nWlu+SlkNG4crDaytwL5/rOc8Vlrb/PFCfVKqMwDF9QWuO3siWn5 Kwn9Loe1+u2ZJqQcvyxAvLwGCHYgFyyPfqAhJPulihHzflXPSZePyBT2ZlobKT5yWq4j PVPQ== X-Gm-Message-State: AKwxytcCXgAQh9LquDt9pMwRvHQ+BcJgqe8SyALdaNFu6R82GpXi2gSl EilLmA7nmbDIZ5NLvIBu9MfeXq2h9jKIJGnLidN9S5R28Bo+7YhIuP13SskIDplv+lXWzCjkK/P l0ihd5vCnYkToge7wJIkYGbwvKhgJYuE9ELVklxV7QQ== X-Received: by 10.223.171.161 with SMTP id s30mr13353295wrc.160.1517501174350; Thu, 01 Feb 2018 08:06:14 -0800 (PST) X-Google-Smtp-Source: AH8x227ipoNNYogwj5MC8K1ZEk3XAoD5g3nrZLuSZxPNwBljZNVOucd6Cv44H8uJWQRgirT8mMSnTQ== X-Received: by 10.223.171.161 with SMTP id s30mr13353280wrc.160.1517501174072; Thu, 01 Feb 2018 08:06:14 -0800 (PST) Received: from localhost ([2a02:8109:98c0:1604:e0bc:dea5:ede9:cfef]) by smtp.gmail.com with ESMTPSA id t141sm260099wmd.34.2018.02.01.08.06.12 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 01 Feb 2018 08:06:12 -0800 (PST) From: Kleber Sacilotto de Souza To: kernel-team@lists.ubuntu.com Subject: [SRU][Trusty][Artful][PATCH 1/1] crypto: hmac - require that the underlying hash algorithm is unkeyed Date: Thu, 1 Feb 2018 17:06:10 +0100 Message-Id: <20180201160610.4262-2-kleber.souza@canonical.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180201160610.4262-1-kleber.souza@canonical.com> References: <20180201160610.4262-1-kleber.souza@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Eric Biggers 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 #include 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 Cc: Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu CVE-2017-17806 (cherry picked from commit af3ff8045bbf3e32f1a448542e73abb4c8ceb6f1) Signed-off-by: Kleber Sacilotto de Souza --- 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 ade790b454e9..758688b4bc6b 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -197,11 +197,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 ac4d76350d1b..956979787efb 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -24,11 +24,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 821eae8cbd8c..0af57a99c6a1 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -70,6 +70,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);