diff options
author | Daiki Ueno <dueno@redhat.com> | 2020-03-09 13:01:17 +0100 |
---|---|---|
committer | Niels Möller <nisse@lysator.liu.se> | 2020-03-09 19:08:12 +0100 |
commit | a9894036fc5e3c972d751ea28e64e23ddc77fc37 (patch) | |
tree | 873173e84238d4534089c944b409cca89076eb77 | |
parent | 84284d37751241703e254f3277be9d57d788714a (diff) | |
download | nettle-a9894036fc5e3c972d751ea28e64e23ddc77fc37.tar.gz |
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: Daiki Ueno <dueno@redhat.com>
-rw-r--r-- | chacha-set-nonce.c | 7 | ||||
-rw-r--r-- | chacha.h | 5 | ||||
-rw-r--r-- | nettle.texinfo | 12 | ||||
-rw-r--r-- | testsuite/chacha-test.c | 37 |
4 files changed, 59 insertions, 2 deletions
diff --git a/chacha-set-nonce.c b/chacha-set-nonce.c index 607f176b..2c34e498 100644 --- a/chacha-set-nonce.c +++ b/chacha-set-nonce.c @@ -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 @@ -82,6 +84,9 @@ 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); diff --git a/nettle.texinfo b/nettle.texinfo index 19eb6d34..0b339f51 100644 --- a/nettle.texinfo +++ b/nettle.texinfo @@ -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}, diff --git a/testsuite/chacha-test.c b/testsuite/chacha-test.c index d6489e9c..6875d4bb 100644 --- a/testsuite/chacha-test.c +++ b/testsuite/chacha-test.c @@ -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")); } |