cfb8: Fix decrypt path
[gd/nettle] / cfb.c
diff --git a/cfb.c b/cfb.c
index 82cf18f4d9c6e25c60ccb2e75158f4ad1fc13eef..93c3025a220cc17a2cf0edf2d2d77dd7e5632558 100644 (file)
--- a/cfb.c
+++ b/cfb.c
@@ -147,12 +147,11 @@ cfb_decrypt(const void *ctx, nettle_cipher_func *f,
           * not less than block_size. So does part */
 
          f(ctx, block_size, buffer, iv);
-         f(ctx, part - block_size, buffer + block_size, src);
-         memcpy(iv, src + part - block_size, block_size);
+         f(ctx, part - block_size, buffer + block_size, dst);
+         memcpy(iv, dst + part - block_size, block_size);
          memxor(dst, buffer, part);
 
          length -= part;
-         src += part;
          dst += part;
        }
 
@@ -163,3 +162,73 @@ cfb_decrypt(const void *ctx, nettle_cipher_func *f,
        }
     }
 }
+
+/* CFB-8 uses slight optimization: it encrypts or decrypts up to block_size
+ * bytes and does memcpy/memxor afterwards */
+void
+cfb8_encrypt(const void *ctx, nettle_cipher_func *f,
+            size_t block_size, uint8_t *iv,
+            size_t length, uint8_t *dst,
+            const uint8_t *src)
+{
+  TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
+  TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
+  TMP_ALLOC(buffer, block_size * 2);
+  TMP_ALLOC(outbuf, block_size);
+  uint8_t pos;
+
+  memcpy(buffer, iv, block_size);
+  pos = 0;
+  while (length)
+    {
+      uint8_t t;
+
+      if (pos == block_size)
+       {
+         memcpy(buffer, buffer + block_size, block_size);
+         pos = 0;
+       }
+
+      f(ctx, block_size, outbuf, buffer + pos);
+      t = *(dst++) = *(src++) ^ outbuf[0];
+      buffer[pos + block_size] = t;
+      length--;
+      pos ++;
+    }
+  memcpy(iv, buffer + pos, block_size);
+}
+
+void
+cfb8_decrypt(const void *ctx, nettle_cipher_func *f,
+            size_t block_size, uint8_t *iv,
+            size_t length, uint8_t *dst,
+            const uint8_t *src)
+{
+  TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
+  TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
+  TMP_ALLOC(buffer, block_size * 2);
+  TMP_ALLOC(outbuf, block_size * 2);
+  uint8_t i = 0;
+
+  memcpy(buffer + block_size, iv, block_size);
+
+  while (length)
+    {
+
+      memcpy(buffer, buffer + block_size, block_size);
+      memcpy(buffer + block_size, src,
+            length < block_size ? length : block_size);
+
+      for (i = 0; i < length && i < block_size; i++)
+       f(ctx, block_size, outbuf + i, buffer + i);
+
+      memxor3(dst, src, outbuf, i);
+
+      length -= i;
+      src += i;
+      dst += i;
+
+    }
+
+  memcpy(iv, buffer + i, block_size);
+}