]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
chacha: add variant that treats counter value as 32-bit
authorDaiki Ueno <dueno@redhat.com>
Mon, 9 Mar 2020 12:01:18 +0000 (13:01 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Mon, 9 Mar 2020 18:09:18 +0000 (19:09 +0100)
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 <dueno@redhat.com>
chacha-crypt.c
chacha-poly1305.c
chacha-set-nonce.c
chacha.h
nettle.texinfo
testsuite/chacha-test.c

index 63d799cef23cc626455cc408fbc5673477caead5..0bb44ed919f74fd9998154e6a1a5bfeeecf75c60 100644 (file)
@@ -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;
+  }
+}
index 974a502290e0f80027aede2a19a12c0bd126df68..a15fef0cd7420c0e377506864c2f76e0ef972955 100644 (file)
@@ -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;
 }
                         
index 2c34e498c3f3a8b2801879ca668395f9e99953ae..1547aea1ad98e2f718844dc52ca3d039f8033971 100644 (file)
@@ -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);
+}
index 440fe9687643878141632490c923e15abfcacc9b..fe28b835316c6250c62eaed926e5499eda195f26 100644 (file)
--- 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
index 0b339f519c49f4474354ebb89ecdcd9dc24be8c7..fe44f6af3ddf70348a5352a32ddd994835ec2405 100644 (file)
@@ -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
index 6875d4bb07272ed6fbecb84e65f96d787ba8d432..fb8f1db7a2c85ebbae58b06986bd701496c87c20 100644 (file)
@@ -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"),