>From 7b7d54558fe4fbd20d722ee01d63b13961217416 Mon Sep 17 00:00:00 2001
From: "Yuriy M. Kaminskiy" <yumkam@gmail.com>
Date: Mon, 11 Mar 2019 20:51:57 +0300
Subject: [PATCH 1/3] chacha: prepare for multiblock asm implementation

---
 chacha-crypt.c    | 89 +++++++++++++++++++++++++++++++++++++++++++------------
 chacha-internal.h |  4 +++
 configure.ac      |  3 ++
 3 files changed, 77 insertions(+), 19 deletions(-)

diff --git a/chacha-crypt.c b/chacha-crypt.c
index 63d799ce..03e50d97 100644
--- a/chacha-crypt.c
+++ b/chacha-crypt.c
@@ -54,34 +54,85 @@
 
 #define CHACHA_ROUNDS 20
 
+/* is the pointer aligned on a word boundary? */
+static int
+chacha_is_aligned(const void *p) {
+	return ((size_t)p & (sizeof(size_t) - 1)) == 0;
+}
+
+#ifdef HAVE_NATIVE_chacha_blocks
 void
-chacha_crypt(struct chacha_ctx *ctx,
-	      size_t length,
-	      uint8_t *c,
-	      const uint8_t *m)
+_nettle_chacha_blocks_c
+#else
+#undef _chacha_blocks
+static void
+_chacha_blocks
+#endif
+	(struct chacha_ctx *ctx, const uint8_t *m, uint8_t *c, size_t length, size_t rounds)
 {
-  if (!length)
-    return;
-  
-  for (;;)
+  while(length >= CHACHA_BLOCK_SIZE)
     {
       uint32_t x[_CHACHA_STATE_LENGTH];
+      uint32_t *dst = m ? x : (uint32_t *)c;
+      _chacha_core (dst, ctx->state, rounds);
+      ctx->state[13] += (++ctx->state[12] == 0);
+      /* stopping at 2^70 length per nonce is user's responsibility */
 
-      _chacha_core (x, ctx->state, CHACHA_ROUNDS);
+      if (m)
+        {
+	  memxor3 (c, m, x, CHACHA_BLOCK_SIZE);
+	  m += CHACHA_BLOCK_SIZE;
+	}
 
+      c += CHACHA_BLOCK_SIZE;
+      length -= CHACHA_BLOCK_SIZE;
+    }
+  if (length)
+    {
+      uint32_t x[_CHACHA_STATE_LENGTH];
+      _chacha_core (x, ctx->state, rounds);
       ctx->state[13] += (++ctx->state[12] == 0);
-
       /* stopping at 2^70 length per nonce is user's responsibility */
-      
-      if (length <= CHACHA_BLOCK_SIZE)
-	{
+
+      if (m)
+        {
 	  memxor3 (c, m, x, length);
-	  return;
+	  m += length;
 	}
-      memxor3 (c, m, x, CHACHA_BLOCK_SIZE);
+      else
+	memcpy (c, x, length);
+    }
+}
 
-      length -= CHACHA_BLOCK_SIZE;
-      c += CHACHA_BLOCK_SIZE;
-      m += CHACHA_BLOCK_SIZE;
-  }
+void
+chacha_crypt(struct chacha_ctx *ctx,
+	      size_t length,
+	      uint8_t *c,
+	      const uint8_t *m)
+{
+  unsigned char buffer[16 * CHACHA_BLOCK_SIZE];
+  int in_aligned, out_aligned;
+  in_aligned = chacha_is_aligned(m);
+  out_aligned = chacha_is_aligned(c);
+  if (in_aligned && out_aligned)
+    {
+      return _chacha_blocks(ctx, m, c, length, CHACHA_ROUNDS);
+    }
+  while (length)
+    {
+      const size_t bytes = (length > sizeof(buffer)) ? sizeof(buffer) : length;
+      const unsigned char *src = m;
+      unsigned char *dst = (out_aligned) ? c : buffer;
+      if (!in_aligned)
+	{
+	  memcpy(buffer, m, bytes);
+	  src = buffer;
+	}
+      _chacha_blocks(ctx, src, dst, bytes, CHACHA_ROUNDS);
+      if (!out_aligned)
+	memcpy(c, buffer, bytes);
+      if (m) m += bytes;
+      c += bytes;
+      length -= bytes;
+    }
 }
diff --git a/chacha-internal.h b/chacha-internal.h
index 1bca8e74..2e2baea0 100644
--- a/chacha-internal.h
+++ b/chacha-internal.h
@@ -39,8 +39,12 @@
 #include "nettle-types.h"
 
 #define _chacha_core _nettle_chacha_core
+#define _chacha_blocks _nettle_chacha_blocks
 
 void
 _chacha_core(uint32_t *dst, const uint32_t *src, unsigned rounds);
 
+void
+_chacha_blocks(struct chacha_ctx *ctx, const uint8_t *src, uint8_t *dst, size_t length, size_t rounds);
+
 #endif /* NETTLE_CHACHA_INTERNAL_H_INCLUDED */
diff --git a/configure.ac b/configure.ac
index 4a482bdd..21c932a5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -468,6 +468,7 @@ asm_replace_list="aes-encrypt-internal.asm aes-decrypt-internal.asm \
 # Assembler files which generate additional object files if they are used.
 asm_nettle_optional_list="gcm-hash8.asm cpuid.asm \
   aes-encrypt-internal-2.asm aes-decrypt-internal-2.asm memxor-2.asm \
+  chacha-blocks.asm chacha-blocks-2.asm \
   chacha-core-internal-2.asm \
   gcm-hash.asm gcm-hash-2.asm \
   salsa20-core-internal-2.asm sha1-compress-2.asm sha256-compress-2.asm \
@@ -572,6 +573,8 @@ AH_VERBATIM([HAVE_NATIVE],
 [/* Define to 1 each of the following for which a native (ie. CPU specific)
     implementation of the corresponding routine exists.  */
 #undef HAVE_NATIVE_chacha_core
+#undef HAVE_NATIVE_chacha_blocks
+#undef HAVE_NATIVE_hchacha
 #undef HAVE_NATIVE_ecc_192_modp
 #undef HAVE_NATIVE_ecc_192_redc
 #undef HAVE_NATIVE_ecc_224_modp
-- 
2.11.0

