Revert to old design for mbedtls_ct_memmove_left

Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
diff --git a/library/constant_time.c b/library/constant_time.c
index c60ec84..d4bd331 100644
--- a/library/constant_time.c
+++ b/library/constant_time.c
@@ -129,48 +129,18 @@
 
 void mbedtls_ct_memmove_left(void *start, size_t total, size_t offset)
 {
-    /* In case of inlining, ensure that code generated is independent of the value of offset
-     * (e.g., if the compiler knows that offset == 0, it might be able to optimise this function
-     * to a no-op). */
-    size_t hidden_offset = mbedtls_ct_compiler_opaque(offset);
-
-    /* During this loop, j will take every value from [0..total) exactly once,
-     * regardless of the value of hidden_offset (it only changes the initial
-     * value for j).
-     *
-     * For this reason, when testing, it is safe to mark hidden_offset as non-secret.
-     * This prevents the const-flow checkers from generating a false-positive.
-     */
-    TEST_CF_PUBLIC(&hidden_offset, sizeof(hidden_offset));
-
-    /* Iterate over the array, reading each byte once and writing each byte once. */
+    volatile unsigned char *buf = start;
     for (size_t i = 0; i < total; i++) {
-        /* Each iteration, read one byte, and write it to start[i].
-         *
-         * The source address will either be the "true" source address, if it's in the range
-         * where data is getting moved, or (if the source address is off the end of the
-         * array), it will wrap back to the start.
-         *
-         * If the source address is out of range, mask it to zero.
-         */
-
-        // The offset that we will read from (if in range)
-        size_t j = i + hidden_offset;
-
-        // Is the address off the end of the array?
-        mbedtls_ct_condition_t not_dummy = mbedtls_ct_bool_lt(j, total);
-
-        // Bring read address into range
-        j = j % total;
-
-        // Read a byte
-        uint8_t b = ((uint8_t *) start)[j];
-
-        // Set it to zero if it's out of range
-        b = mbedtls_ct_uint_if0(not_dummy, b);
-
-        // Write the byte to start[i]
-        ((uint8_t *) start)[i] = b;
+        mbedtls_ct_condition_t no_op = mbedtls_ct_bool_gt(total - offset, i);
+        /* The first `total - offset` passes are a no-op. The last
+         * `offset` passes shift the data one byte to the left and
+         * zero out the last byte. */
+        for (size_t n = 0; n < total - 1; n++) {
+            unsigned char current = buf[n];
+            unsigned char next    = buf[n+1];
+            buf[n] = mbedtls_ct_uint_if(no_op, current, next);
+        }
+        buf[total-1] = mbedtls_ct_uint_if0(no_op, buf[total-1]);
     }
 }