diff options
-rw-r--r-- | patches/cve/CVE-2017-17806-crypto-hmac-require-that-the-underlying-hash-algorit.patch | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/patches/cve/CVE-2017-17806-crypto-hmac-require-that-the-underlying-hash-algorit.patch b/patches/cve/CVE-2017-17806-crypto-hmac-require-that-the-underlying-hash-algorit.patch new file mode 100644 index 0000000..7bf40b3 --- /dev/null +++ b/patches/cve/CVE-2017-17806-crypto-hmac-require-that-the-underlying-hash-algorit.patch | |||
@@ -0,0 +1,157 @@ | |||
1 | From 902ae89f841de0c8d2857919296923f6332e174f Mon Sep 17 00:00:00 2001 | ||
2 | From: Eric Biggers <ebiggers@google.com> | ||
3 | Date: Tue, 28 Nov 2017 18:01:38 -0800 | ||
4 | Subject: [PATCH] crypto: hmac - require that the underlying hash algorithm is | ||
5 | unkeyed | ||
6 | |||
7 | commit af3ff8045bbf3e32f1a448542e73abb4c8ceb6f1 upstream. | ||
8 | |||
9 | Because the HMAC template didn't check that its underlying hash | ||
10 | algorithm is unkeyed, trying to use "hmac(hmac(sha3-512-generic))" | ||
11 | through AF_ALG or through KEYCTL_DH_COMPUTE resulted in the inner HMAC | ||
12 | being used without having been keyed, resulting in sha3_update() being | ||
13 | called without sha3_init(), causing a stack buffer overflow. | ||
14 | |||
15 | This is a very old bug, but it seems to have only started causing real | ||
16 | problems when SHA-3 support was added (requires CONFIG_CRYPTO_SHA3) | ||
17 | because the innermost hash's state is ->import()ed from a zeroed buffer, | ||
18 | and it just so happens that other hash algorithms are fine with that, | ||
19 | but SHA-3 is not. However, there could be arch or hardware-dependent | ||
20 | hash algorithms also affected; I couldn't test everything. | ||
21 | |||
22 | Fix the bug by introducing a function crypto_shash_alg_has_setkey() | ||
23 | which tests whether a shash algorithm is keyed. Then update the HMAC | ||
24 | template to require that its underlying hash algorithm is unkeyed. | ||
25 | |||
26 | Here is a reproducer: | ||
27 | |||
28 | #include <linux/if_alg.h> | ||
29 | #include <sys/socket.h> | ||
30 | |||
31 | int main() | ||
32 | { | ||
33 | int algfd; | ||
34 | struct sockaddr_alg addr = { | ||
35 | .salg_type = "hash", | ||
36 | .salg_name = "hmac(hmac(sha3-512-generic))", | ||
37 | }; | ||
38 | char key[4096] = { 0 }; | ||
39 | |||
40 | algfd = socket(AF_ALG, SOCK_SEQPACKET, 0); | ||
41 | bind(algfd, (const struct sockaddr *)&addr, sizeof(addr)); | ||
42 | setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key)); | ||
43 | } | ||
44 | |||
45 | Here was the KASAN report from syzbot: | ||
46 | |||
47 | BUG: KASAN: stack-out-of-bounds in memcpy include/linux/string.h:341 [inline] | ||
48 | BUG: KASAN: stack-out-of-bounds in sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161 | ||
49 | Write of size 4096 at addr ffff8801cca07c40 by task syzkaller076574/3044 | ||
50 | |||
51 | CPU: 1 PID: 3044 Comm: syzkaller076574 Not tainted 4.14.0-mm1+ #25 | ||
52 | Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 | ||
53 | Call Trace: | ||
54 | __dump_stack lib/dump_stack.c:17 [inline] | ||
55 | dump_stack+0x194/0x257 lib/dump_stack.c:53 | ||
56 | print_address_description+0x73/0x250 mm/kasan/report.c:252 | ||
57 | kasan_report_error mm/kasan/report.c:351 [inline] | ||
58 | kasan_report+0x25b/0x340 mm/kasan/report.c:409 | ||
59 | check_memory_region_inline mm/kasan/kasan.c:260 [inline] | ||
60 | check_memory_region+0x137/0x190 mm/kasan/kasan.c:267 | ||
61 | memcpy+0x37/0x50 mm/kasan/kasan.c:303 | ||
62 | memcpy include/linux/string.h:341 [inline] | ||
63 | sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161 | ||
64 | crypto_shash_update+0xcb/0x220 crypto/shash.c:109 | ||
65 | shash_finup_unaligned+0x2a/0x60 crypto/shash.c:151 | ||
66 | crypto_shash_finup+0xc4/0x120 crypto/shash.c:165 | ||
67 | hmac_finup+0x182/0x330 crypto/hmac.c:152 | ||
68 | crypto_shash_finup+0xc4/0x120 crypto/shash.c:165 | ||
69 | shash_digest_unaligned+0x9e/0xd0 crypto/shash.c:172 | ||
70 | crypto_shash_digest+0xc4/0x120 crypto/shash.c:186 | ||
71 | hmac_setkey+0x36a/0x690 crypto/hmac.c:66 | ||
72 | crypto_shash_setkey+0xad/0x190 crypto/shash.c:64 | ||
73 | shash_async_setkey+0x47/0x60 crypto/shash.c:207 | ||
74 | crypto_ahash_setkey+0xaf/0x180 crypto/ahash.c:200 | ||
75 | hash_setkey+0x40/0x90 crypto/algif_hash.c:446 | ||
76 | alg_setkey crypto/af_alg.c:221 [inline] | ||
77 | alg_setsockopt+0x2a1/0x350 crypto/af_alg.c:254 | ||
78 | SYSC_setsockopt net/socket.c:1851 [inline] | ||
79 | SyS_setsockopt+0x189/0x360 net/socket.c:1830 | ||
80 | entry_SYSCALL_64_fastpath+0x1f/0x96 | ||
81 | |||
82 | CVE: CVE-2017-17806 | ||
83 | Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.14.y&id=902ae89f841de0c8d2857919296923f6332e174f] | ||
84 | |||
85 | Reported-by: syzbot <syzkaller@googlegroups.com> | ||
86 | Signed-off-by: Eric Biggers <ebiggers@google.com> | ||
87 | Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> | ||
88 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
89 | Signed-off-by: Andreas Wellving <andreas.wellving@enea.com> | ||
90 | --- | ||
91 | crypto/hmac.c | 6 +++++- | ||
92 | crypto/shash.c | 5 +++-- | ||
93 | include/crypto/internal/hash.h | 8 ++++++++ | ||
94 | 3 files changed, 16 insertions(+), 3 deletions(-) | ||
95 | |||
96 | diff --git a/crypto/hmac.c b/crypto/hmac.c | ||
97 | index 92871dc2a63e..e74730224f0a 100644 | ||
98 | --- a/crypto/hmac.c | ||
99 | +++ b/crypto/hmac.c | ||
100 | @@ -195,11 +195,15 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) | ||
101 | salg = shash_attr_alg(tb[1], 0, 0); | ||
102 | if (IS_ERR(salg)) | ||
103 | return PTR_ERR(salg); | ||
104 | + alg = &salg->base; | ||
105 | |||
106 | + /* The underlying hash algorithm must be unkeyed */ | ||
107 | err = -EINVAL; | ||
108 | + if (crypto_shash_alg_has_setkey(salg)) | ||
109 | + goto out_put_alg; | ||
110 | + | ||
111 | ds = salg->digestsize; | ||
112 | ss = salg->statesize; | ||
113 | - alg = &salg->base; | ||
114 | if (ds > alg->cra_blocksize || | ||
115 | ss < alg->cra_blocksize) | ||
116 | goto out_put_alg; | ||
117 | diff --git a/crypto/shash.c b/crypto/shash.c | ||
118 | index 325a14da5827..e849d3ee2e27 100644 | ||
119 | --- a/crypto/shash.c | ||
120 | +++ b/crypto/shash.c | ||
121 | @@ -25,11 +25,12 @@ | ||
122 | |||
123 | static const struct crypto_type crypto_shash_type; | ||
124 | |||
125 | -static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, | ||
126 | - unsigned int keylen) | ||
127 | +int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, | ||
128 | + unsigned int keylen) | ||
129 | { | ||
130 | return -ENOSYS; | ||
131 | } | ||
132 | +EXPORT_SYMBOL_GPL(shash_no_setkey); | ||
133 | |||
134 | static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, | ||
135 | unsigned int keylen) | ||
136 | diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h | ||
137 | index f0b44c16e88f..c2bae8da642c 100644 | ||
138 | --- a/include/crypto/internal/hash.h | ||
139 | +++ b/include/crypto/internal/hash.h | ||
140 | @@ -82,6 +82,14 @@ int ahash_register_instance(struct crypto_template *tmpl, | ||
141 | struct ahash_instance *inst); | ||
142 | void ahash_free_instance(struct crypto_instance *inst); | ||
143 | |||
144 | +int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, | ||
145 | + unsigned int keylen); | ||
146 | + | ||
147 | +static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) | ||
148 | +{ | ||
149 | + return alg->setkey != shash_no_setkey; | ||
150 | +} | ||
151 | + | ||
152 | int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, | ||
153 | struct hash_alg_common *alg, | ||
154 | struct crypto_instance *inst); | ||
155 | -- | ||
156 | 2.20.1 | ||
157 | |||