]> git.codecow.com Git - Monocypher.git/commitdiff
Incremental left to right sliding windows
authorLoup Vaillant <loup@loup-vaillant.fr>
Sun, 6 Oct 2019 21:58:38 +0000 (23:58 +0200)
committerLoup Vaillant <loup@loup-vaillant.fr>
Sun, 6 Oct 2019 21:58:38 +0000 (23:58 +0200)
The main loop of the scalar multiplication goes one by one, so we can't
have the sliding loop skip indices.  By adding a context that keeps
track of the next needed addition (as well as its value), we'll be able
to fuse the two slides and the scalar multiplication together.

src/monocypher.c

index 2896dcaf5d6f2a0de98275e1d4146e657fafcc5e..79ad75322d17a602b60476e2d4eb0495f2e66191 100644 (file)
@@ -1656,36 +1656,64 @@ static const fe window_T2[8] = {
      -2735503, -13812022, -16236442, -32461234, -12290683},
 };
 
-// Compute signed sliding windows (either 0, or odd numbers)
-// Slide from left to right, based on Roberto Maria Avanzi[2005]
-static void slide(size_t width, i8 *adds, const u8 scalar[32])
+// Incremental sliding windows (left to right)
+// Based on Roberto Maria Avanzi[2005]
+typedef struct {
+    int next_index; // position of the next signed digit
+    int next_digit; // next signed digit (odd number below 2^window_width)
+    int next_check; // point at which we must check for a new window
+} slide_ctx;
+
+void slide_init(slide_ctx *ctx, const u8 scalar[32])
 {
-    int i = 256;
-    while (i-1 > 0 && scalar_bit(scalar, i-1) == 0) {
+    int i = 255;
+    while (i > 0 && scalar_bit(scalar, i) == 0) {
         i--;
     }
+    ctx->next_check = i + 1;
+    ctx->next_index = -1;
+    ctx->next_digit = -1;
+}
+
+void slide_step(slide_ctx *ctx, size_t width, int i, const u8 scalar[32])
+{
+    if (scalar_bit(scalar, i) == scalar_bit(scalar, i - 1)) {
+        ctx->next_check--;
+    } else {
+        unsigned w  = MIN(width, (unsigned)(i + 1));
+        int v = -(scalar_bit(scalar, i) << ((int)w-1));
+        FOR (j, 0, w-1) {
+            v += scalar_bit(scalar, i-(w-1)+j) << j;
+        }
+        v += scalar_bit(scalar, i-w);
+        unsigned lsb = v & (~v + 1);           // smallest bit of v
+        unsigned s   = (   ((lsb & 0xAA) != 0) // log2(lsb)
+                        | (((lsb & 0xCC) != 0) << 1)
+                        | (((lsb & 0xF0) != 0) << 2));
+        ctx->next_index  = i-(w-1)+s;
+        ctx->next_digit  = v >> s;
+        ctx->next_check -= w;
+    }
+}
+
+static void slide(size_t width, i8 *adds, const u8 scalar[32])
+{
     FOR (j, 0, 253 + width) {
         adds[j] = 0;
     }
+    slide_ctx ctx;
+    slide_init(&ctx, scalar);
+    int i = ctx.next_check;
     while (i >= 0) {
-        unsigned e0 = (unsigned) scalar_bit(scalar, i    );
-        unsigned e1 = (unsigned) scalar_bit(scalar, i - 1);
-        if (e0 == e1) {
-            i--;
-        } else {
-            unsigned w = MIN(width, (unsigned)(i + 1));
-            int      v = -(int)(e0 << (w-1));
-            FOR (j, 0, w-1) {
-                v += scalar_bit(scalar, i-(w-1)+j) << j;
-            }
-            v += scalar_bit(scalar, i-w);
-            unsigned lsb = v & (~v + 1);              // smallest bit of v
-            unsigned s   = ( (lsb & 0xAA) != 0      ) // log2(lsb)
-                         | (((lsb & 0xCC) != 0) << 1)
-                         | (((lsb & 0xF0) != 0) << 2);
-            adds[i-(w-1)+s] = v >> s;
-            i -= w;
+        if (i == ctx.next_check) {
+            slide_step(&ctx, width, i, scalar);
         }
+        if (i == ctx.next_index) {
+            // addition goes here
+            adds[i] = ctx.next_digit;
+        }
+        // doubling goes here
+        i--;
     }
 }