]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
chacha: add function to set initial block counter
authorDaiki Ueno <dueno@redhat.com>
Mon, 9 Mar 2020 12:01:17 +0000 (13:01 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Mon, 9 Mar 2020 18:08:12 +0000 (19:08 +0100)
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>
chacha-set-nonce.c
chacha.h
nettle.texinfo
testsuite/chacha-test.c

index 607f176b2fd851af348af89e0a93e97724f670a0..2c34e498c3f3a8b2801879ca668395f9e99953ae 100644 (file)
@@ -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);
+}
index 429a55b685b0cb389910a6c1b060c7753d42b52c..440fe9687643878141632490c923e15abfcacc9b 100644 (file)
--- a/chacha.h
+++ b/chacha.h
@@ -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);
index 19eb6d3472a2985648d7ed132781b3206af97d8c..0b339f519c49f4474354ebb89ecdcd9dc24be8c7 100644 (file)
@@ -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},
index d6489e9cde79355c6e153772a467aaef721a436b..6875d4bb07272ed6fbecb84e65f96d787ba8d432 100644 (file)
@@ -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"));
 }