Re: [PATCH v2 1/3] chacha: add function to set initial block counter

2020-03-09 Thread Niels Möller
Daiki Ueno  writes:

> From: Daiki Ueno 
>
> 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.

I've merged all three patches to master-updates. Two nits below:

> +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 */

Should be 2^38, not 2^70, right?

> +Nettle's implementation of ChaCha-Poly1305 follows @cite{RFC 8439},
> +where the ChaCha cipher is initialized with a 12-byte nonce and a 4-byte
> +block counter. This allows up to 256 gigabytes of data to be encrypted
> +using the same key.

Should be "same key and nonce"; the counter size limits the size of a
message, but the nonce allows for many messages using the same key.

I'll fix these.

It would be nice with a test case where the first 32 bits of the counter
wrap around, which is the only case where chacha_crypt and
chacha_crypt32 behave differently. Is that something you can look into?

Thanks!
/Niels

-- 
Niels Möller. PGP-encrypted email is preferred. Keyid 368C6677.
Internet email is subject to wholesale government surveillance.
___
nettle-bugs mailing list
nettle-bugs@lists.lysator.liu.se
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs


[PATCH v2 1/3] chacha: add function to set initial block counter

2020-03-09 Thread Daiki Ueno
From: Daiki Ueno 

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 
---
 chacha-set-nonce.c  |  7 +++
 chacha.h|  5 +
 nettle.texinfo  | 12 
 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);
+}
diff --git a/chacha.h b/chacha.h
index 429a55b6..440fe968 100644
--- 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);
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(, counter->data);
+
  chacha_crypt (, 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(, nonce->data);
+  if (counter)
+   chacha_set_counter(, 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