* getkey.c (parse_auto_key_locate): Fix dupe-removal code.
[gnupg.git] / cipher / blowfish.c
index 72d617a..1a1ce56 100644 (file)
@@ -1,31 +1,33 @@
 /* blowfish.c  -  Blowfish encryption
- *     Copyright (c) 1997 by Werner Koch (dd9jn)
+ *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  *
- * For a description of the algorithm, see:
- *   Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
- *   ISBN 0-471-11709-9. Pages 336 ff.
+ * This file is part of GnuPG.
  *
- * This file is part of G10.
- *
- * G10 is free software; you can redistribute it and/or modify
+ * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * G10 is distributed in the hope that it will be useful,
+ * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * For a description of the algorithm, see:
+ *   Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
+ *   ISBN 0-471-11709-9. Pages 336 ff.
  */
 
 /* Test values:
  * key   "abcdefghijklmnopqrstuvwxyz";
  * plain  "BLOWFISH"
  * cipher 32 4E D0 FE F4 13 A2 03
+ *
  */
 
 #include <config.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-#include "util.h"
 #include "types.h"
-#include "blowfish.h"
+#include "util.h"
+#include "errors.h"
+#include "algorithms.h"
+
+
+
+#define CIPHER_ALGO_BLOWFISH    4  /* blowfish 128 bit key */
+
+#define BLOWFISH_BLOCKSIZE 8
+#define BLOWFISH_ROUNDS 16
+
+typedef struct {
+    u32 s0[256];
+    u32 s1[256];
+    u32 s2[256];
+    u32 s3[256];
+    u32 p[BLOWFISH_ROUNDS+2];
+} BLOWFISH_context;
+
+static int bf_setkey( void *c, const byte *key, unsigned keylen );
 
 /* precomputed S boxes */
 static const u32 ks0[256] = {
@@ -225,69 +245,161 @@ static const u32 ps[BLOWFISH_ROUNDS+2] = {
 
 
 
-
-
-static u32
+#if BLOWFISH_ROUNDS != 16
+static inline u32
 function_F( BLOWFISH_context *bc, u32 x )
 {
     u16 a, b, c, d;
 
-  #ifdef BIG_ENDIAN_HOST
+#ifdef BIG_ENDIAN_HOST
     a = ((byte*)&x)[0];
     b = ((byte*)&x)[1];
     c = ((byte*)&x)[2];
     d = ((byte*)&x)[3];
-  #else
+#else
     a = ((byte*)&x)[3];
     b = ((byte*)&x)[2];
     c = ((byte*)&x)[1];
     d = ((byte*)&x)[0];
-  #endif
+#endif
 
     return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d];
 }
+#endif
+
+#ifdef BIG_ENDIAN_HOST
+#define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]])       \
+                  ^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] )
+#else
+#define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]])       \
+                  ^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] )
+#endif
+#define R(l,r,i)  do { l ^= p[i]; r ^= F(l); } while(0)
+
+static void
+burn_stack (int bytes)
+{
+    char buf[64];
+    
+    wipememory(buf,sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
 
 
 static void
-encrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
+do_encrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
 {
-    u32 xl, xr, temp;
+#if BLOWFISH_ROUNDS == 16
+    u32 xl, xr, *s0, *s1, *s2, *s3, *p;
+
+    xl = *ret_xl;
+    xr = *ret_xr;
+    p = bc->p;
+    s0 = bc->s0;
+    s1 = bc->s1;
+    s2 = bc->s2;
+    s3 = bc->s3;
+
+    R( xl, xr, 0);
+    R( xr, xl, 1);
+    R( xl, xr, 2);
+    R( xr, xl, 3);
+    R( xl, xr, 4);
+    R( xr, xl, 5);
+    R( xl, xr, 6);
+    R( xr, xl, 7);
+    R( xl, xr, 8);
+    R( xr, xl, 9);
+    R( xl, xr, 10);
+    R( xr, xl, 11);
+    R( xl, xr, 12);
+    R( xr, xl, 13);
+    R( xl, xr, 14);
+    R( xr, xl, 15);
+
+    xl ^= p[BLOWFISH_ROUNDS];
+    xr ^= p[BLOWFISH_ROUNDS+1];
+
+    *ret_xl = xr;
+    *ret_xr = xl;
+
+#else
+    u32 xl, xr, temp, *p;
     int i;
 
     xl = *ret_xl;
     xr = *ret_xr;
+    p = bc->p;
 
     for(i=0; i < BLOWFISH_ROUNDS; i++ ) {
-       xl ^= bc->p[i];
+       xl ^= p[i];
        xr ^= function_F(bc, xl);
        temp = xl;
        xl = xr;
        xr = temp;
     }
-
     temp = xl;
     xl = xr;
     xr = temp;
 
-    xr ^= bc->p[BLOWFISH_ROUNDS];
-    xl ^= bc->p[BLOWFISH_ROUNDS+1];
+    xr ^= p[BLOWFISH_ROUNDS];
+    xl ^= p[BLOWFISH_ROUNDS+1];
 
     *ret_xl = xl;
     *ret_xr = xr;
+#endif
 }
 
 
 static void
 decrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
 {
-    u32 xl, xr, temp;
+#if BLOWFISH_ROUNDS == 16
+    u32 xl, xr, *s0, *s1, *s2, *s3, *p;
+
+    xl = *ret_xl;
+    xr = *ret_xr;
+    p = bc->p;
+    s0 = bc->s0;
+    s1 = bc->s1;
+    s2 = bc->s2;
+    s3 = bc->s3;
+
+    R( xl, xr, 17);
+    R( xr, xl, 16);
+    R( xl, xr, 15);
+    R( xr, xl, 14);
+    R( xl, xr, 13);
+    R( xr, xl, 12);
+    R( xl, xr, 11);
+    R( xr, xl, 10);
+    R( xl, xr, 9);
+    R( xr, xl, 8);
+    R( xl, xr, 7);
+    R( xr, xl, 6);
+    R( xl, xr, 5);
+    R( xr, xl, 4);
+    R( xl, xr, 3);
+    R( xr, xl, 2);
+
+    xl ^= p[1];
+    xr ^= p[0];
+
+    *ret_xl = xr;
+    *ret_xr = xl;
+
+#else
+    u32 xl, xr, temp, *p;
     int i;
 
     xl = *ret_xl;
     xr = *ret_xr;
+    p = bc->p;
 
     for(i=BLOWFISH_ROUNDS+1; i > 1; i-- ) {
-       xl ^= bc->p[i];
+       xl ^= p[i];
        xr ^= function_F(bc, xl);
        temp = xl;
        xl = xr;
@@ -298,116 +410,113 @@ decrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
     xl = xr;
     xr = temp;
 
-    xr ^= bc->p[1];
-    xl ^= bc->p[0];
+    xr ^= p[1];
+    xl ^= p[0];
 
     *ret_xl = xl;
     *ret_xr = xr;
+#endif
 }
 
+#undef F
+#undef R
+
 static void
-encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+do_encrypt_block( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf )
 {
     u32 d1, d2;
 
-  #ifdef BIG_ENDIAN_HOST
-    d1 = ((u32*)inbuf)[0]; /* fixme: this may not be aligned */
-    d2 = ((u32*)inbuf)[1];
-  #else
-    ((byte*)&d1)[3] = inbuf[0];
-    ((byte*)&d1)[2] = inbuf[1];
-    ((byte*)&d1)[1] = inbuf[2];
-    ((byte*)&d1)[0] = inbuf[3];
-    ((byte*)&d2)[3] = inbuf[4];
-    ((byte*)&d2)[2] = inbuf[5];
-    ((byte*)&d2)[1] = inbuf[6];
-    ((byte*)&d2)[0] = inbuf[7];
-  #endif
-
-    encrypt( bc, &d1, &d2 );
-
-  #ifdef BIG_ENDIAN_HOST
-    ((u32*)outbuf)[0] = d1;
-    ((u32*)outbuf)[1] = d2;
-  #else
-    outbuf[0] = ((byte*)&d1)[3];
-    outbuf[1] = ((byte*)&d1)[2];
-    outbuf[2] = ((byte*)&d1)[1];
-    outbuf[3] = ((byte*)&d1)[0];
-    outbuf[4] = ((byte*)&d2)[3];
-    outbuf[5] = ((byte*)&d2)[2];
-    outbuf[6] = ((byte*)&d2)[1];
-    outbuf[7] = ((byte*)&d2)[0];
-  #endif
+    d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
+    d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
+    do_encrypt( bc, &d1, &d2 );
+    outbuf[0] = (d1 >> 24) & 0xff;
+    outbuf[1] = (d1 >> 16) & 0xff;
+    outbuf[2] = (d1 >> 8) & 0xff;
+    outbuf[3] =  d1       & 0xff;
+    outbuf[4] = (d2 >> 24) & 0xff;
+    outbuf[5] = (d2 >> 16) & 0xff;
+    outbuf[6] = (d2 >> 8) & 0xff;
+    outbuf[7] =  d2       & 0xff;
 }
 
+static void
+encrypt_block( void *bc, byte *outbuf, const byte *inbuf )
+{
+    do_encrypt_block (bc, outbuf, inbuf);
+    burn_stack (64);
+}
 
 static void
-decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+do_decrypt_block( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf )
 {
     u32 d1, d2;
 
-  #ifdef BIG_ENDIAN_HOST
-    d1 = ((u32*)inbuf)[0]; /* fixme: this may not be aligned */
-    d2 = ((u32*)inbuf)[1];
-  #else
-    ((byte*)&d1)[3] = inbuf[0];
-    ((byte*)&d1)[2] = inbuf[1];
-    ((byte*)&d1)[1] = inbuf[2];
-    ((byte*)&d1)[0] = inbuf[3];
-    ((byte*)&d2)[3] = inbuf[4];
-    ((byte*)&d2)[2] = inbuf[5];
-    ((byte*)&d2)[1] = inbuf[6];
-    ((byte*)&d2)[0] = inbuf[7];
-  #endif
-
+    d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
+    d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
     decrypt( bc, &d1, &d2 );
+    outbuf[0] = (d1 >> 24) & 0xff;
+    outbuf[1] = (d1 >> 16) & 0xff;
+    outbuf[2] = (d1 >> 8) & 0xff;
+    outbuf[3] =  d1       & 0xff;
+    outbuf[4] = (d2 >> 24) & 0xff;
+    outbuf[5] = (d2 >> 16) & 0xff;
+    outbuf[6] = (d2 >> 8) & 0xff;
+    outbuf[7] =  d2       & 0xff;
+}
 
-  #ifdef BIG_ENDIAN_HOST
-    ((u32*)outbuf)[0] = d1;
-    ((u32*)outbuf)[1] = d2;
-  #else
-    outbuf[0] = ((byte*)&d1)[3];
-    outbuf[1] = ((byte*)&d1)[2];
-    outbuf[2] = ((byte*)&d1)[1];
-    outbuf[3] = ((byte*)&d1)[0];
-    outbuf[4] = ((byte*)&d2)[3];
-    outbuf[5] = ((byte*)&d2)[2];
-    outbuf[6] = ((byte*)&d2)[1];
-    outbuf[7] = ((byte*)&d2)[0];
-  #endif
+static void
+decrypt_block( void *bc, byte *outbuf, const byte *inbuf )
+{
+    do_decrypt_block (bc, outbuf, inbuf);
+    burn_stack (64);
 }
 
 
-static void
-selftest()
+static const char*
+selftest(void)
 {
     BLOWFISH_context c;
     byte plain[] = "BLOWFISH";
     byte buffer[8];
+    byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 };
+    byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 };
+    byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 };
 
-    blowfish_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 );
+    bf_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 );
     encrypt_block( &c, buffer, plain );
     if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) )
-       log_error("wrong blowfish encryption\n");
+       return "Blowfish selftest failed (1).";
     decrypt_block( &c, buffer, buffer );
     if( memcmp( buffer, plain, 8 ) )
-       log_bug("blowfish failed\n");
-}
+       return "Blowfish selftest failed (2).";
 
+    bf_setkey( &c, key3, 8 );
+    encrypt_block( &c, buffer, plain3 );
+    if( memcmp( buffer, cipher3, 8 ) )
+       return "Blowfish selftest failed (3).";
+    decrypt_block( &c, buffer, buffer );
+    if( memcmp( buffer, plain3, 8 ) )
+       return "Blowfish selftest failed (4).";
+    return NULL;
+}
 
 
-void
-blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
+static int
+do_bf_setkey( BLOWFISH_context *c, const byte *key, unsigned keylen )
 {
-    int i, j, k;
+    int i, j;
     u32 data, datal, datar;
     static int initialized;
+    static const char *selftest_failed;
 
     if( !initialized ) {
        initialized = 1;
-       selftest();
+       selftest_failed = selftest();
+       if( selftest_failed )
+           fprintf(stderr,"%s\n", selftest_failed );
     }
+    if( selftest_failed )
+       return G10ERR_SELFTEST_FAILED;
 
     for(i=0; i < BLOWFISH_ROUNDS+2; i++ )
        c->p[i] = ps[i];
@@ -419,191 +528,92 @@ blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
     }
 
     for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) {
-      #ifdef BIG_ENDIAN_HOST
+#ifdef BIG_ENDIAN_HOST
        ((byte*)&data)[0] = key[j];
        ((byte*)&data)[1] = key[(j+1)%keylen];
        ((byte*)&data)[2] = key[(j+2)%keylen];
        ((byte*)&data)[3] = key[(j+3)%keylen];
-      #else
+#else
        ((byte*)&data)[3] = key[j];
        ((byte*)&data)[2] = key[(j+1)%keylen];
        ((byte*)&data)[1] = key[(j+2)%keylen];
        ((byte*)&data)[0] = key[(j+3)%keylen];
-      #endif
+#endif
        c->p[i] ^= data;
        j = (j+4) % keylen;
     }
 
     datal = datar = 0;
     for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) {
-       encrypt( c, &datal, &datar );
+       do_encrypt( c, &datal, &datar );
        c->p[i]   = datal;
        c->p[i+1] = datar;
     }
     for(i=0; i < 256; i += 2 ) {
-       encrypt( c, &datal, &datar );
+       do_encrypt( c, &datal, &datar );
        c->s0[i]   = datal;
        c->s0[i+1] = datar;
     }
     for(i=0; i < 256; i += 2 ) {
-       encrypt( c, &datal, &datar );
+       do_encrypt( c, &datal, &datar );
        c->s1[i]   = datal;
        c->s1[i+1] = datar;
     }
     for(i=0; i < 256; i += 2 ) {
-       encrypt( c, &datal, &datar );
+       do_encrypt( c, &datal, &datar );
        c->s2[i]   = datal;
        c->s2[i+1] = datar;
     }
     for(i=0; i < 256; i += 2 ) {
-       encrypt( c, &datal, &datar );
+       do_encrypt( c, &datal, &datar );
        c->s3[i]   = datal;
        c->s3[i+1] = datar;
     }
-}
-
 
-void
-blowfish_setiv( BLOWFISH_context *c, byte *iv )
-{
-    if( iv )
-       memcpy( c->iv, iv, BLOWFISH_BLOCKSIZE );
-    else
-       memset( c->iv, 0, BLOWFISH_BLOCKSIZE );
-    c->count = 0;
-    encrypt_block( c, c->eniv, c->iv );
-}
-
-
-void
-blowfish_encode( BLOWFISH_context *c, byte *outbuf, byte *inbuf,
-                                                   unsigned nblocks )
-{
-    unsigned n;
 
-    for(n=0; n < nblocks; n++ ) {
-       encrypt_block( c, outbuf, inbuf );
-       inbuf  += BLOWFISH_BLOCKSIZE;;
-       outbuf += BLOWFISH_BLOCKSIZE;
+    /* Check for weak key.  A weak key is a key in which a value in */
+    /* the P-array (here c) occurs more than once per table.       */
+    for(i=0; i < 255; i++ ) {
+       for( j=i+1; j < 256; j++) {
+           if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) ||
+               (c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) )
+               return G10ERR_WEAK_KEY;
+       }
     }
-}
 
-void
-blowfish_decode( BLOWFISH_context *c, byte *outbuf, byte *inbuf,
-                                                   unsigned nblocks )
-{
-    unsigned n;
-
-    for(n=0; n < nblocks; n++ ) {
-       decrypt_block( c, outbuf, inbuf );
-       inbuf  += BLOWFISH_BLOCKSIZE;;
-       outbuf += BLOWFISH_BLOCKSIZE;
-    }
+    return 0;
 }
 
-
-
-/****************
- * FIXME: Make use of bigger chunks
- * (out may overlap with a or b)
- */
-static void
-xorblock( byte *out, byte *a, byte *b, unsigned count )
+static int
+bf_setkey( void *c, const byte *key, unsigned keylen )
 {
-    for( ; count ; count--, a++, b++ )
-       *out++ = *a ^ *b ;
+    int rc = do_bf_setkey (c, key, keylen);
+    burn_stack (64);
+    return rc;
 }
 
-
-
 /****************
- * Encode buffer in CFB mode. nbytes can be an arbitrary value.
+ * Return some information about the algorithm.  We need algo here to
+ * distinguish different flavors of the algorithm.
+ * Returns: A pointer to string describing the algorithm or NULL if
+ *         the ALGO is invalid.
  */
-void
-blowfish_encode_cfb( BLOWFISH_context *c, byte *outbuf,
-                                         byte *inbuf, unsigned nbytes)
-{
-    unsigned n;
-
-    if( c->count ) {  /* must make a full block first */
-       assert( c->count < BLOWFISH_BLOCKSIZE );
-       n = BLOWFISH_BLOCKSIZE - c->count;
-       if( n > nbytes )
-           n = nbytes;
-       xorblock( outbuf, c->eniv+c->count, inbuf, n);
-       memcpy( c->iv+c->count, outbuf, n);
-       c->count += n;
-       nbytes -= n;
-       inbuf += n;
-       outbuf += n;
-       assert( c->count <= BLOWFISH_BLOCKSIZE);
-       if( c->count == BLOWFISH_BLOCKSIZE ) {
-           encrypt_block( c, c->eniv, c->iv );
-           c->count = 0;
-       }
-       else
-           return;
-    }
-    assert(!c->count);
-    while( nbytes >= BLOWFISH_BLOCKSIZE ) {
-       xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
-       memcpy( c->iv, outbuf, BLOWFISH_BLOCKSIZE);
-       encrypt_block( c, c->eniv, c->iv );
-       nbytes -= BLOWFISH_BLOCKSIZE;
-       inbuf += BLOWFISH_BLOCKSIZE;
-       outbuf += BLOWFISH_BLOCKSIZE;
-    }
-
-    if( nbytes ) {
-       xorblock( outbuf, c->eniv, inbuf, nbytes );
-       memcpy( c->iv, outbuf, nbytes );
-       c->count = nbytes;
-    }
-
-}
-
-
-void
-blowfish_decode_cfb( BLOWFISH_context *c, byte *outbuf,
-                                         byte *inbuf, unsigned nbytes)
+const char *
+blowfish_get_info(int algo, size_t *keylen,
+                 size_t *blocksize, size_t *contextsize,
+                 int (**r_setkey)(void *c, const byte *key, unsigned keylen),
+                 void (**r_encrypt)(void *c, byte *outbuf, const byte *inbuf),
+                 void (**r_decrypt)( void *c, byte *outbuf, const byte *inbuf)
+                 )
 {
-    unsigned n;
-
-    if( c->count ) {  /* must make a full block first */
-       assert( c->count < BLOWFISH_BLOCKSIZE );
-       n = BLOWFISH_BLOCKSIZE - c->count;
-       if( n > nbytes )
-           n = nbytes;
-       memcpy( c->iv+c->count, inbuf, n);
-       xorblock( outbuf, c->eniv+c->count, inbuf, n);
-       c->count += n;
-       nbytes -= n;
-       inbuf += n;
-       outbuf += n;
-       assert( c->count <= BLOWFISH_BLOCKSIZE);
-       if( c->count == BLOWFISH_BLOCKSIZE ) {
-           encrypt_block( c, c->eniv, c->iv );
-           c->count = 0;
-       }
-       else
-           return;
-    }
-
-    assert(!c->count);
-    while( nbytes >= BLOWFISH_BLOCKSIZE ) {
-       memcpy( c->iv, inbuf, BLOWFISH_BLOCKSIZE);
-       xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
-       encrypt_block( c, c->eniv, c->iv );
-       nbytes -= BLOWFISH_BLOCKSIZE;
-       inbuf += BLOWFISH_BLOCKSIZE;
-       outbuf += BLOWFISH_BLOCKSIZE;
-    }
-
-    if( nbytes ) {
-       memcpy( c->iv, inbuf, nbytes );
-       xorblock( outbuf, c->eniv, inbuf, nbytes );
-       c->count = nbytes;
-    }
-
+    *keylen = 128;
+    *blocksize = BLOWFISH_BLOCKSIZE;
+    *contextsize = sizeof(BLOWFISH_context);
+    *r_setkey = bf_setkey;
+    *r_encrypt = encrypt_block;
+    *r_decrypt = decrypt_block;
+
+    if( algo == CIPHER_ALGO_BLOWFISH )
+       return "BLOWFISH";
+    return NULL;
 }
-