diff options
author | jsing <> | 2014-06-24 18:12:09 +0000 |
---|---|---|
committer | jsing <> | 2014-06-24 18:12:09 +0000 |
commit | 6a9c4d13fc97c0ad186e4d15839ef568659ebf6f (patch) | |
tree | 77b512bc366b09aa3f9194007a50fa04d944872c | |
parent | 8bcb66ae2fbdc9abd5d6029738e23c72c75bad68 (diff) | |
download | openbsd-6a9c4d13fc97c0ad186e4d15839ef568659ebf6f.tar.gz openbsd-6a9c4d13fc97c0ad186e4d15839ef568659ebf6f.tar.bz2 openbsd-6a9c4d13fc97c0ad186e4d15839ef568659ebf6f.zip |
If a chacha operation does not consume all of the generated key stream,
ensure that we save it and consume it on subsequent writes. Otherwise we
end up discarding part of the key stream and instead generate a new block
at the start of the next write.
This was only an issue for callers that did multiple writes that are not
multiples of 64 bytes - in particular, the ChaCha20Poly1305 usage does not
hit this problem since it performs encryption in a single-shot. For the
same reason, this is also a non-issue when openssl(1) is used to encrypt
with ChaCha.
Issue identified by insane coder; reported to bugs@ by Joseph M. Schwartz.
ok beck@
-rw-r--r-- | src/lib/libcrypto/chacha/chacha-merged.c | 32 | ||||
-rw-r--r-- | src/lib/libcrypto/chacha/chacha.c | 17 | ||||
-rw-r--r-- | src/lib/libcrypto/chacha/chacha.h | 4 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/chacha/chacha-merged.c | 32 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/chacha/chacha.c | 17 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/chacha/chacha.h | 4 |
6 files changed, 92 insertions, 14 deletions
diff --git a/src/lib/libcrypto/chacha/chacha-merged.c b/src/lib/libcrypto/chacha/chacha-merged.c index 25092b16da..a665fb316f 100644 --- a/src/lib/libcrypto/chacha/chacha-merged.c +++ b/src/lib/libcrypto/chacha/chacha-merged.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: chacha-merged.c,v 1.5 2014/06/24 17:48:30 jsing Exp $ */ | 1 | /* $OpenBSD: chacha-merged.c,v 1.6 2014/06/24 18:12:09 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | chacha-merged.c version 20080118 | 3 | chacha-merged.c version 20080118 |
4 | D. J. Bernstein | 4 | D. J. Bernstein |
@@ -7,16 +7,18 @@ Public domain. | |||
7 | 7 | ||
8 | #include <sys/types.h> | 8 | #include <sys/types.h> |
9 | 9 | ||
10 | struct chacha_ctx { | ||
11 | u_int input[16]; | ||
12 | }; | ||
13 | |||
14 | #define CHACHA_MINKEYLEN 16 | 10 | #define CHACHA_MINKEYLEN 16 |
15 | #define CHACHA_NONCELEN 8 | 11 | #define CHACHA_NONCELEN 8 |
16 | #define CHACHA_CTRLEN 8 | 12 | #define CHACHA_CTRLEN 8 |
17 | #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) | 13 | #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) |
18 | #define CHACHA_BLOCKLEN 64 | 14 | #define CHACHA_BLOCKLEN 64 |
19 | 15 | ||
16 | struct chacha_ctx { | ||
17 | u_int input[16]; | ||
18 | u_int8_t ks[CHACHA_BLOCKLEN]; | ||
19 | u_int8_t unused; | ||
20 | }; | ||
21 | |||
20 | static inline void chacha_keysetup(struct chacha_ctx *x, const u_char *k, | 22 | static inline void chacha_keysetup(struct chacha_ctx *x, const u_char *k, |
21 | u_int kbits) | 23 | u_int kbits) |
22 | __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))); | 24 | __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))); |
@@ -187,6 +189,25 @@ chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes) | |||
187 | x14 = PLUS(x14, j14); | 189 | x14 = PLUS(x14, j14); |
188 | x15 = PLUS(x15, j15); | 190 | x15 = PLUS(x15, j15); |
189 | 191 | ||
192 | if (bytes < 64) { | ||
193 | U32TO8_LITTLE(x->ks + 0, x0); | ||
194 | U32TO8_LITTLE(x->ks + 4, x1); | ||
195 | U32TO8_LITTLE(x->ks + 8, x2); | ||
196 | U32TO8_LITTLE(x->ks + 12, x3); | ||
197 | U32TO8_LITTLE(x->ks + 16, x4); | ||
198 | U32TO8_LITTLE(x->ks + 20, x5); | ||
199 | U32TO8_LITTLE(x->ks + 24, x6); | ||
200 | U32TO8_LITTLE(x->ks + 28, x7); | ||
201 | U32TO8_LITTLE(x->ks + 32, x8); | ||
202 | U32TO8_LITTLE(x->ks + 36, x9); | ||
203 | U32TO8_LITTLE(x->ks + 40, x10); | ||
204 | U32TO8_LITTLE(x->ks + 44, x11); | ||
205 | U32TO8_LITTLE(x->ks + 48, x12); | ||
206 | U32TO8_LITTLE(x->ks + 52, x13); | ||
207 | U32TO8_LITTLE(x->ks + 56, x14); | ||
208 | U32TO8_LITTLE(x->ks + 60, x15); | ||
209 | } | ||
210 | |||
190 | x0 = XOR(x0, U8TO32_LITTLE(m + 0)); | 211 | x0 = XOR(x0, U8TO32_LITTLE(m + 0)); |
191 | x1 = XOR(x1, U8TO32_LITTLE(m + 4)); | 212 | x1 = XOR(x1, U8TO32_LITTLE(m + 4)); |
192 | x2 = XOR(x2, U8TO32_LITTLE(m + 8)); | 213 | x2 = XOR(x2, U8TO32_LITTLE(m + 8)); |
@@ -237,6 +258,7 @@ chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes) | |||
237 | } | 258 | } |
238 | x->input[12] = j12; | 259 | x->input[12] = j12; |
239 | x->input[13] = j13; | 260 | x->input[13] = j13; |
261 | x->unused = 64 - bytes; | ||
240 | return; | 262 | return; |
241 | } | 263 | } |
242 | bytes -= 64; | 264 | bytes -= 64; |
diff --git a/src/lib/libcrypto/chacha/chacha.c b/src/lib/libcrypto/chacha/chacha.c index a12c824fe6..141b3e99f6 100644 --- a/src/lib/libcrypto/chacha/chacha.c +++ b/src/lib/libcrypto/chacha/chacha.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: chacha.c,v 1.4 2014/06/12 15:49:28 deraadt Exp $ */ | 1 | /* $OpenBSD: chacha.c,v 1.5 2014/06/24 18:12:09 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -22,6 +22,7 @@ void | |||
22 | ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, uint32_t keybits) | 22 | ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, uint32_t keybits) |
23 | { | 23 | { |
24 | chacha_keysetup((chacha_ctx *)ctx, key, keybits); | 24 | chacha_keysetup((chacha_ctx *)ctx, key, keybits); |
25 | ctx->unused = 0; | ||
25 | } | 26 | } |
26 | 27 | ||
27 | void | 28 | void |
@@ -29,11 +30,25 @@ ChaCha_set_iv(ChaCha_ctx *ctx, const unsigned char *iv, | |||
29 | const unsigned char *counter) | 30 | const unsigned char *counter) |
30 | { | 31 | { |
31 | chacha_ivsetup((chacha_ctx *)ctx, iv, counter); | 32 | chacha_ivsetup((chacha_ctx *)ctx, iv, counter); |
33 | ctx->unused = 0; | ||
32 | } | 34 | } |
33 | 35 | ||
34 | void | 36 | void |
35 | ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len) | 37 | ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len) |
36 | { | 38 | { |
39 | unsigned char *k; | ||
40 | int i, l; | ||
41 | |||
42 | /* Consume remaining keystream, if any exists. */ | ||
43 | if (ctx->unused > 0) { | ||
44 | k = ctx->ks + 64 - ctx->unused; | ||
45 | l = (len > ctx->unused) ? ctx->unused : len; | ||
46 | for (i = 0; i < l; i++) | ||
47 | *(out++) = *(in++) ^ *(k++); | ||
48 | ctx->unused -= l; | ||
49 | len -= l; | ||
50 | } | ||
51 | |||
37 | chacha_encrypt_bytes((chacha_ctx *)ctx, in, out, (uint32_t)len); | 52 | chacha_encrypt_bytes((chacha_ctx *)ctx, in, out, (uint32_t)len); |
38 | } | 53 | } |
39 | 54 | ||
diff --git a/src/lib/libcrypto/chacha/chacha.h b/src/lib/libcrypto/chacha/chacha.h index 636770ad99..a221825d9e 100644 --- a/src/lib/libcrypto/chacha/chacha.h +++ b/src/lib/libcrypto/chacha/chacha.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: chacha.h,v 1.4 2014/06/12 15:49:28 deraadt Exp $ */ | 1 | /* $OpenBSD: chacha.h,v 1.5 2014/06/24 18:12:09 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -32,6 +32,8 @@ extern "C" { | |||
32 | 32 | ||
33 | typedef struct { | 33 | typedef struct { |
34 | unsigned int input[16]; | 34 | unsigned int input[16]; |
35 | unsigned char ks[64]; | ||
36 | unsigned char unused; | ||
35 | } ChaCha_ctx; | 37 | } ChaCha_ctx; |
36 | 38 | ||
37 | void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, | 39 | void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, |
diff --git a/src/lib/libssl/src/crypto/chacha/chacha-merged.c b/src/lib/libssl/src/crypto/chacha/chacha-merged.c index 25092b16da..a665fb316f 100644 --- a/src/lib/libssl/src/crypto/chacha/chacha-merged.c +++ b/src/lib/libssl/src/crypto/chacha/chacha-merged.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: chacha-merged.c,v 1.5 2014/06/24 17:48:30 jsing Exp $ */ | 1 | /* $OpenBSD: chacha-merged.c,v 1.6 2014/06/24 18:12:09 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | chacha-merged.c version 20080118 | 3 | chacha-merged.c version 20080118 |
4 | D. J. Bernstein | 4 | D. J. Bernstein |
@@ -7,16 +7,18 @@ Public domain. | |||
7 | 7 | ||
8 | #include <sys/types.h> | 8 | #include <sys/types.h> |
9 | 9 | ||
10 | struct chacha_ctx { | ||
11 | u_int input[16]; | ||
12 | }; | ||
13 | |||
14 | #define CHACHA_MINKEYLEN 16 | 10 | #define CHACHA_MINKEYLEN 16 |
15 | #define CHACHA_NONCELEN 8 | 11 | #define CHACHA_NONCELEN 8 |
16 | #define CHACHA_CTRLEN 8 | 12 | #define CHACHA_CTRLEN 8 |
17 | #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) | 13 | #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) |
18 | #define CHACHA_BLOCKLEN 64 | 14 | #define CHACHA_BLOCKLEN 64 |
19 | 15 | ||
16 | struct chacha_ctx { | ||
17 | u_int input[16]; | ||
18 | u_int8_t ks[CHACHA_BLOCKLEN]; | ||
19 | u_int8_t unused; | ||
20 | }; | ||
21 | |||
20 | static inline void chacha_keysetup(struct chacha_ctx *x, const u_char *k, | 22 | static inline void chacha_keysetup(struct chacha_ctx *x, const u_char *k, |
21 | u_int kbits) | 23 | u_int kbits) |
22 | __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))); | 24 | __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))); |
@@ -187,6 +189,25 @@ chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes) | |||
187 | x14 = PLUS(x14, j14); | 189 | x14 = PLUS(x14, j14); |
188 | x15 = PLUS(x15, j15); | 190 | x15 = PLUS(x15, j15); |
189 | 191 | ||
192 | if (bytes < 64) { | ||
193 | U32TO8_LITTLE(x->ks + 0, x0); | ||
194 | U32TO8_LITTLE(x->ks + 4, x1); | ||
195 | U32TO8_LITTLE(x->ks + 8, x2); | ||
196 | U32TO8_LITTLE(x->ks + 12, x3); | ||
197 | U32TO8_LITTLE(x->ks + 16, x4); | ||
198 | U32TO8_LITTLE(x->ks + 20, x5); | ||
199 | U32TO8_LITTLE(x->ks + 24, x6); | ||
200 | U32TO8_LITTLE(x->ks + 28, x7); | ||
201 | U32TO8_LITTLE(x->ks + 32, x8); | ||
202 | U32TO8_LITTLE(x->ks + 36, x9); | ||
203 | U32TO8_LITTLE(x->ks + 40, x10); | ||
204 | U32TO8_LITTLE(x->ks + 44, x11); | ||
205 | U32TO8_LITTLE(x->ks + 48, x12); | ||
206 | U32TO8_LITTLE(x->ks + 52, x13); | ||
207 | U32TO8_LITTLE(x->ks + 56, x14); | ||
208 | U32TO8_LITTLE(x->ks + 60, x15); | ||
209 | } | ||
210 | |||
190 | x0 = XOR(x0, U8TO32_LITTLE(m + 0)); | 211 | x0 = XOR(x0, U8TO32_LITTLE(m + 0)); |
191 | x1 = XOR(x1, U8TO32_LITTLE(m + 4)); | 212 | x1 = XOR(x1, U8TO32_LITTLE(m + 4)); |
192 | x2 = XOR(x2, U8TO32_LITTLE(m + 8)); | 213 | x2 = XOR(x2, U8TO32_LITTLE(m + 8)); |
@@ -237,6 +258,7 @@ chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes) | |||
237 | } | 258 | } |
238 | x->input[12] = j12; | 259 | x->input[12] = j12; |
239 | x->input[13] = j13; | 260 | x->input[13] = j13; |
261 | x->unused = 64 - bytes; | ||
240 | return; | 262 | return; |
241 | } | 263 | } |
242 | bytes -= 64; | 264 | bytes -= 64; |
diff --git a/src/lib/libssl/src/crypto/chacha/chacha.c b/src/lib/libssl/src/crypto/chacha/chacha.c index a12c824fe6..141b3e99f6 100644 --- a/src/lib/libssl/src/crypto/chacha/chacha.c +++ b/src/lib/libssl/src/crypto/chacha/chacha.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: chacha.c,v 1.4 2014/06/12 15:49:28 deraadt Exp $ */ | 1 | /* $OpenBSD: chacha.c,v 1.5 2014/06/24 18:12:09 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -22,6 +22,7 @@ void | |||
22 | ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, uint32_t keybits) | 22 | ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, uint32_t keybits) |
23 | { | 23 | { |
24 | chacha_keysetup((chacha_ctx *)ctx, key, keybits); | 24 | chacha_keysetup((chacha_ctx *)ctx, key, keybits); |
25 | ctx->unused = 0; | ||
25 | } | 26 | } |
26 | 27 | ||
27 | void | 28 | void |
@@ -29,11 +30,25 @@ ChaCha_set_iv(ChaCha_ctx *ctx, const unsigned char *iv, | |||
29 | const unsigned char *counter) | 30 | const unsigned char *counter) |
30 | { | 31 | { |
31 | chacha_ivsetup((chacha_ctx *)ctx, iv, counter); | 32 | chacha_ivsetup((chacha_ctx *)ctx, iv, counter); |
33 | ctx->unused = 0; | ||
32 | } | 34 | } |
33 | 35 | ||
34 | void | 36 | void |
35 | ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len) | 37 | ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len) |
36 | { | 38 | { |
39 | unsigned char *k; | ||
40 | int i, l; | ||
41 | |||
42 | /* Consume remaining keystream, if any exists. */ | ||
43 | if (ctx->unused > 0) { | ||
44 | k = ctx->ks + 64 - ctx->unused; | ||
45 | l = (len > ctx->unused) ? ctx->unused : len; | ||
46 | for (i = 0; i < l; i++) | ||
47 | *(out++) = *(in++) ^ *(k++); | ||
48 | ctx->unused -= l; | ||
49 | len -= l; | ||
50 | } | ||
51 | |||
37 | chacha_encrypt_bytes((chacha_ctx *)ctx, in, out, (uint32_t)len); | 52 | chacha_encrypt_bytes((chacha_ctx *)ctx, in, out, (uint32_t)len); |
38 | } | 53 | } |
39 | 54 | ||
diff --git a/src/lib/libssl/src/crypto/chacha/chacha.h b/src/lib/libssl/src/crypto/chacha/chacha.h index 636770ad99..a221825d9e 100644 --- a/src/lib/libssl/src/crypto/chacha/chacha.h +++ b/src/lib/libssl/src/crypto/chacha/chacha.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: chacha.h,v 1.4 2014/06/12 15:49:28 deraadt Exp $ */ | 1 | /* $OpenBSD: chacha.h,v 1.5 2014/06/24 18:12:09 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -32,6 +32,8 @@ extern "C" { | |||
32 | 32 | ||
33 | typedef struct { | 33 | typedef struct { |
34 | unsigned int input[16]; | 34 | unsigned int input[16]; |
35 | unsigned char ks[64]; | ||
36 | unsigned char unused; | ||
35 | } ChaCha_ctx; | 37 | } ChaCha_ctx; |
36 | 38 | ||
37 | void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, | 39 | void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, |