]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
(cbc_decrypt_internal): New function, doing the real CBC
authorNiels Möller <nisse@lysator.liu.se>
Mon, 11 Feb 2002 17:48:48 +0000 (18:48 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Mon, 11 Feb 2002 17:48:48 +0000 (18:48 +0100)
procesing and requiring that src != dst.
(cbc_decrypt): Use cbc_decrypt_internal. If src == dst, use a
buffer of limited size to copy the ciphertext.

Rev: src/nettle/cbc.c:1.5

cbc.c

diff --git a/cbc.c b/cbc.c
index 1873c8642c9dc98415307508e543afcf8dcdd643..0eb96f022df27e0c1a586df7c686f9ad0599b775 100644 (file)
--- a/cbc.c
+++ b/cbc.c
@@ -49,6 +49,31 @@ cbc_encrypt(void *ctx, void (*f)(void *ctx,
     }
 }
 
+/* Reqires that dst != src */
+static void
+cbc_decrypt_internal(void *ctx, void (*f)(void *ctx,
+                                         unsigned length, uint8_t *dst,
+                                         const uint8_t *src),
+                    unsigned block_size, uint8_t *iv,
+                    unsigned length, uint8_t *dst,
+                    const uint8_t *src)
+{
+  assert(length);
+  assert( !(length % block_size) );
+  assert(src != dst);
+  
+  /* Decrypt in ECB mode */
+  f(ctx, length, dst, src);
+
+  /* XOR the cryptotext, shifted one block */
+  memxor(dst, iv, block_size);
+  memxor(dst + block_size, src, length - block_size);
+  memcpy(iv, src + length - block_size, block_size);
+}
+
+/* Don't allocate any more space than this on the stack */
+#define CBC_BUFFER_LIMIT 4096
+
 void
 cbc_decrypt(void *ctx, void (*f)(void *ctx,
                                 unsigned length, uint8_t *dst,
@@ -62,23 +87,49 @@ cbc_decrypt(void *ctx, void (*f)(void *ctx,
   if (!length)
     return;
 
-  if (src == dst)
+  if (src != dst)
+    cbc_decrypt_internal(ctx, f, block_size, iv,
+                        length, dst, src);
+  else
     {
-      /* Keep a copy of the ciphertext. */
-      /* FIXME: If length is large enough, allocate a smaller buffer
-       * and process one buffer size at a time */
-      uint8_t *tmp = alloca(length);
-      memcpy(tmp, src, length);
-      src = tmp;
+      /* We need a copy of the ciphertext, so we can't ECB decrypt in
+       * place.
+       *
+       * If length is small, we allocate a complete copy of src on the
+       * stack. Otherwise, we allocate a block of size at most
+       * CBC_BUFFER_LIMIT, and process that amount of data at a
+       * time.
+       *
+       * NOTE: We assume that block_size <= CBC_BUFFER_LIMIT. */
+
+      uint8_t *buffer;
+      
+      if (length <= CBC_BUFFER_LIMIT)
+       buffer = alloca(length);
+      else
+       {
+         /* The buffer size must be an integral number of blocks. */
+         unsigned buffer_size
+           = CBC_BUFFER_LIMIT - (CBC_BUFFER_LIMIT % block_size);
+
+         buffer = alloca(buffer_size);
+
+         for ( ; length >= buffer_size;
+               length -= buffer_size, dst += buffer_size, src += buffer_size)
+           {
+             memcpy(buffer, src, buffer_size);
+             cbc_decrypt_internal(ctx, f, block_size, iv,
+                                  buffer_size, dst, buffer);
+           }
+         if (!length)
+           return;
+       }
+      /* Now, we have at most CBC_BUFFER_LIMIT octets left */
+      memcpy(buffer, src, length);
+
+      cbc_decrypt_internal(ctx, f, block_size, iv,
+                          length, dst, buffer);
     }
-
-  /* Decrypt in ECB mode */
-  f(ctx, length, dst, src);
-
-  /* XOR the cryptotext, shifted one block */
-  memxor(dst, iv, block_size);
-  memxor(dst + block_size, src, length - block_size);
-  memcpy(iv, src + length - block_size, block_size);
 }
 
 #if 0