summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2014-06-24 18:12:09 +0000
committerjsing <>2014-06-24 18:12:09 +0000
commit6a9c4d13fc97c0ad186e4d15839ef568659ebf6f (patch)
tree77b512bc366b09aa3f9194007a50fa04d944872c
parent8bcb66ae2fbdc9abd5d6029738e23c72c75bad68 (diff)
downloadopenbsd-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.c32
-rw-r--r--src/lib/libcrypto/chacha/chacha.c17
-rw-r--r--src/lib/libcrypto/chacha/chacha.h4
-rw-r--r--src/lib/libssl/src/crypto/chacha/chacha-merged.c32
-rw-r--r--src/lib/libssl/src/crypto/chacha/chacha.c17
-rw-r--r--src/lib/libssl/src/crypto/chacha/chacha.h4
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/*
3chacha-merged.c version 20080118 3chacha-merged.c version 20080118
4D. J. Bernstein 4D. J. Bernstein
@@ -7,16 +7,18 @@ Public domain.
7 7
8#include <sys/types.h> 8#include <sys/types.h>
9 9
10struct 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
16struct chacha_ctx {
17 u_int input[16];
18 u_int8_t ks[CHACHA_BLOCKLEN];
19 u_int8_t unused;
20};
21
20static inline void chacha_keysetup(struct chacha_ctx *x, const u_char *k, 22static 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
22ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, uint32_t keybits) 22ChaCha_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
27void 28void
@@ -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
34void 36void
35ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len) 37ChaCha(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
33typedef struct { 33typedef 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
37void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, 39void 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/*
3chacha-merged.c version 20080118 3chacha-merged.c version 20080118
4D. J. Bernstein 4D. J. Bernstein
@@ -7,16 +7,18 @@ Public domain.
7 7
8#include <sys/types.h> 8#include <sys/types.h>
9 9
10struct 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
16struct chacha_ctx {
17 u_int input[16];
18 u_int8_t ks[CHACHA_BLOCKLEN];
19 u_int8_t unused;
20};
21
20static inline void chacha_keysetup(struct chacha_ctx *x, const u_char *k, 22static 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
22ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, uint32_t keybits) 22ChaCha_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
27void 28void
@@ -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
34void 36void
35ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len) 37ChaCha(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
33typedef struct { 33typedef 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
37void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, 39void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key,