More portable blowfish macros.
authorUlf Möller <ulf@openssl.org>
Tue, 27 Apr 1999 21:17:18 +0000 (21:17 +0000)
committerUlf Möller <ulf@openssl.org>
Tue, 27 Apr 1999 21:17:18 +0000 (21:17 +0000)
Submitted by: Andy Polyakov <appro@fy.chalmers.se>

crypto/bf/bf_enc.c
crypto/bf/bf_locl.h
crypto/bf/blowfish.h
crypto/opensslconf.h.in

index f8a95e2..ee01834 100644 (file)
@@ -71,6 +71,7 @@ to modify the code.
 
 void BF_encrypt(BF_LONG *data, BF_KEY *key)
        {
+#ifndef BF_PTR2
        register BF_LONG l,r,*p,*s;
 
        p=key->P;
@@ -105,12 +106,48 @@ void BF_encrypt(BF_LONG *data, BF_KEY *key)
 
        data[1]=l&0xffffffffL;
        data[0]=r&0xffffffffL;
+#else
+       register BF_LONG l,r,t,*k;
+
+       l=data[0];
+       r=data[1];
+       k=(BF_LONG*)key;
+
+       l^=k[0];
+       BF_ENC(r,l,k, 1);
+       BF_ENC(l,r,k, 2);
+       BF_ENC(r,l,k, 3);
+       BF_ENC(l,r,k, 4);
+       BF_ENC(r,l,k, 5);
+       BF_ENC(l,r,k, 6);
+       BF_ENC(r,l,k, 7);
+       BF_ENC(l,r,k, 8);
+       BF_ENC(r,l,k, 9);
+       BF_ENC(l,r,k,10);
+       BF_ENC(r,l,k,11);
+       BF_ENC(l,r,k,12);
+       BF_ENC(r,l,k,13);
+       BF_ENC(l,r,k,14);
+       BF_ENC(r,l,k,15);
+       BF_ENC(l,r,k,16);
+#if BF_ROUNDS == 20
+       BF_ENC(r,l,k,17);
+       BF_ENC(l,r,k,18);
+       BF_ENC(r,l,k,19);
+       BF_ENC(l,r,k,20);
+#endif
+       r^=k[BF_ROUNDS+1];
+
+       data[1]=l&0xffffffffL;
+       data[0]=r&0xffffffffL;
+#endif
        }
 
 #ifndef BF_DEFAULT_OPTIONS
 
 void BF_decrypt(BF_LONG *data, BF_KEY *key)
        {
+#ifndef BF_PTR2
        register BF_LONG l,r,*p,*s;
 
        p=key->P;
@@ -145,6 +182,41 @@ void BF_decrypt(BF_LONG *data, BF_KEY *key)
 
        data[1]=l&0xffffffffL;
        data[0]=r&0xffffffffL;
+#else
+       register BF_LONG l,r,t,*k;
+
+       l=data[0];
+       r=data[1];
+       k=(BF_LONG *)key;
+
+       l^=k[BF_ROUNDS+1];
+#if BF_ROUNDS == 20
+       BF_ENC(r,l,k,20);
+       BF_ENC(l,r,k,19);
+       BF_ENC(r,l,k,18);
+       BF_ENC(l,r,k,17);
+#endif
+       BF_ENC(r,l,k,16);
+       BF_ENC(l,r,k,15);
+       BF_ENC(r,l,k,14);
+       BF_ENC(l,r,k,13);
+       BF_ENC(r,l,k,12);
+       BF_ENC(l,r,k,11);
+       BF_ENC(r,l,k,10);
+       BF_ENC(l,r,k, 9);
+       BF_ENC(r,l,k, 8);
+       BF_ENC(l,r,k, 7);
+       BF_ENC(r,l,k, 6);
+       BF_ENC(l,r,k, 5);
+       BF_ENC(r,l,k, 4);
+       BF_ENC(l,r,k, 3);
+       BF_ENC(r,l,k, 2);
+       BF_ENC(l,r,k, 1);
+       r^=k[0];
+
+       data[1]=l&0xffffffffL;
+       data[0]=r&0xffffffffL;
+#endif
        }
 
 void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
index 7936e6c..3ebb145 100644 (file)
 /* This is actually a big endian algorithm, the most significate byte
  * is used to lookup array 0 */
 
-#define BF_M   0x3fc
-#define BF_0   22L
-#define BF_1   14L
-#define BF_2    6L
-#define BF_3    2L /* left shift */
-
 #if defined(BF_PTR2)
 
-/* This is basically a special pentium verson */
-#define BF_ENC(LL,R,S,P) \
-       { \
-       BF_LONG t,u,v; \
-       u=R>>BF_0; \
-       v=R>>BF_1; \
-       u&=BF_M; \
-       v&=BF_M; \
-       t=  *(BF_LONG *)((unsigned char *)&(S[  0])+u); \
-       u=R>>BF_2; \
-       t+= *(BF_LONG *)((unsigned char *)&(S[256])+v); \
-       v=R<<BF_3; \
-       u&=BF_M; \
-       v&=BF_M; \
-       t^= *(BF_LONG *)((unsigned char *)&(S[512])+u); \
-       LL^=P; \
-       t+= *(BF_LONG *)((unsigned char *)&(S[768])+v); \
-       LL^=t; \
-       }
+/*
+ * This is basically a special Intel version. Point is that Intel
+ * doesn't have many registers, but offers a reach choice of addressing
+ * modes. So we spare some registers by directly traversing BF_KEY
+ * structure and hiring the most decorated addressing mode. The code
+ * generated by EGCS is *perfectly* competitive with assembler
+ * implementation!
+ */
+#define BF_ENC(LL,R,KEY,Pi) (\
+       LL^=KEY[Pi], \
+       t=  KEY[BF_ROUNDS+2 +   0 + ((R>>24)&0xFF)], \
+       t+= KEY[BF_ROUNDS+2 + 256 + ((R>>16)&0xFF)], \
+       t^= KEY[BF_ROUNDS+2 + 512 + ((R>>8 )&0xFF)], \
+       t+= KEY[BF_ROUNDS+2 + 768 + ((R    )&0xFF)], \
+       LL^=t \
+       )
 
 #elif defined(BF_PTR)
 
-/* This is normally very good */
+#ifndef BF_LONG_LOG2
+#define BF_LONG_LOG2  2       /* default to BF_LONG being 32 bits */
+#endif
+#define BF_M  (0xFF<<BF_LONG_LOG2)
+#define BF_0  (24-BF_LONG_LOG2)
+#define BF_1  (16-BF_LONG_LOG2)
+#define BF_2  ( 8-BF_LONG_LOG2)
+#define BF_3  BF_LONG_LOG2 /* left shift */
+
+/*
+ * This is normally very good on RISC platforms where normally you
+ * have to explicitely "multiplicate" array index by sizeof(BF_LONG)
+ * in order to caclulate the effective address. This implementation
+ * excuses CPU from this extra work. Power[PC] uses should have most
+ * fun as (R>>BF_i)&BF_M gets folded into a single instruction, namely
+ * rlwinm. So let'em double-check if their compiler does it.
+ */
 
-#define BF_ENC(LL,R,S,P) \
-       LL^=P; \
+#define BF_ENC(LL,R,S,P) \
+       LL^=P, \
        LL^= (((*(BF_LONG *)((unsigned char *)&(S[  0])+((R>>BF_0)&BF_M))+ \
                *(BF_LONG *)((unsigned char *)&(S[256])+((R>>BF_1)&BF_M)))^ \
                *(BF_LONG *)((unsigned char *)&(S[512])+((R>>BF_2)&BF_M)))+ \
-               *(BF_LONG *)((unsigned char *)&(S[768])+((R<<BF_3)&BF_M)));
+               *(BF_LONG *)((unsigned char *)&(S[768])+((R<<BF_3)&BF_M))) \
+       )
 #else
 
-/* This will always work, even on 64 bit machines and strangly enough,
- * on the Alpha it is faster than the pointer versions (both 32 and 64
- * versions of BF_LONG) */
+/*
+ * This is a *generic* version. Seem to perform best on platforms that
+ * offer explicit support for extraction of 8-bit nibbles preferably
+ * complemented with "multiplying" of array index by sizeof(BF_LONG).
+ * For the moment of this writing the list comprises Alpha CPU featuring
+ * extbl and s[48]addq instructions.
+ */
 
-#define BF_ENC(LL,R,S,P) \
-       LL^=P; \
-       LL^=((( S[        (int)(R>>24L)      ] + \
-               S[0x0100+((int)(R>>16L)&0xff)])^ \
-               S[0x0200+((int)(R>> 8L)&0xff)])+ \
-               S[0x0300+((int)(R     )&0xff)])&0xffffffffL;
+#define BF_ENC(LL,R,S,P) ( \
+       LL^=P, \
+       LL^=((( S[       ((int)(R>>24)&0xff)] + \
+               S[0x0100+((int)(R>>16)&0xff)])^ \
+               S[0x0200+((int)(R>> 8)&0xff)])+ \
+               S[0x0300+((int)(R    )&0xff)])&0xffffffffL \
+       )
 #endif
 
 #endif
index a18dfee..02f73b2 100644 (file)
@@ -70,8 +70,25 @@ extern "C" {
 #define BF_ENCRYPT     1
 #define BF_DECRYPT     0
 
-#ifdef WIN16
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! BF_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! BF_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(WIN16) || defined(__LP32__)
 #define BF_LONG unsigned long
+#elif defined(_CRAY) || defined(__ILP64__)
+#define BF_LONG unsigned long
+#define BF_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *                                     <appro@fy.chalmers.se>
+ */
 #else
 #define BF_LONG unsigned int
 #endif
index f5e6c92..cd05361 100644 (file)
 
 #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
 #define CONFIG_HEADER_BF_LOCL_H
-/* Special defines which change the way the code is built depending on the
-   CPU and OS.  For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
-   even newer MIPS CPU's, but at the moment one size fits all for
-   optimization options.  Older Sparc's work better with only UNROLL, but
-   there's no way to tell at compile time what it is you're running on */
-
-#if defined( sun )                    /* Newer Sparc's */
-#  define BF_PTR
-#elif defined( __ultrix )     /* Older MIPS */
-#  define BF_PTR
-#elif defined( __sgi )                /* Newer MIPS */
-#  define BF_PTR
-#endif /* Systems-specific speed defines */
-
-/* use BF_PTR2 for intel boxes,
- * BF_PTR for sparc and MIPS/SGI
- * use nothing for Alpha and HP.
- */
-#if !defined(BF_PTR) && !defined(BF_PTR2)
-#define BF_PTR2
-#endif
+#undef BF_PTR
 #endif /* HEADER_BF_LOCL_H */
 
 #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)