mpi/ec: fix when 'unsigned long' is 32-bit but limb size is 64-bit
[libgcrypt.git] / cipher / cipher-ofb.c
index 3fb9b0d..f821d1b 100644 (file)
 
 #include "g10lib.h"
 #include "cipher.h"
-#include "ath.h"
 #include "bufhelp.h"
 #include "./cipher-internal.h"
 
 
 gcry_err_code_t
 _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
-                          unsigned char *outbuf, unsigned int outbuflen,
-                          const unsigned char *inbuf, unsigned int inbuflen)
+                          unsigned char *outbuf, size_t outbuflen,
+                          const unsigned char *inbuf, size_t inbuflen)
 {
   unsigned char *ivp;
-  size_t blocksize = c->cipher->blocksize;
+  gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
+  size_t blocksize = c->spec->blocksize;
   unsigned int burn, nburn;
 
+  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
+   * length, to allow better optimization of this function.  */
+  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
+    return GPG_ERR_INV_LENGTH;
+
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
@@ -47,7 +52,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
     {
       /* Short enough to be encoded by the remaining XOR mask. */
       /* XOR the input with the IV */
-      ivp = c->u_iv.iv + c->cipher->blocksize - c->unused;
+      ivp = c->u_iv.iv + blocksize - c->unused;
       buf_xor(outbuf, ivp, inbuf, inbuflen);
       c->unused -= inbuflen;
       return 0;
@@ -69,8 +74,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
   while ( inbuflen >= blocksize )
     {
       /* Encrypt the IV (and save the current one). */
-      memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
       burn = nburn > burn ? nburn : burn;
       buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
       outbuf += blocksize;
@@ -79,74 +83,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
     }
   if ( inbuflen )
     { /* process the remaining bytes */
-      memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
-      burn = nburn > burn ? nburn : burn;
-      c->unused = blocksize;
-      c->unused -= inbuflen;
-      buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen);
-      outbuf += inbuflen;
-      inbuf += inbuflen;
-      inbuflen = 0;
-    }
-
-  if (burn > 0)
-    _gcry_burn_stack (burn + 4 * sizeof(void *));
-
-  return 0;
-}
-
-
-gcry_err_code_t
-_gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
-                          unsigned char *outbuf, unsigned int outbuflen,
-                          const unsigned char *inbuf, unsigned int inbuflen)
-{
-  unsigned char *ivp;
-  size_t blocksize = c->cipher->blocksize;
-  unsigned int burn, nburn;
-
-  if (outbuflen < inbuflen)
-    return GPG_ERR_BUFFER_TOO_SHORT;
-
-  if( inbuflen <= c->unused )
-    {
-      /* Short enough to be encoded by the remaining XOR mask. */
-      ivp = c->u_iv.iv + blocksize - c->unused;
-      buf_xor(outbuf, ivp, inbuf, inbuflen);
-      c->unused -= inbuflen;
-      return 0;
-    }
-
-  burn = 0;
-
-  if ( c->unused )
-    {
-      inbuflen -= c->unused;
-      ivp = c->u_iv.iv + blocksize - c->unused;
-      buf_xor(outbuf, ivp, inbuf, c->unused);
-      outbuf += c->unused;
-      inbuf += c->unused;
-      c->unused = 0;
-    }
-
-  /* Now we can process complete blocks. */
-  while ( inbuflen >= blocksize )
-    {
-      /* Encrypt the IV (and save the current one). */
-      memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
-      burn = nburn > burn ? nburn : burn;
-      buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
-      outbuf += blocksize;
-      inbuf += blocksize;
-      inbuflen -= blocksize;
-    }
-  if ( inbuflen )
-    { /* Process the remaining bytes. */
-      /* Encrypt the IV (and save the current one). */
-      memcpy( c->lastiv, c->u_iv.iv, blocksize );
-      nburn = c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+      nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
       burn = nburn > burn ? nburn : burn;
       c->unused = blocksize;
       c->unused -= inbuflen;