See ChangeLog: Sun Jan 17 11:04:33 CET 1999 Werner Koch
[gnupg.git] / cipher / blowfish.c
index 3ed2ed8..3bbc038 100644 (file)
@@ -5,14 +5,14 @@
  *   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 GnuPG.
  *
- * GNUPG 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.
  *
- * GNUPG 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.
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-#include "util.h"
 #include "types.h"
+#include "errors.h"
 #include "blowfish.h"
 
+
+
 #define CIPHER_ALGO_BLOWFISH    4  /* blowfish 128 bit key */
 #define CIPHER_ALGO_BLOWFISH160 42  /* blowfish 160 bit key (not in OpenPGP)*/
 
-#define FNCCAST_SETKEY(f)  (void(*)(void*, byte*, unsigned))(f)
+#define FNCCAST_SETKEY(f)  (int(*)(void*, byte*, unsigned))(f)
 #define FNCCAST_CRYPT(f)   (void(*)(void*, byte*, byte*))(f)
 
 #define BLOWFISH_BLOCKSIZE 8
@@ -55,7 +57,7 @@ typedef struct {
     u32 p[BLOWFISH_ROUNDS+2];
 } BLOWFISH_context;
 
-static void bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen );
+static int  bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen );
 static void encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf );
 static void decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf );
 
@@ -451,7 +453,7 @@ decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
 }
 
 
-static void
+static const char*
 selftest()
 {
     BLOWFISH_context c;
@@ -464,33 +466,39 @@ selftest()
     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 ) )
-       log_error("wrong blowfish encryption (3)\n");
+       return "Blowfish selftest failed (3).";
     decrypt_block( &c, buffer, buffer );
     if( memcmp( buffer, plain3, 8 ) )
-       log_bug("blowfish failed (3)\n");
+       return "Blowfish selftest failed (4).";
+    return NULL;
 }
 
 
 
-static void
+static int
 bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
 {
     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];
@@ -543,6 +551,19 @@ bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
        c->s3[i]   = datal;
        c->s3[i+1] = datar;
     }
+
+
+    /* 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;
+       }
+    }
+
+    return 0;
 }
 
 
@@ -555,7 +576,7 @@ bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
 const char *
 blowfish_get_info( int algo, size_t *keylen,
                   size_t *blocksize, size_t *contextsize,
-                  void (**r_setkey)( void *c, byte *key, unsigned keylen ),
+                  int  (**r_setkey)( void *c, byte *key, unsigned keylen ),
                   void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ),
                   void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf )
                 )