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

chacha: add function to set initial block counter

The ChaCha20 based header protection algorithm in QUIC requires a way
to set the initial value of counter:
https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#name-chacha20-based-header-prote



This will add a new function chacha_set_counter, which takes an
8-octet initial value of the block counter.
Signed-off-by: default avatarDaiki Ueno <dueno@redhat.com>
parent 84284d37
......@@ -68,3 +68,10 @@ chacha_set_nonce96(struct chacha_ctx *ctx, const uint8_t *nonce)
ctx->state[14] = LE_READ_UINT32(nonce + 4);
ctx->state[15] = LE_READ_UINT32(nonce + 8);
}
void
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);
}
......@@ -46,6 +46,7 @@ extern "C" {
#define chacha_set_key nettle_chacha_set_key
#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_crypt nettle_chacha_crypt
/* Currently, only 256-bit keys are supported. */
......@@ -53,6 +54,7 @@ extern "C" {
#define CHACHA_BLOCK_SIZE 64
#define CHACHA_NONCE_SIZE 8
#define CHACHA_NONCE96_SIZE 12
#define CHACHA_COUNTER_SIZE 8
#define _CHACHA_STATE_LENGTH 16
......@@ -81,6 +83,9 @@ chacha_set_nonce(struct chacha_ctx *ctx, const uint8_t *nonce);
void
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_crypt(struct chacha_ctx *ctx, size_t length,
uint8_t *dst, const uint8_t *src);
......
......@@ -1669,6 +1669,10 @@ ChaCha block size, 64.
Size of the nonce, 8.
@end defvr
@defvr Constant CHACHA_COUNTER_SIZE
Size of the counter, 8.
@end defvr
@deftypefun void chacha_set_key (struct chacha_ctx *@var{ctx}, const uint8_t *@var{key})
Initialize the cipher. The same function is used for both encryption and
decryption. Before using the cipher,
......@@ -1681,6 +1685,14 @@ octets. This function also initializes the block counter, setting it to
zero.
@end deftypefun
@deftypefun void chacha_set_counter (struct chacha_ctx *@var{ctx}, const uint8_t *@var{counter})
Sets the block counter. It is always of size @code{CHACHA_COUNTER_SIZE},
8 octets. This is rarely needed since @code{chacha_set_nonce}
initializes the block counter to zero. When it is still necessary, this
function must be called after @code{chacha_set_nonce}.
@end deftypefun
@deftypefun void chacha_crypt (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. When a
message is encrypted using a sequence of calls to @code{chacha_crypt},
......
......@@ -38,8 +38,9 @@
#include "chacha-internal.h"
static void
test_chacha(const struct tstring *key, const struct tstring *nonce,
const struct tstring *expected, unsigned rounds)
_test_chacha(const struct tstring *key, const struct tstring *nonce,
const struct tstring *expected, unsigned rounds,
const struct tstring *counter)
{
struct chacha_ctx ctx;
......@@ -69,6 +70,9 @@ test_chacha(const struct tstring *key, const struct tstring *nonce,
else
die ("Bad nonce size %u.\n", (unsigned) nonce->length);
if (counter)
chacha_set_counter(&ctx, counter->data);
chacha_crypt (&ctx, length, data, data);
ASSERT (data[-1] == 17);
......@@ -98,6 +102,8 @@ test_chacha(const struct tstring *key, const struct tstring *nonce,
ASSERT (nonce->length == CHACHA_NONCE_SIZE);
chacha_set_nonce(&ctx, nonce->data);
if (counter)
chacha_set_counter(&ctx, counter->data);
_chacha_core (out, ctx.state, rounds);
if (!MEMEQ(CHACHA_BLOCK_SIZE, out, expected->data))
......@@ -117,6 +123,21 @@ test_chacha(const struct tstring *key, const struct tstring *nonce,
}
}
static void
test_chacha(const struct tstring *key, const struct tstring *nonce,
const struct tstring *expected, unsigned rounds)
{
_test_chacha(key, nonce, expected, rounds, NULL);
}
static void
test_chacha_with_counter(const struct tstring *key, const struct tstring *nonce,
const struct tstring *expected, unsigned rounds,
const struct tstring *counter)
{
_test_chacha(key, nonce, expected, rounds, counter);
}
void
test_main(void)
{
......@@ -644,4 +665,16 @@ test_main(void)
"d2826446079faa09 14c2d705d98b02a2"
"b5129cd1de164eb9 cbd083e8a2503c4e"),
20);
/* This is identical to the 96-bit nonce test, but it manually sets
the counter value */
test_chacha_with_counter(SHEX("0001020304050607 08090a0b0c0d0e0f"
"1011121314151617 18191a1b1c1d1e1f"),
SHEX("0000004a00000000"),
SHEX("10f1e7e4d13b5915 500fdd1fa32071c4"
"c7d1f4c733c06803 0422aa9ac3d46c4e"
"d2826446079faa09 14c2d705d98b02a2"
"b5129cd1de164eb9 cbd083e8a2503c4e"),
20,
SHEX("0100000000000009"));
}
Markdown is supported
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