*** empty log message ***
[libgcrypt.git] / cipher / cipher.c
index 1f24c6b..95c4b70 100644 (file)
 #include "util.h"
 #include "errors.h"
 #include "cipher.h"
+#include "des.h"
 #include "blowfish.h"
 #include "cast5.h"
+#include "dynload.h"
 
-#define STD_BLOCKSIZE 8
 
-#if BLOWFISH_BLOCKSIZE != STD_BLOCKSIZE
-  #error Invalid BLOWFISH blocksize
-#elif CAST5_BLOCKSIZE != STD_BLOCKSIZE
-  #error Invalid CAST blocksize
-#endif
-
-
-static struct { const char *name; int algo;} cipher_names[] = {
-    { "IDEA",        CIPHER_ALGO_IDEA        },
-    { "3DES",        CIPHER_ALGO_3DES        },
-    { "CAST",        CIPHER_ALGO_CAST        },
-    { "BLOWFISH128", CIPHER_ALGO_BLOWFISH128 },
-    { "ROT_N",       CIPHER_ALGO_ROT_N       },
-    { "SAFER_SK128", CIPHER_ALGO_SAFER_SK128 },
-    { "DES_SK",      CIPHER_ALGO_DES_SK      },
-    { "BLOWFISH",    CIPHER_ALGO_BLOWFISH    },
-    {NULL} };
+#define MAX_BLOCKSIZE 16
+#define TABLE_SIZE 10
 
+struct cipher_table_s {
+    const char *name;
+    int algo;
+    size_t blocksize;
+    size_t keylen;
+    size_t contextsize; /* allocate this amount of context */
+    int  (*setkey)( void *c, byte *key, unsigned keylen );
+    void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
+    void (*decrypt)( void *c, byte *outbuf, byte *inbuf );
+};
 
-/* Hmmm, no way for a void arg in function pointer? */
-#define FNCCAST_SETKEY(f)  (void(*)(void*, byte*, unsigned))(f)
-#define FNCCAST_CRYPT(f)   (void(*)(void*, byte*, byte*))(f)
+static struct cipher_table_s cipher_table[TABLE_SIZE];
 
 
 struct cipher_handle_s {
     int  algo;
     int  mode;
-    byte iv[STD_BLOCKSIZE];    /* (this should be ulong aligned) */
-    byte lastiv[STD_BLOCKSIZE];
+    size_t blocksize;
+    byte iv[MAX_BLOCKSIZE];    /* (this should be ulong aligned) */
+    byte lastiv[MAX_BLOCKSIZE];
     int  unused;  /* in IV */
-    void (*setkey)( void *c, byte *key, unsigned keylen );
+    int  (*setkey)( void *c, byte *key, unsigned keylen );
     void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
     void (*decrypt)( void *c, byte *outbuf, byte *inbuf );
-    void (*sync_cfb)( void *c );
-    union {
-       int              context;
-       BLOWFISH_context blowfish;
-       CAST5_context cast5;
-    } c;
+    byte context[1];
 };
 
 
+static int
+dummy_setkey( void *c, byte *key, unsigned keylen ) { return 0; }
+static void
+dummy_encrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); }
+static void
+dummy_decrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); }
+
+
+
+/****************
+ * Put the static entries into the table.
+ */
+static void
+setup_cipher_table()
+{
+
+    int i;
+
+    i = 0;
+    cipher_table[i].algo = CIPHER_ALGO_BLOWFISH;
+    cipher_table[i].name = blowfish_get_info( cipher_table[i].algo,
+                                        &cipher_table[i].keylen,
+                                        &cipher_table[i].blocksize,
+                                        &cipher_table[i].contextsize,
+                                        &cipher_table[i].setkey,
+                                        &cipher_table[i].encrypt,
+                                        &cipher_table[i].decrypt     );
+    if( !cipher_table[i].name )
+       BUG();
+    i++;
+    cipher_table[i].algo = CIPHER_ALGO_CAST5;
+    cipher_table[i].name = cast5_get_info( cipher_table[i].algo,
+                                        &cipher_table[i].keylen,
+                                        &cipher_table[i].blocksize,
+                                        &cipher_table[i].contextsize,
+                                        &cipher_table[i].setkey,
+                                        &cipher_table[i].encrypt,
+                                        &cipher_table[i].decrypt     );
+    if( !cipher_table[i].name )
+       BUG();
+    i++;
+    cipher_table[i].algo = CIPHER_ALGO_3DES;
+    cipher_table[i].name = des_get_info( cipher_table[i].algo,
+                                        &cipher_table[i].keylen,
+                                        &cipher_table[i].blocksize,
+                                        &cipher_table[i].contextsize,
+                                        &cipher_table[i].setkey,
+                                        &cipher_table[i].encrypt,
+                                        &cipher_table[i].decrypt     );
+    if( !cipher_table[i].name )
+       BUG();
+    i++;
+    cipher_table[i].algo = CIPHER_ALGO_BLOWFISH160;
+    cipher_table[i].name = blowfish_get_info( cipher_table[i].algo,
+                                        &cipher_table[i].keylen,
+                                        &cipher_table[i].blocksize,
+                                        &cipher_table[i].contextsize,
+                                        &cipher_table[i].setkey,
+                                        &cipher_table[i].encrypt,
+                                        &cipher_table[i].decrypt     );
+    if( !cipher_table[i].name )
+       BUG();
+    i++;
+    cipher_table[i].algo = CIPHER_ALGO_DUMMY;
+    cipher_table[i].name = "DUMMY";
+    cipher_table[i].blocksize = 8;
+    cipher_table[i].keylen = 128;
+    cipher_table[i].contextsize = 0;
+    cipher_table[i].setkey = dummy_setkey;
+    cipher_table[i].encrypt = dummy_encrypt_block;
+    cipher_table[i].decrypt = dummy_decrypt_block;
+    i++;
+
+    for( ; i < TABLE_SIZE; i++ )
+       cipher_table[i].name = NULL;
+}
+
+
+/****************
+ * Try to load all modules and return true if new modules are available
+ */
+static int
+load_cipher_modules()
+{
+    static int done = 0;
+    static int initialized = 0;
+    void *context = NULL;
+    struct cipher_table_s *ct;
+    int ct_idx;
+    int i;
+    const char *name;
+    int any = 0;
+
+    if( !initialized ) {
+       setup_cipher_table(); /* load static modules on the first call */
+       initialized = 1;
+       return 1;
+    }
+
+    if( done )
+       return 0;
+    done = 1;
+
+    for(ct_idx=0, ct = cipher_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
+       if( !ct->name )
+           break;
+    }
+    if( ct_idx >= TABLE_SIZE-1 )
+       BUG(); /* table already full */
+    /* now load all extensions */
+    while( (name = enum_gnupgext_ciphers( &context, &ct->algo,
+                               &ct->keylen, &ct->blocksize, &ct->contextsize,
+                               &ct->setkey, &ct->encrypt, &ct->decrypt)) ) {
+       if( ct->blocksize != 8 && ct->blocksize != 16 ) {
+           log_info("skipping cipher %d: unsupported blocksize\n", ct->algo);
+           continue;
+       }
+       for(i=0; cipher_table[i].name; i++ )
+           if( cipher_table[i].algo == ct->algo )
+               break;
+       if( cipher_table[i].name ) {
+           log_info("skipping cipher %d: already loaded\n", ct->algo );
+           continue;
+       }
+       /* put it into the table */
+       if( g10_opt_verbose > 1 )
+           log_info("loaded cipher %d (%s)\n", ct->algo, name);
+       ct->name = name;
+       ct_idx++;
+       ct++;
+       any = 1;
+       /* check whether there are more available table slots */
+       if( ct_idx >= TABLE_SIZE-1 ) {
+           log_info("cipher table full; ignoring other extensions\n");
+           break;
+       }
+    }
+    enum_gnupgext_ciphers( &context, NULL, NULL, NULL, NULL,
+                                          NULL, NULL, NULL );
+    return any;
+}
+
+
+
+
+
+
+
 /****************
  * Map a string to the cipher algo
  */
@@ -85,9 +223,11 @@ string_to_cipher_algo( const char *string )
     int i;
     const char *s;
 
-    for(i=0; (s=cipher_names[i].name); i++ )
-       if( !stricmp( s, string ) )
-           return cipher_names[i].algo;
+    do {
+       for(i=0; (s=cipher_table[i].name); i++ )
+           if( !stricmp( s, string ) )
+               return cipher_table[i].algo;
+    } while( load_cipher_modules() );
     return 0;
 }
 
@@ -99,9 +239,11 @@ cipher_algo_to_string( int algo )
 {
     int i;
 
-    for(i=0; cipher_names[i].name; i++ )
-       if( cipher_names[i].algo == algo )
-           return cipher_names[i].name;
+    do {
+       for(i=0; cipher_table[i].name; i++ )
+           if( cipher_table[i].algo == algo )
+               return cipher_table[i].name;
+    } while( load_cipher_modules() );
     return NULL;
 }
 
@@ -111,14 +253,55 @@ cipher_algo_to_string( int algo )
 int
 check_cipher_algo( int algo )
 {
-    switch( algo ) {
-      case CIPHER_ALGO_BLOWFISH128:
-      case CIPHER_ALGO_BLOWFISH:
-      case CIPHER_ALGO_CAST:
-       return 0;
-      default:
-       return G10ERR_CIPHER_ALGO;
-    }
+    int i;
+
+    do {
+       for(i=0; cipher_table[i].name; i++ )
+          if( cipher_table[i].algo == algo )
+              return 0; /* okay */
+    } while( load_cipher_modules() );
+    return G10ERR_CIPHER_ALGO;
+}
+
+
+unsigned
+cipher_get_keylen( int algo )
+{
+    int i;
+    unsigned len = 0;
+
+    do {
+       for(i=0; cipher_table[i].name; i++ ) {
+           if( cipher_table[i].algo == algo ) {
+               len = cipher_table[i].keylen;
+               if( !len )
+                   log_bug("cipher %d w/o key length\n", algo );
+               return len;
+           }
+       }
+    } while( load_cipher_modules() );
+    log_bug("cipher %d not found\n", algo );
+    return 0;
+}
+
+unsigned
+cipher_get_blocksize( int algo )
+{
+    int i;
+    unsigned len = 0;
+
+    do {
+       for(i=0; cipher_table[i].name; i++ ) {
+           if( cipher_table[i].algo == algo ) {
+               len = cipher_table[i].blocksize;
+               if( !len )
+                   log_bug("cipher %d w/o blocksize\n", algo );
+               return len;
+           }
+       }
+    } while( load_cipher_modules() );
+    log_bug("cipher %d not found\n", algo );
+    return 0;
 }
 
 
@@ -130,37 +313,39 @@ CIPHER_HANDLE
 cipher_open( int algo, int mode, int secure )
 {
     CIPHER_HANDLE hd;
+    int i;
 
     fast_random_poll();
-    /* performance hint:
-     * It is possible to allocate less memory depending on the cipher */
-    hd = secure ? m_alloc_secure_clear( sizeof *hd )
-               : m_alloc_clear( sizeof *hd );
+    do {
+       for(i=0; cipher_table[i].name; i++ )
+           if( cipher_table[i].algo == algo )
+               break;
+    } while( !cipher_table[i].name && load_cipher_modules() );
+    if( !cipher_table[i].name ) {
+       log_fatal("cipher_open: algorithm %d not available\n", algo );
+       return NULL;
+    }
+
+    /* ? perform selftest here and mark this with a flag in cipher_table ? */
+
+    hd = secure ? m_alloc_secure_clear( sizeof *hd
+                                       + cipher_table[i].contextsize )
+               : m_alloc_clear( sizeof *hd + cipher_table[i].contextsize );
     hd->algo = algo;
-    if( mode == CIPHER_MODE_AUTO_CFB ) {
-       if( algo == CIPHER_ALGO_CAST )
-           hd->mode = CIPHER_MODE_PHILS_CFB;
-       else
+    hd->blocksize = cipher_table[i].blocksize;
+    hd->setkey = cipher_table[i].setkey;
+    hd->encrypt = cipher_table[i].encrypt;
+    hd->decrypt = cipher_table[i].decrypt;
+    if( algo == CIPHER_ALGO_DUMMY )
+       hd->mode = CIPHER_MODE_DUMMY;
+    else if( mode == CIPHER_MODE_AUTO_CFB ) {
+       if( algo == CIPHER_ALGO_BLOWFISH160 || algo >= 100 )
            hd->mode = CIPHER_MODE_CFB;
+       else
+           hd->mode = CIPHER_MODE_PHILS_CFB;
     }
     else
        hd->mode = mode;
-    switch( algo )  {
-      case CIPHER_ALGO_BLOWFISH:
-      case CIPHER_ALGO_BLOWFISH128:
-       hd->setkey  = FNCCAST_SETKEY(blowfish_setkey);
-       hd->encrypt = FNCCAST_CRYPT(blowfish_encrypt_block);
-       hd->decrypt = FNCCAST_CRYPT(blowfish_decrypt_block);
-       break;
-
-      case CIPHER_ALGO_CAST:
-       hd->setkey  = FNCCAST_SETKEY(cast5_setkey);
-       hd->encrypt = FNCCAST_CRYPT(cast5_encrypt_block);
-       hd->decrypt = FNCCAST_CRYPT(cast5_decrypt_block);
-       break;
-
-      default: log_fatal("cipher_open: invalid algo %d\n", algo );
-    }
 
     return hd;
 }
@@ -173,20 +358,21 @@ cipher_close( CIPHER_HANDLE c )
 }
 
 
-void
+int
 cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen )
 {
-    (*c->setkey)( &c->c.context, key, keylen );
+    return (*c->setkey)( &c->context, key, keylen );
 }
 
 
+
 void
 cipher_setiv( CIPHER_HANDLE c, const byte *iv )
 {
     if( iv )
-       memcpy( c->iv, iv, STD_BLOCKSIZE );
+       memcpy( c->iv, iv, c->blocksize );
     else
-       memset( c->iv, 0, STD_BLOCKSIZE );
+       memset( c->iv, 0, c->blocksize );
     c->unused = 0;
 }
 
@@ -198,9 +384,9 @@ do_ecb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
     unsigned n;
 
     for(n=0; n < nblocks; n++ ) {
-       (*c->encrypt)( &c->c.context, outbuf, inbuf );
-       inbuf  += CAST5_BLOCKSIZE;;
-       outbuf += CAST5_BLOCKSIZE;
+       (*c->encrypt)( &c->context, outbuf, inbuf );
+       inbuf  += c->blocksize;
+       outbuf += c->blocksize;
     }
 }
 
@@ -210,9 +396,9 @@ do_ecb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
     unsigned n;
 
     for(n=0; n < nblocks; n++ ) {
-       (*c->decrypt)( &c->c.context, outbuf, inbuf );
-       inbuf  += CAST5_BLOCKSIZE;;
-       outbuf += CAST5_BLOCKSIZE;
+       (*c->decrypt)( &c->context, outbuf, inbuf );
+       inbuf  += c->blocksize;
+       outbuf += c->blocksize;
     }
 }
 
@@ -221,11 +407,12 @@ static void
 do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
 {
     byte *ivp;
+    size_t blocksize = c->blocksize;
 
     if( nbytes <= c->unused ) {
        /* short enough to be encoded by the remaining XOR mask */
        /* XOR the input with the IV and store input into IV */
-       for(ivp=c->iv+STD_BLOCKSIZE - c->unused; nbytes; nbytes--, c->unused-- )
+       for(ivp=c->iv+c->blocksize - c->unused; nbytes; nbytes--, c->unused-- )
            *outbuf++ = (*ivp++ ^= *inbuf++);
        return;
     }
@@ -233,26 +420,26 @@ do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
     if( c->unused ) {
        /* XOR the input with the IV and store input into IV */
        nbytes -= c->unused;
-       for(ivp=c->iv+STD_BLOCKSIZE - c->unused; c->unused; c->unused-- )
+       for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- )
            *outbuf++ = (*ivp++ ^= *inbuf++);
     }
 
     /* now we can process complete blocks */
-    while( nbytes >= STD_BLOCKSIZE ) {
+    while( nbytes >= blocksize ) {
        int i;
        /* encrypt the IV (and save the current one) */
-       memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
-       (*c->encrypt)( &c->c.context, c->iv, c->iv );
+       memcpy( c->lastiv, c->iv, blocksize );
+       (*c->encrypt)( &c->context, c->iv, c->iv );
        /* XOR the input with the IV and store input into IV */
-       for(ivp=c->iv,i=0; i < STD_BLOCKSIZE; i++ )
+       for(ivp=c->iv,i=0; i < blocksize; i++ )
            *outbuf++ = (*ivp++ ^= *inbuf++);
-       nbytes -= STD_BLOCKSIZE;
+       nbytes -= blocksize;
     }
     if( nbytes ) { /* process the remaining bytes */
        /* encrypt the IV (and save the current one) */
-       memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
-       (*c->encrypt)( &c->c.context, c->iv, c->iv );
-       c->unused = STD_BLOCKSIZE;
+       memcpy( c->lastiv, c->iv, blocksize );
+       (*c->encrypt)( &c->context, c->iv, c->iv );
+       c->unused = blocksize;
        /* and apply the xor */
        c->unused -= nbytes;
        for(ivp=c->iv; nbytes; nbytes-- )
@@ -260,17 +447,17 @@ do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
     }
 }
 
-
 static void
 do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
 {
     byte *ivp;
     ulong temp;
+    size_t blocksize = c->blocksize;
 
     if( nbytes <= c->unused ) {
        /* short enough to be encoded by the remaining XOR mask */
        /* XOR the input with the IV and store input into IV */
-       for(ivp=c->iv+STD_BLOCKSIZE - c->unused; nbytes; nbytes--,c->unused--){
+       for(ivp=c->iv+blocksize - c->unused; nbytes; nbytes--,c->unused--){
            temp = *inbuf++;
            *outbuf++ = *ivp ^ temp;
            *ivp++ = temp;
@@ -281,7 +468,7 @@ do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
     if( c->unused ) {
        /* XOR the input with the IV and store input into IV */
        nbytes -= c->unused;
-       for(ivp=c->iv+STD_BLOCKSIZE - c->unused; c->unused; c->unused-- ) {
+       for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) {
            temp = *inbuf++;
            *outbuf++ = *ivp ^ temp;
            *ivp++ = temp;
@@ -289,68 +476,24 @@ do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
     }
 
     /* now we can process complete blocks */
-  #ifdef BIG_ENDIAN_HOST
-    /* This does only make sense for big endian hosts, due to ... ivp = temp*/
-    if( !((ulong)inbuf % SIZEOF_UNSIGNED_LONG) ) {
-       while( nbytes >= STD_BLOCKSIZE ) {
-           /* encrypt the IV (and save the current one) */
-           memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
-           (*c->encrypt)( &c->c.context, c->iv, c->iv );
-           ivp = c->iv;
-           /* XOR the input with the IV and store input into IV */
-         #if SIZEOF_UNSIGNED_LONG == STD_BLOCKSIZE
-           temp = *(ulong*)inbuf;
-           *(ulong*)outbuf = *(ulong*)c->iv ^ temp;
-           *(ulong*)ivp    = temp;
-         #elif (2*SIZEOF_UNSIGNED_LONG) == STD_BLOCKSIZE
-           temp = ((ulong*)inbuf)[0];
-           ((ulong*)outbuf)[0] = ((ulong*)c->iv)[0] ^ temp;
-           ((ulong*)ivp)[0] = temp;
-           temp = ((ulong*)inbuf)[1];
-           ((ulong*)outbuf)[1] = ((ulong*)c->iv)[1] ^ temp;
-           ((ulong*)ivp)[1] = temp;
-         #elif (4*SIZEOF_UNSIGNED_LONG) == STD_BLOCKSIZE
-           temp = ((ulong*)inbuf)[0];
-           ((ulong*)outbuf)[0] = ((ulong*)c->iv)[0] ^ temp;
-           ((ulong*)ivp)[0] = temp;
-           temp = ((ulong*)inbuf)[1];
-           ((ulong*)outbuf)[1] = ((ulong*)c->iv)[1] ^ temp;
-           ((ulong*)ivp)[1] = temp;
-           temp = ((ulong*)inbuf)[2];
-           ((ulong*)outbuf)[2] = ((ulong*)c->iv)[2] ^ temp;
-           ((ulong*)ivp)[2] = temp;
-           temp = ((ulong*)inbuf)[3];
-           ((ulong*)outbuf)[3] = ((ulong*)c->iv)[3] ^ temp;
-           ((ulong*)ivp)[3] = temp;
-         #else
-           #error Please disable the align test.
-         #endif
-           nbytes -= STD_BLOCKSIZE;
-       }
-    }
-    else { /* non aligned version */
-  #endif /* BIG_ENDIAN_HOST */
-       while( nbytes >= STD_BLOCKSIZE ) {
-           int i;
-           /* encrypt the IV (and save the current one) */
-           memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
-           (*c->encrypt)( &c->c.context, c->iv, c->iv );
-           /* XOR the input with the IV and store input into IV */
-           for(ivp=c->iv,i=0; i < STD_BLOCKSIZE; i++ ) {
-               temp = *inbuf++;
-               *outbuf++ = *ivp ^ temp;
-               *ivp++ = temp;
-           }
-           nbytes -= STD_BLOCKSIZE;
+    while( nbytes >= blocksize ) {
+       int i;
+       /* encrypt the IV (and save the current one) */
+       memcpy( c->lastiv, c->iv, blocksize );
+       (*c->encrypt)( &c->context, c->iv, c->iv );
+       /* XOR the input with the IV and store input into IV */
+       for(ivp=c->iv,i=0; i < blocksize; i++ ) {
+           temp = *inbuf++;
+           *outbuf++ = *ivp ^ temp;
+           *ivp++ = temp;
        }
-   #ifdef BIG_ENDIAN_HOST
+       nbytes -= blocksize;
     }
-   #endif
     if( nbytes ) { /* process the remaining bytes */
        /* encrypt the IV (and save the current one) */
-       memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
-       (*c->encrypt)( &c->c.context, c->iv, c->iv );
-       c->unused = STD_BLOCKSIZE;
+       memcpy( c->lastiv, c->iv, blocksize );
+       (*c->encrypt)( &c->context, c->iv, c->iv );
+       c->unused = blocksize;
        /* and apply the xor */
        c->unused -= nbytes;
        for(ivp=c->iv; nbytes; nbytes-- ) {
@@ -379,6 +522,10 @@ cipher_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
       case CIPHER_MODE_PHILS_CFB:
        do_cfb_encrypt(c, outbuf, inbuf, nbytes );
        break;
+      case CIPHER_MODE_DUMMY:
+       if( inbuf != outbuf )
+           memmove( outbuf, inbuf, nbytes );
+       break;
       default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
     }
 }
@@ -401,6 +548,10 @@ cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
       case CIPHER_MODE_PHILS_CFB:
        do_cfb_decrypt(c, outbuf, inbuf, nbytes );
        break;
+      case CIPHER_MODE_DUMMY:
+       if( inbuf != outbuf )
+           memmove( outbuf, inbuf, nbytes );
+       break;
       default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode );
     }
 }
@@ -408,15 +559,15 @@ cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
 
 
 /****************
- * Used for PGP's somewhat strange CFB mode. Does only work if
+ * Used for PGP's somewhat strange CFB mode. Only works if
  * the handle is in PHILS_CFB mode
  */
 void
 cipher_sync( CIPHER_HANDLE c )
 {
     if( c->mode == CIPHER_MODE_PHILS_CFB && c->unused ) {
-       memmove(c->iv + c->unused, c->iv, CAST5_BLOCKSIZE - c->unused );
-       memcpy(c->iv, c->lastiv + CAST5_BLOCKSIZE - c->unused, c->unused);
+       memmove(c->iv + c->unused, c->iv, c->blocksize - c->unused );
+       memcpy(c->iv, c->lastiv + c->blocksize - c->unused, c->unused);
        c->unused = 0;
     }
 }