From: Daiki Ueno <du...@redhat.com>

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: Daiki Ueno <du...@redhat.com>
---
 chacha-crypt.c          | 32 ++++++++++++++++++++++++++++++++
 chacha-poly1305.c       |  4 ++--
 chacha-set-nonce.c      |  6 ++++++
 chacha.h                | 10 ++++++++++
 nettle.texinfo          | 31 +++++++++++++++++++++++++++++++
 testsuite/chacha-test.c | 34 ++++++++++++++++++++++++++++++----
 6 files changed, 111 insertions(+), 6 deletions(-)

diff --git a/chacha-crypt.c b/chacha-crypt.c
index 63d799ce..0bb44ed9 100644
--- a/chacha-crypt.c
+++ b/chacha-crypt.c
@@ -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;
+  }
+}
diff --git a/chacha-poly1305.c b/chacha-poly1305.c
index 974a5022..a15fef0c 100644
--- a/chacha-poly1305.c
+++ b/chacha-poly1305.c
@@ -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;
 }
                         
diff --git a/chacha-set-nonce.c b/chacha-set-nonce.c
index 2c34e498..1547aea1 100644
--- a/chacha-set-nonce.c
+++ b/chacha-set-nonce.c
@@ -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);
+}
diff --git a/chacha.h b/chacha.h
index 440fe968..fe28b835 100644
--- a/chacha.h
+++ b/chacha.h
@@ -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
diff --git a/nettle.texinfo b/nettle.texinfo
index 0b339f51..fe44f6af 100644
--- a/nettle.texinfo
+++ b/nettle.texinfo
@@ -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
diff --git a/testsuite/chacha-test.c b/testsuite/chacha-test.c
index 6875d4bb..fb8f1db7 100644
--- a/testsuite/chacha-test.c
+++ b/testsuite/chacha-test.c
@@ -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"),
-- 
2.24.1

_______________________________________________
nettle-bugs mailing list
nettle-bugs@lists.lysator.liu.se
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to