Commit 2176ccc1 authored by Daiki Ueno's avatar Daiki Ueno Committed by Niels Möller
Browse files

chacha: add variant that treats counter value as 32-bit



The ChaCha-Poly1305 implementation previously used the chacha_crypt
function that assumes the block counter is 64-bit long, while RFC 8439
defines that the counter is 32-bit long.  Although this should be fine
as long as up to 256 gigabytes of data is encrypted with the same key,
it would be nice to use a separate functions (chacha_set_counter32 and
chacha_crypt32) that assume the counter is 32-bit long.
Signed-off-by: default avatarDaiki Ueno <dueno@redhat.com>
parent a9894036
......@@ -85,3 +85,35 @@ chacha_crypt(struct chacha_ctx *ctx,
m += CHACHA_BLOCK_SIZE;
}
}
void
chacha_crypt32(struct chacha_ctx *ctx,
size_t length,
uint8_t *c,
const uint8_t *m)
{
if (!length)
return;
for (;;)
{
uint32_t x[_CHACHA_STATE_LENGTH];
_chacha_core (x, ctx->state, CHACHA_ROUNDS);
++ctx->state[12];
/* stopping at 2^70 length per nonce is user's responsibility */
if (length <= CHACHA_BLOCK_SIZE)
{
memxor3 (c, m, x, length);
return;
}
memxor3 (c, m, x, CHACHA_BLOCK_SIZE);
length -= CHACHA_BLOCK_SIZE;
c += CHACHA_BLOCK_SIZE;
m += CHACHA_BLOCK_SIZE;
}
}
......@@ -130,7 +130,7 @@ chacha_poly1305_encrypt (struct chacha_poly1305_ctx *ctx,
assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);
poly1305_pad (ctx);
chacha_crypt (&ctx->chacha, length, dst, src);
chacha_crypt32 (&ctx->chacha, length, dst, src);
poly1305_update (ctx, length, dst);
ctx->data_size += length;
}
......@@ -146,7 +146,7 @@ chacha_poly1305_decrypt (struct chacha_poly1305_ctx *ctx,
poly1305_pad (ctx);
poly1305_update (ctx, length, src);
chacha_crypt (&ctx->chacha, length, dst, src);
chacha_crypt32 (&ctx->chacha, length, dst, src);
ctx->data_size += length;
}
......
......@@ -75,3 +75,9 @@ chacha_set_counter(struct chacha_ctx *ctx, const uint8_t *counter)
ctx->state[12] = LE_READ_UINT32(counter + 0);
ctx->state[13] = LE_READ_UINT32(counter + 4);
}
void
chacha_set_counter32(struct chacha_ctx *ctx, const uint8_t *counter)
{
ctx->state[12] = LE_READ_UINT32(counter + 0);
}
......@@ -47,7 +47,9 @@ extern "C" {
#define chacha_set_nonce nettle_chacha_set_nonce
#define chacha_set_nonce96 nettle_chacha_set_nonce96
#define chacha_set_counter nettle_chacha_set_counter
#define chacha_set_counter32 nettle_chacha_set_counter32
#define chacha_crypt nettle_chacha_crypt
#define chacha_crypt32 nettle_chacha_crypt32
/* Currently, only 256-bit keys are supported. */
#define CHACHA_KEY_SIZE 32
......@@ -55,6 +57,7 @@ extern "C" {
#define CHACHA_NONCE_SIZE 8
#define CHACHA_NONCE96_SIZE 12
#define CHACHA_COUNTER_SIZE 8
#define CHACHA_COUNTER32_SIZE 4
#define _CHACHA_STATE_LENGTH 16
......@@ -86,10 +89,17 @@ chacha_set_nonce96(struct chacha_ctx *ctx, const uint8_t *nonce);
void
chacha_set_counter(struct chacha_ctx *ctx, const uint8_t *counter);
void
chacha_set_counter32(struct chacha_ctx *ctx, const uint8_t *counter);
void
chacha_crypt(struct chacha_ctx *ctx, size_t length,
uint8_t *dst, const uint8_t *src);
void
chacha_crypt32(struct chacha_ctx *ctx, size_t length,
uint8_t *dst, const uint8_t *src);
#ifdef __cplusplus
}
#endif
......
......@@ -1700,6 +1700,37 @@ all but the last call @emph{must} use a length that is a multiple of
@code{CHACHA_BLOCK_SIZE}.
@end deftypefun
@subsubsection 32-bit counter variant
While the original paper uses 64-bit counter value, the variant defined
in @cite{RFC 8439} uses 32-bit counter value. This variant is
particularly useful for @pxref{ChaCha-Poly1305} AEAD construction, which
supports 12-octet nonces.
@defvr Constant CHACHA_NONCE96_SIZE
Size of the nonce, 12.
@end defvr
@defvr Constant CHACHA_COUNTER32_SIZE
Size of the counter, 4.
@end defvr
@deftypefun void chacha_set_nonce96 (struct chacha_ctx *@var{ctx}, const uint8_t *@var{nonce})
Sets the nonce. This is similar to the above @code{chacha_set_nonce},
but the input is always of size @code{CHACHA_NONCE96_SIZE}, 12 octets.
@end deftypefun
@deftypefun void chacha_set_counter32 (struct chacha_ctx *@var{ctx}, const uint8_t *@var{counter})
Sets the block counter. This is similar to the above @code{chacha_set_counter},
but the input is always of size @code{CHACHA_COUNTER32_SIZE}, 4 octets.
@end deftypefun
@deftypefun void chacha_crypt32 (struct chacha_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
Encrypts or decrypts the data of a message, using ChaCha. This is similar to the
above @code{chacha_crypt}, but it assumes the internal counter value is 32-bit
long and the nonce is 96-bit long.
@end deftypefun
@subsection DES
@cindex DES
DES is the old Data Encryption Standard, specified by NIST. It uses a
......
......@@ -71,9 +71,23 @@ _test_chacha(const struct tstring *key, const struct tstring *nonce,
die ("Bad nonce size %u.\n", (unsigned) nonce->length);
if (counter)
chacha_set_counter(&ctx, counter->data);
{
if (counter->length == CHACHA_COUNTER_SIZE)
{
ASSERT (nonce->length == CHACHA_NONCE_SIZE);
chacha_set_counter(&ctx, counter->data);
}
else if (counter->length == CHACHA_COUNTER32_SIZE)
{
ASSERT (nonce->length == CHACHA_NONCE96_SIZE);
chacha_set_counter32(&ctx, counter->data);
}
}
chacha_crypt (&ctx, length, data, data);
if (nonce->length == CHACHA_NONCE_SIZE)
chacha_crypt (&ctx, length, data, data);
else
chacha_crypt32 (&ctx, length, data, data);
ASSERT (data[-1] == 17);
ASSERT (data[length] == 17);
......@@ -666,8 +680,20 @@ test_main(void)
"b5129cd1de164eb9 cbd083e8a2503c4e"),
20);
/* This is identical to the 96-bit nonce test, but it manually sets
the counter value */
/* This is identical to the above 96-bit nonce test, but it manually
sets the 32-bit counter value */
test_chacha_with_counter(SHEX("0001020304050607 08090a0b0c0d0e0f"
"1011121314151617 18191a1b1c1d1e1f"),
SHEX("000000090000004a 00000000"),
SHEX("10f1e7e4d13b5915 500fdd1fa32071c4"
"c7d1f4c733c06803 0422aa9ac3d46c4e"
"d2826446079faa09 14c2d705d98b02a2"
"b5129cd1de164eb9 cbd083e8a2503c4e"),
20,
SHEX("01000000"));
/* This is identical to the above 96-bit nonce test, but it manually
sets the 64-bit counter value */
test_chacha_with_counter(SHEX("0001020304050607 08090a0b0c0d0e0f"
"1011121314151617 18191a1b1c1d1e1f"),
SHEX("0000004a00000000"),
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment