1 |
From e57121d08c38dabec15cf3e1e2ad46721af30cae Mon Sep 17 00:00:00 2001 |
2 |
From: Eric Biggers <ebiggers@google.com> |
3 |
Date: Mon, 11 Dec 2017 12:15:17 -0800 |
4 |
Subject: crypto: chacha20poly1305 - validate the digest size |
5 |
|
6 |
From: Eric Biggers <ebiggers@google.com> |
7 |
|
8 |
commit e57121d08c38dabec15cf3e1e2ad46721af30cae upstream. |
9 |
|
10 |
If the rfc7539 template was instantiated with a hash algorithm with |
11 |
digest size larger than 16 bytes (POLY1305_DIGEST_SIZE), then the digest |
12 |
overran the 'tag' buffer in 'struct chachapoly_req_ctx', corrupting the |
13 |
subsequent memory, including 'cryptlen'. This caused a crash during |
14 |
crypto_skcipher_decrypt(). |
15 |
|
16 |
Fix it by, when instantiating the template, requiring that the |
17 |
underlying hash algorithm has the digest size expected for Poly1305. |
18 |
|
19 |
Reproducer: |
20 |
|
21 |
#include <linux/if_alg.h> |
22 |
#include <sys/socket.h> |
23 |
#include <unistd.h> |
24 |
|
25 |
int main() |
26 |
{ |
27 |
int algfd, reqfd; |
28 |
struct sockaddr_alg addr = { |
29 |
.salg_type = "aead", |
30 |
.salg_name = "rfc7539(chacha20,sha256)", |
31 |
}; |
32 |
unsigned char buf[32] = { 0 }; |
33 |
|
34 |
algfd = socket(AF_ALG, SOCK_SEQPACKET, 0); |
35 |
bind(algfd, (void *)&addr, sizeof(addr)); |
36 |
setsockopt(algfd, SOL_ALG, ALG_SET_KEY, buf, sizeof(buf)); |
37 |
reqfd = accept(algfd, 0, 0); |
38 |
write(reqfd, buf, 16); |
39 |
read(reqfd, buf, 16); |
40 |
} |
41 |
|
42 |
Reported-by: syzbot <syzkaller@googlegroups.com> |
43 |
Fixes: 71ebc4d1b27d ("crypto: chacha20poly1305 - Add a ChaCha20-Poly1305 AEAD construction, RFC7539") |
44 |
Signed-off-by: Eric Biggers <ebiggers@google.com> |
45 |
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
46 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
47 |
|
48 |
--- |
49 |
crypto/chacha20poly1305.c | 6 +++++- |
50 |
1 file changed, 5 insertions(+), 1 deletion(-) |
51 |
|
52 |
--- a/crypto/chacha20poly1305.c |
53 |
+++ b/crypto/chacha20poly1305.c |
54 |
@@ -610,6 +610,11 @@ static int chachapoly_create(struct cryp |
55 |
algt->mask)); |
56 |
if (IS_ERR(poly)) |
57 |
return PTR_ERR(poly); |
58 |
+ poly_hash = __crypto_hash_alg_common(poly); |
59 |
+ |
60 |
+ err = -EINVAL; |
61 |
+ if (poly_hash->digestsize != POLY1305_DIGEST_SIZE) |
62 |
+ goto out_put_poly; |
63 |
|
64 |
err = -ENOMEM; |
65 |
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); |
66 |
@@ -618,7 +623,6 @@ static int chachapoly_create(struct cryp |
67 |
|
68 |
ctx = aead_instance_ctx(inst); |
69 |
ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize; |
70 |
- poly_hash = __crypto_hash_alg_common(poly); |
71 |
err = crypto_init_ahash_spawn(&ctx->poly, poly_hash, |
72 |
aead_crypto_instance(inst)); |
73 |
if (err) |