CTR mode may now be used with arbitrary long data chunks.
[libgcrypt.git] / cipher / cipher.c
index 4808a5f..90fdb17 100644 (file)
 #define CTX_MAGIC_NORMAL 0x24091964
 #define CTX_MAGIC_SECURE 0x46919042
 
+/* Try to use 16 byte aligned cipher context for better performance.
+   We use the aligned attribute, thus it is only possible to implement
+   this with gcc.  */
 #undef NEED_16BYTE_ALIGNED_CONTEXT
-#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
-#define NEED_16BYTE_ALIGNED_CONTEXT 1
+#if defined (__GNUC__)
+# define NEED_16BYTE_ALIGNED_CONTEXT 1
 #endif
 
 /* A dummy extraspec so that we do not need to tests the extraspec
@@ -58,39 +61,39 @@ static struct cipher_table_entry
       &dummy_extra_spec,                  GCRY_CIPHER_BLOWFISH },
 #endif
 #if USE_DES
-    { &_gcry_cipher_spec_des,       
+    { &_gcry_cipher_spec_des,
       &dummy_extra_spec,                  GCRY_CIPHER_DES },
     { &_gcry_cipher_spec_tripledes,
       &_gcry_cipher_extraspec_tripledes,  GCRY_CIPHER_3DES, 1 },
 #endif
 #if USE_ARCFOUR
-    { &_gcry_cipher_spec_arcfour,    
+    { &_gcry_cipher_spec_arcfour,
       &dummy_extra_spec,                  GCRY_CIPHER_ARCFOUR },
 #endif
 #if USE_CAST5
-    { &_gcry_cipher_spec_cast5,      
+    { &_gcry_cipher_spec_cast5,
       &dummy_extra_spec,                  GCRY_CIPHER_CAST5 },
 #endif
 #if USE_AES
-    { &_gcry_cipher_spec_aes,        
+    { &_gcry_cipher_spec_aes,
       &_gcry_cipher_extraspec_aes,        GCRY_CIPHER_AES,    1 },
-    { &_gcry_cipher_spec_aes192,     
+    { &_gcry_cipher_spec_aes192,
       &_gcry_cipher_extraspec_aes192,     GCRY_CIPHER_AES192, 1 },
-    { &_gcry_cipher_spec_aes256,     
+    { &_gcry_cipher_spec_aes256,
       &_gcry_cipher_extraspec_aes256,     GCRY_CIPHER_AES256, 1 },
 #endif
 #if USE_TWOFISH
     { &_gcry_cipher_spec_twofish,
       &dummy_extra_spec,                  GCRY_CIPHER_TWOFISH },
-    { &_gcry_cipher_spec_twofish128,     
+    { &_gcry_cipher_spec_twofish128,
       &dummy_extra_spec,                  GCRY_CIPHER_TWOFISH128 },
 #endif
 #if USE_SERPENT
-    { &_gcry_cipher_spec_serpent128, 
+    { &_gcry_cipher_spec_serpent128,
       &dummy_extra_spec,                  GCRY_CIPHER_SERPENT128 },
     { &_gcry_cipher_spec_serpent192,
       &dummy_extra_spec,                  GCRY_CIPHER_SERPENT192 },
-    { &_gcry_cipher_spec_serpent256, 
+    { &_gcry_cipher_spec_serpent256,
       &dummy_extra_spec,                  GCRY_CIPHER_SERPENT256 },
 #endif
 #if USE_RFC2268
@@ -98,13 +101,13 @@ static struct cipher_table_entry
       &dummy_extra_spec,                  GCRY_CIPHER_RFC2268_40 },
 #endif
 #if USE_SEED
-    { &_gcry_cipher_spec_seed, 
+    { &_gcry_cipher_spec_seed,
       &dummy_extra_spec,                  GCRY_CIPHER_SEED },
 #endif
 #if USE_CAMELLIA
     { &_gcry_cipher_spec_camellia128,
       &dummy_extra_spec,                  GCRY_CIPHER_CAMELLIA128 },
-    { &_gcry_cipher_spec_camellia192, 
+    { &_gcry_cipher_spec_camellia192,
       &dummy_extra_spec,                  GCRY_CIPHER_CAMELLIA192 },
     { &_gcry_cipher_spec_camellia256,
       &dummy_extra_spec,                  GCRY_CIPHER_CAMELLIA256 },
@@ -118,7 +121,7 @@ static gcry_module_t ciphers_registered;
 /* This is the lock protecting CIPHERS_REGISTERED.  */
 static ath_mutex_t ciphers_registered_lock = ATH_MUTEX_INITIALIZER;
 
-/* Flag to check wether the default ciphers have already been
+/* Flag to check whether the default ciphers have already been
    registered.  */
 static int default_ciphers_registered;
 
@@ -137,19 +140,20 @@ static int default_ciphers_registered;
   while (0)
 
 
-/* A VIA processor with the Padlock engine requires an alignment of
-   most data on a 16 byte boundary.  Because we trick out the compiler
-   while allocating the context, the align attribute as used in
-   rijndael.c does not work on its own.  Thus we need to make sure
-   that the entire context structure is a aligned on that boundary.
-   We achieve this by defining a new type and use that instead of our
-   usual alignment type.  */
-typedef union 
+/* A VIA processor with the Padlock engine as well as the Intel AES_NI
+   instructions require an alignment of most data on a 16 byte
+   boundary.  Because we trick out the compiler while allocating the
+   context, the align attribute as used in rijndael.c does not work on
+   its own.  Thus we need to make sure that the entire context
+   structure is a aligned on that boundary.  We achieve this by
+   defining a new type and use that instead of our usual alignment
+   type.  */
+typedef union
 {
   PROPERLY_ALIGNED_TYPE foo;
 #ifdef NEED_16BYTE_ALIGNED_CONTEXT
   char bar[16] __attribute__ ((aligned (16)));
-#endif  
+#endif
   char c[1];
 } cipher_context_alignment_t;
 
@@ -166,7 +170,7 @@ struct gcry_cipher_handle
 
   /* The algorithm id.  This is a hack required because the module
      interface does not easily allow to retrieve this value. */
-  int algo;  
+  int algo;
 
   /* A structure with function pointers for bulk operations.  Due to
      limitations of the module system (we don't want to change the
@@ -174,16 +178,19 @@ struct gcry_cipher_handle
      open function intializes them and the actual encryption routines
      use them if they are not NULL.  */
   struct {
-    void (*cfb_enc)(void *context, unsigned char *iv, 
+    void (*cfb_enc)(void *context, unsigned char *iv,
                     void *outbuf_arg, const void *inbuf_arg,
                     unsigned int nblocks);
-    void (*cfb_dec)(void *context, unsigned char *iv, 
+    void (*cfb_dec)(void *context, unsigned char *iv,
                     void *outbuf_arg, const void *inbuf_arg,
                     unsigned int nblocks);
-    void (*cbc_enc)(void *context, unsigned char *iv, 
+    void (*cbc_enc)(void *context, unsigned char *iv,
                     void *outbuf_arg, const void *inbuf_arg,
                     unsigned int nblocks, int cbc_mac);
-    void (*cbc_dec)(void *context, unsigned char *iv, 
+    void (*cbc_dec)(void *context, unsigned char *iv,
+                    void *outbuf_arg, const void *inbuf_arg,
+                    unsigned int nblocks);
+    void (*ctr_enc)(void *context, unsigned char *iv,
                     void *outbuf_arg, const void *inbuf_arg,
                     unsigned int nblocks);
   } bulk;
@@ -194,22 +201,27 @@ struct gcry_cipher_handle
 
   struct {
     unsigned int key:1; /* Set to 1 if a key has been set.  */
-    unsigned int iv:1;  /* Set to 1 if ae IV has been set.  */
+    unsigned int iv:1;  /* Set to 1 if a IV has been set.  */
   } marks;
 
-  /* The initialization vector.  To help code optimization we make
-     sure that it is aligned on an unsigned long and u32 boundary.  */
+  /* The initialization vector.  For best performance we make sure
+     that it is properly aligned.  In particular some implementations
+     of bulk operations expect an 16 byte aligned IV.  */
   union {
-    unsigned long dummy_iv;         
-    u32 dummy_u32_iv;
-    unsigned char iv[MAX_BLOCKSIZE];   
+    cipher_context_alignment_t iv_align;
+    unsigned char iv[MAX_BLOCKSIZE];
   } u_iv;
 
-  unsigned char lastiv[MAX_BLOCKSIZE];
-  int unused;  /* Number of unused bytes in the IV. */
-
-  unsigned char ctr[MAX_BLOCKSIZE];     /* For Counter (CTR) mode. */
+  /* The counter for CTR mode.  This field is also used by AESWRAP and
+     thus we can't use the U_IV union.  */
+  union {
+    cipher_context_alignment_t iv_align;
+    unsigned char ctr[MAX_BLOCKSIZE];
+  } u_ctr;
 
+  /* Space to save an IV or CTR for chaining operations.  */
+  unsigned char lastiv[MAX_BLOCKSIZE];
+  int unused;  /* Number of unused bytes in LASTIV. */
 
   /* What follows are two contexts of the cipher in use.  The first
      one needs to be aligned well enough for the cipher operation
@@ -227,7 +239,7 @@ struct gcry_cipher_handle
 static gcry_err_code_t
 dummy_setkey (void *c, const unsigned char *key, unsigned int keylen)
 {
-  (void)c; 
+  (void)c;
   (void)key;
   (void)keylen;
   return GPG_ERR_NO_ERROR;
@@ -286,7 +298,7 @@ cipher_register_default (void)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   int i;
-  
+
   for (i = 0; !err && cipher_table[i].cipher; i++)
     {
       if (! cipher_table[i].cipher->setkey)
@@ -389,8 +401,8 @@ _gcry_cipher_register (gcry_cipher_spec_t *cipher,
 
   ath_mutex_lock (&ciphers_registered_lock);
   err = _gcry_module_add (&ciphers_registered, 0,
-                         (void *)cipher, 
-                         (void *)(extraspec? extraspec : &dummy_extra_spec), 
+                         (void *)cipher,
+                         (void *)(extraspec? extraspec : &dummy_extra_spec),
                           &mod);
   ath_mutex_unlock (&ciphers_registered_lock);
 
@@ -420,7 +432,7 @@ gcry_cipher_unregister (gcry_module_t module)
    ispassed as NULL.  A pointer to the specification of the module
    implementing this algorithm is return in OID_SPEC unless passed as
    NULL.*/
-static int 
+static int
 search_oid (const char *oid, int *algorithm, gcry_cipher_oid_spec_t *oid_spec)
 {
   gcry_module_t module;
@@ -484,7 +496,7 @@ gcry_cipher_map_name (const char *string)
     }
 
   ath_mutex_unlock (&ciphers_registered_lock);
-  
+
   return algorithm;
 }
 
@@ -593,7 +605,7 @@ check_cipher_algo (int algorithm)
   else
     err = GPG_ERR_CIPHER_ALGO;
   ath_mutex_unlock (&ciphers_registered_lock);
-  
+
   return err;
 }
 
@@ -683,10 +695,10 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
   /* If the application missed to call the random poll function, we do
      it here to ensure that it is used once in a while. */
   _gcry_fast_random_poll ();
-  
+
   REGISTER_DEFAULT_CIPHERS;
 
-  /* Fetch the according module and check wether the cipher is marked
+  /* Fetch the according module and check whether the cipher is marked
      available for use.  */
   ath_mutex_lock (&ciphers_registered_lock);
   module = _gcry_module_lookup_id (ciphers_registered, algo);
@@ -698,7 +710,6 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
        {
          /* Not available for use.  */
          err = GPG_ERR_CIPHER_ALGO;
-         _gcry_module_release (module);
        }
       else
         {
@@ -712,7 +723,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
 
   /* check flags */
   if ((! err)
-      && ((flags & ~(0 
+      && ((flags & ~(0
                     | GCRY_CIPHER_SECURE
                     | GCRY_CIPHER_ENABLE_SYNC
                     | GCRY_CIPHER_CBC_CTS
@@ -811,9 +822,10 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
               h->bulk.cfb_dec = _gcry_aes_cfb_dec;
               h->bulk.cbc_enc = _gcry_aes_cbc_enc;
               h->bulk.cbc_dec = _gcry_aes_cbc_dec;
+              h->bulk.ctr_enc = _gcry_aes_ctr_enc;
               break;
 #endif /*USE_AES*/
-              
+
             default:
               break;
             }
@@ -903,7 +915,7 @@ static void
 cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen )
 {
   memset (c->u_iv.iv, 0, c->cipher->blocksize);
-  if (iv) 
+  if (iv)
     {
       if (ivlen != c->cipher->blocksize)
         {
@@ -933,7 +945,7 @@ cipher_reset (gcry_cipher_hd_t c)
   memset (&c->marks, 0, sizeof c->marks);
   memset (c->u_iv.iv, 0, c->cipher->blocksize);
   memset (c->lastiv, 0, c->cipher->blocksize);
-  memset (c->ctr, 0, c->cipher->blocksize);
+  memset (c->u_ctr.ctr, 0, c->cipher->blocksize);
 }
 
 
@@ -945,7 +957,7 @@ do_ecb_encrypt (gcry_cipher_hd_t c,
 {
   unsigned int blocksize = c->cipher->blocksize;
   unsigned int n, nblocks;
-  
+
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
   if ((inbuflen % blocksize))
@@ -976,7 +988,7 @@ do_ecb_decrypt (gcry_cipher_hd_t c,
     return GPG_ERR_INV_LENGTH;
   nblocks = inbuflen / c->cipher->blocksize;
 
-  for (n=0; n < nblocks; n++ ) 
+  for (n=0; n < nblocks; n++ )
     {
       c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf );
       inbuf  += blocksize;
@@ -1006,7 +1018,7 @@ do_cbc_encrypt (gcry_cipher_hd_t c,
            && (c->flags & GCRY_CIPHER_CBC_CTS)))
     return GPG_ERR_INV_LENGTH;
 
-  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) 
+  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
     {
       if ((inbuflen % blocksize) == 0)
        nblocks--;
@@ -1015,7 +1027,7 @@ do_cbc_encrypt (gcry_cipher_hd_t c,
   if (c->bulk.cbc_enc)
     {
       c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks,
-                       (c->flags & GCRY_CIPHER_CBC_MAC)); 
+                       (c->flags & GCRY_CIPHER_CBC_MAC));
       inbuf  += nblocks * blocksize;
       if (!(c->flags & GCRY_CIPHER_CBC_MAC))
         outbuf += nblocks * blocksize;
@@ -1055,7 +1067,7 @@ do_cbc_encrypt (gcry_cipher_hd_t c,
         }
       for (; i < blocksize; i++)
         outbuf[i] = 0 ^ *ivp++;
-      
+
       c->cipher->encrypt (&c->context.c, outbuf, outbuf);
       memcpy (c->u_iv.iv, outbuf, blocksize);
     }
@@ -1093,13 +1105,13 @@ do_cbc_decrypt (gcry_cipher_hd_t c,
 
   if (c->bulk.cbc_dec)
     {
-      c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); 
+      c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
       inbuf  += nblocks * blocksize;
       outbuf += nblocks * blocksize;
     }
   else
     {
-      for (n=0; n < nblocks; n++ ) 
+      for (n=0; n < nblocks; n++ )
         {
           /* Because outbuf and inbuf might be the same, we have to
            * save the original ciphertext block.  We use LASTIV for
@@ -1114,22 +1126,22 @@ do_cbc_decrypt (gcry_cipher_hd_t c,
         }
     }
 
-  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) 
+  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
     {
       int restbytes;
-      
+
       if ((inbuflen % blocksize) == 0)
         restbytes = blocksize;
       else
         restbytes = inbuflen % blocksize;
-      
+
       memcpy (c->lastiv, c->u_iv.iv, blocksize );         /* Save Cn-2. */
       memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
 
       c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
       for (ivp=c->u_iv.iv,i=0; i < restbytes; i++ )
         outbuf[i] ^= *ivp++;
-      
+
       memcpy(outbuf + blocksize, outbuf, restbytes);
       for(i=restbytes; i < blocksize; i++)
         c->u_iv.iv[i] = outbuf[i];
@@ -1151,7 +1163,7 @@ do_cfb_encrypt (gcry_cipher_hd_t c,
   unsigned char *ivp;
   size_t blocksize = c->cipher->blocksize;
   size_t blocksize_x_2 = blocksize + blocksize;
-  
+
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
@@ -1180,7 +1192,7 @@ do_cfb_encrypt (gcry_cipher_hd_t c,
   if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc)
     {
       unsigned int nblocks = inbuflen / blocksize;
-      c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); 
+      c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
       outbuf += nblocks * blocksize;
       inbuf  += nblocks * blocksize;
       inbuflen -= nblocks * blocksize;
@@ -1210,7 +1222,7 @@ do_cfb_encrypt (gcry_cipher_hd_t c,
         *outbuf++ = (*ivp++ ^= *inbuf++);
       inbuflen -= blocksize;
     }
-  if ( inbuflen ) 
+  if ( inbuflen )
     {
       /* Save the current IV and then encrypt the IV. */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
@@ -1235,7 +1247,7 @@ do_cfb_decrypt (gcry_cipher_hd_t c,
   int i;
   size_t blocksize = c->cipher->blocksize;
   size_t blocksize_x_2 = blocksize + blocksize;
-  
+
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
@@ -1244,7 +1256,7 @@ do_cfb_decrypt (gcry_cipher_hd_t c,
       /* Short enough to be encoded by the remaining XOR mask. */
       /* XOR the input with the IV and store input into IV. */
       for (ivp=c->u_iv.iv+blocksize - c->unused;
-           inbuflen; 
+           inbuflen;
            inbuflen--, c->unused--)
         {
           temp = *inbuf++;
@@ -1253,7 +1265,7 @@ do_cfb_decrypt (gcry_cipher_hd_t c,
         }
       return 0;
     }
-  
+
   if (c->unused)
     {
       /* XOR the input with the IV and store input into IV. */
@@ -1265,14 +1277,14 @@ do_cfb_decrypt (gcry_cipher_hd_t c,
           *ivp++ = temp;
         }
     }
-  
+
   /* Now we can process complete blocks.  We use a loop as long as we
      have at least 2 blocks and use conditions for the rest.  This
      also allows to use a bulk encryption function if available.  */
   if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec)
     {
       unsigned int nblocks = inbuflen / blocksize;
-      c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); 
+      c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
       outbuf += nblocks * blocksize;
       inbuf  += nblocks * blocksize;
       inbuflen -= nblocks * blocksize;
@@ -1310,7 +1322,7 @@ do_cfb_decrypt (gcry_cipher_hd_t c,
     }
 
   if (inbuflen)
-    { 
+    {
       /* Save the current IV and then encrypt the IV. */
       memcpy ( c->lastiv, c->u_iv.iv, blocksize );
       c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
@@ -1364,7 +1376,7 @@ do_ofb_encrypt (gcry_cipher_hd_t c,
       /* Encrypt the IV (and save the current one). */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
       c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
-      
+
       for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
         *outbuf++ = (*ivp++ ^ *inbuf++);
       inbuflen -= blocksize;
@@ -1388,7 +1400,7 @@ do_ofb_decrypt (gcry_cipher_hd_t c,
 {
   unsigned char *ivp;
   size_t blocksize = c->cipher->blocksize;
-  
+
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
@@ -1418,7 +1430,7 @@ do_ofb_decrypt (gcry_cipher_hd_t c,
         *outbuf++ = *ivp++ ^ *inbuf++;
       inbuflen -= blocksize;
     }
-  if ( inbuflen ) 
+  if ( inbuflen )
     { /* Process the remaining bytes. */
       /* Encrypt the IV (and save the current one). */
       memcpy( c->lastiv, c->u_iv.iv, blocksize );
@@ -1438,35 +1450,72 @@ do_ctr_encrypt (gcry_cipher_hd_t c,
                 const unsigned char *inbuf, unsigned int inbuflen)
 {
   unsigned int n;
-  unsigned char tmp[MAX_BLOCKSIZE];
   int i;
   unsigned int blocksize = c->cipher->blocksize;
+  unsigned int nblocks;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
-  if ((inbuflen % blocksize))
-    return GPG_ERR_INV_LENGTH;
+  /* First process a left over encrypted counter.  */
+  if (c->unused)
+    {
+      gcry_assert (c->unused < blocksize);
+      i = blocksize - c->unused;
+      for (n=0; c->unused && n < inbuflen; c->unused--, n++, i++)
+        {
+          /* XOR input with encrypted counter and store in output.  */
+          outbuf[n] = inbuf[n] ^ c->lastiv[i];
+        }
+      inbuf  += n;
+      outbuf += n;
+      inbuflen -= n;
+    }
+
 
-  for (n=0; n < inbuflen; n++)
+  /* Use a bulk method if available.  */
+  nblocks = inbuflen / blocksize;
+  if (nblocks && c->bulk.ctr_enc)
     {
-      if ((n % blocksize) == 0)
-       {
-         c->cipher->encrypt (&c->context.c, tmp, c->ctr);
+      c->bulk.ctr_enc (&c->context.c, c->u_ctr.ctr, outbuf, inbuf, nblocks);
+      inbuf  += nblocks * blocksize;
+      outbuf += nblocks * blocksize;
+      inbuflen -= nblocks * blocksize;
+    }
 
-         for (i = blocksize; i > 0; i--)
-           {
-             c->ctr[i-1]++;
-             if (c->ctr[i-1] != 0)
-               break;
-           }
-       }
+  /* If we don't have a bulk method use the standard method.  We also
+     use this method for the a remaining partial block.  */
+  if (inbuflen)
+    {
+      unsigned char tmp[MAX_BLOCKSIZE];
+
+      for (n=0; n < inbuflen; n++)
+        {
+          if ((n % blocksize) == 0)
+            {
+              c->cipher->encrypt (&c->context.c, tmp, c->u_ctr.ctr);
+
+              for (i = blocksize; i > 0; i--)
+                {
+                  c->u_ctr.ctr[i-1]++;
+                  if (c->u_ctr.ctr[i-1] != 0)
+                    break;
+                }
+            }
+
+          /* XOR input with encrypted counter and store in output.  */
+          outbuf[n] = inbuf[n] ^ tmp[n % blocksize];
+        }
 
-      /* XOR input with encrypted counter and store in output.  */
-      outbuf[n] = inbuf[n] ^ tmp[n % blocksize];
+      /* Save the unused bytes of the counter.  */
+      n %= blocksize;
+      c->unused = (blocksize - n) % blocksize;
+      if (c->unused)
+        memcpy (c->lastiv+n, tmp+n, c->unused);
+
+      wipememory (tmp, sizeof tmp);
     }
 
-  wipememory (tmp, sizeof tmp);
   return 0;
 }
 
@@ -1496,15 +1545,15 @@ do_aeswrap_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
 #endif
   /* We require a cipher with a 128 bit block length.  */
   if (c->cipher->blocksize != 16)
-    return GPG_ERR_INV_LENGTH;  
-  
+    return GPG_ERR_INV_LENGTH;
+
   /* The output buffer must be able to hold the input data plus one
      additional block.  */
   if (outbuflen < inbuflen + 8)
     return GPG_ERR_BUFFER_TOO_SHORT;
   /* Input data must be multiple of 64 bits.  */
   if (inbuflen % 8)
-    return GPG_ERR_INV_ARG;   
+    return GPG_ERR_INV_ARG;
 
   n = inbuflen / 8;
 
@@ -1512,9 +1561,9 @@ do_aeswrap_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
   if (n < 2)
     return GPG_ERR_INV_ARG;
 
-  r = outbuf; 
+  r = outbuf;
   a = outbuf;  /* We store A directly in OUTBUF.  */
-  b = c->ctr;  /* B is also used to concatenate stuff.  */
+  b = c->u_ctr.ctr;  /* B is also used to concatenate stuff.  */
 
   /* If an IV has been set we use that IV as the Alternative Initial
      Value; if it has not been set we use the standard value.  */
@@ -1550,7 +1599,7 @@ do_aeswrap_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
           memcpy (r+i*8, b+8, 8);
         }
    }
-  
+
   return 0;
 }
 
@@ -1571,8 +1620,8 @@ do_aeswrap_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
 #endif
   /* We require a cipher with a 128 bit block length.  */
   if (c->cipher->blocksize != 16)
-    return GPG_ERR_INV_LENGTH;  
-  
+    return GPG_ERR_INV_LENGTH;
+
   /* The output buffer must be able to hold the input data minus one
      additional block.  Fixme: The caller has more restrictive checks
      - we may want to fix them for this mode.  */
@@ -1580,7 +1629,7 @@ do_aeswrap_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
     return GPG_ERR_BUFFER_TOO_SHORT;
   /* Input data must be multiple of 64 bits.  */
   if (inbuflen % 8)
-    return GPG_ERR_INV_ARG;   
+    return GPG_ERR_INV_ARG;
 
   n = inbuflen / 8;
 
@@ -1588,9 +1637,9 @@ do_aeswrap_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
   if (n < 3)
     return GPG_ERR_INV_ARG;
 
-  r = outbuf; 
+  r = outbuf;
   a = c->lastiv;  /* We use c->LASTIV as buffer for A.  */
-  b = c->ctr;     /* B is also used to concatenate stuff.  */
+  b = c->u_ctr.ctr;     /* B is also used to concatenate stuff.  */
 
   /* Copy the inbuf to the outbuf and save A. */
   memcpy (a, inbuf, 8);
@@ -1664,7 +1713,7 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
     case GCRY_CIPHER_MODE_CBC:
       rc = do_cbc_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
       break;
-      
+
     case GCRY_CIPHER_MODE_CFB:
       rc = do_cfb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
       break;
@@ -1700,7 +1749,7 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
           rc = 0;
         }
       break;
-      
+
     default:
       log_fatal ("cipher_encrypt: invalid mode %d\n", c->mode );
       rc = GPG_ERR_INV_CIPHER_MODE;
@@ -1729,7 +1778,7 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
   /* Failsafe: Make sure that the plaintext will never make it into
      OUT if the encryption returned an error.  */
   if (err && out)
-    memset (out, 0x42, outsize); 
+    memset (out, 0x42, outsize);
 
   return gcry_error (err);
 }
@@ -1792,7 +1841,7 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
           rc = 0;
         }
       break;
-      
+
     default:
       log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode );
       rc = GPG_ERR_INV_CIPHER_MODE;
@@ -1858,9 +1907,15 @@ gpg_error_t
 _gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen)
 {
   if (ctr && ctrlen == hd->cipher->blocksize)
-    memcpy (hd->ctr, ctr, hd->cipher->blocksize);
+    {
+      memcpy (hd->u_ctr.ctr, ctr, hd->cipher->blocksize);
+      hd->unused = 0;
+    }
   else if (!ctr || !ctrlen)
-    memset (hd->ctr, 0, hd->cipher->blocksize);
+    {
+      memset (hd->u_ctr.ctr, 0, hd->cipher->blocksize);
+      hd->unused = 0;
+    }
   else
     return gpg_error (GPG_ERR_INV_ARG);
   return 0;
@@ -1919,17 +1974,12 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
       break;
 
     case GCRYCTL_SET_CTR: /* Deprecated; use gcry_cipher_setctr.  */
-      if (buffer && buflen == h->cipher->blocksize)
-       memcpy (h->ctr, buffer, h->cipher->blocksize);
-      else if (buffer == NULL || buflen == 0)
-       memset (h->ctr, 0, h->cipher->blocksize);
-      else
-       rc = GPG_ERR_INV_ARG;
+      rc = gpg_err_code (_gcry_cipher_setctr (h, buffer, buflen));
       break;
 
     case 61:  /* Disable weak key detection (private).  */
       if (h->extraspec->set_extra_info)
-        rc = h->extraspec->set_extra_info 
+        rc = h->extraspec->set_extra_info
           (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0);
       else
         rc = GPG_ERR_NOT_SUPPORTED;
@@ -1937,7 +1987,7 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
 
     case 62: /* Return current input vector (private).  */
       /* This is the input block as used in CFB and OFB mode which has
-         initially been set as IV.  The returned format is: 
+         initially been set as IV.  The returned format is:
            1 byte  Actual length of the block in bytes.
            n byte  The block.
          If the provided buffer is too short, an error is returned. */
@@ -1948,7 +1998,7 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
           unsigned char *ivp;
           unsigned char *dst = buffer;
           int n = h->unused;
-          
+
           if (!n)
             n = h->cipher->blocksize;
           gcry_assert (n <= h->cipher->blocksize);
@@ -1970,10 +2020,10 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
 /* Return information about the cipher handle H.  CMD is the kind of
    information requested.  BUFFER and NBYTES are reserved for now.
 
-   There are no values for CMD yet defined.  
+   There are no values for CMD yet defined.
+
+   The function always returns GPG_ERR_INV_OP.
 
-   The fucntion always returns GPG_ERR_INV_OP.
-   
  */
 gcry_error_t
 gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
@@ -2010,11 +2060,11 @@ gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
     GCRYCTL_TEST_ALGO:
        Returns 0 if the specified algorithm ALGO is available for use.
        BUFFER and NBYTES must be zero.
-  
+
    Note: Because this function is in most cases used to return an
    integer value, we can make it easier for the caller to just look at
    the return value.  The caller will in all cases consult the value
-   and thereby detecting whether a error occured or not (i.e. while
+   and thereby detecting whether a error occurred or not (i.e. while
    checking the block size)
  */
 gcry_error_t
@@ -2079,7 +2129,7 @@ gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
    gcry_cipher_algo_info because it allows for proper type
    checking.  */
 size_t
-gcry_cipher_get_algo_keylen (int algo) 
+gcry_cipher_get_algo_keylen (int algo)
 {
   size_t n;
 
@@ -2095,7 +2145,7 @@ gcry_cipher_get_algo_keylen (int algo)
    gcry_cipher_algo_info because it allows for proper type
    checking.  */
 size_t
-gcry_cipher_get_algo_blklen (int algo) 
+gcry_cipher_get_algo_blklen (int algo)
 {
   size_t n;
 
@@ -2156,7 +2206,7 @@ _gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report)
     {
       ec = GPG_ERR_CIPHER_ALGO;
       if (report)
-        report ("cipher", algo, "module", 
+        report ("cipher", algo, "module",
                 module && !(module->flags & FLAG_MODULE_DISABLED)?
                 "no selftest available" :
                 module? "algorithm disabled" : "algorithm not found");