Bleichenbacher fix: don't leak the plaintext length (step 2)

Replace memmove(to, to + offset, length) by a functionally equivalent
function that strives to make the same memory access patterns
regardless of the value of length. This fixes an information leak
through timing (especially timing of memory accesses via cache probes)
that leads to a Bleichenbacher-style attack on PKCS#1 v1.5 decryption
using the plaintext length as the observable.
diff --git a/library/rsa.c b/library/rsa.c
index f4aafa9..f4a680c 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -1397,6 +1397,22 @@
 #endif
 }
 
+/** Check whether a size is out of bounds, without branches.
+ *
+ * This is equivalent to `size > max`, but is likely to be compiled to
+ * to code using bitwise operation rather than a branch.
+ *
+ * \param size      Size to check.
+ * \param max       Maximum desired value for \p size.
+ * \return          \c 0 if `size <= max`.
+ * \return          \c 1 if `size > max`.
+ */
+static unsigned size_greater_than( size_t size, size_t max )
+{
+    /* Return the sign bit (1 for negative) of (max - size). */
+    return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) );
+}
+
 /** Choose between two integer values, without branches.
  *
  * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled
@@ -1413,6 +1429,42 @@
     return( ( mask & if1 ) | (~mask & if0 ) );
 }
 
+/** Shift some data towards the left inside a buffer without leaking
+ * the length of the data through side channels.
+ *
+ * `mem_move_to_left(start, total, offset)` is functionally equivalent to
+ * ```
+ * memmove(start, start + offset, total - offset);
+ * memset(start + offset, 0, total - offset);
+ * ```
+ * but it strives to use a memory access pattern (and thus total timing)
+ * that does not depend on \p offset. This timing independence comes at
+ * the expense of performance.
+ *
+ * \param start     Pointer to the start of the buffer.
+ * \param total     Total size of the buffer.
+ * \param offset    Offset from which to copy \p total - \p offset bytes.
+ */
+static void mem_move_to_left( void *start,
+                              size_t total,
+                              size_t offset )
+{
+    volatile unsigned char *buf = start;
+    size_t i, n;
+    if( total == 0 )
+        return;
+    for( i = 0; i < total; i++ )
+    {
+        unsigned no_op = size_greater_than( 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( n = 0; n < total - 1; n++ )
+            buf[n] = if_int( no_op, buf[n], buf[n+1] );
+        buf[total-1] = if_int( no_op, buf[total-1], 0 );
+    }
+}
+
 /*
  * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
  */
@@ -1538,8 +1590,7 @@
      * its position no longer depends on the padding and we have enough
      * room from the beginning of the plaintext to copy a number of bytes
      * that does not depend on the padding.  */
-    /* FIXME: we need a constant-time, constant-trace memmove here. */
-    memmove( buf, p, plaintext_size );
+    mem_move_to_left( buf, ilen, ilen - plaintext_size );
 
     /* Finally copy the decrypted plaintext plus trailing data
      * into the output buffer. */