aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/bf
diff options
context:
space:
mode:
authorUlf Möller <ulf@openssl.org>1999-04-27 21:17:18 +0000
committerUlf Möller <ulf@openssl.org>1999-04-27 21:17:18 +0000
commit8cd8a7b7a2cb2b69cd1ede5c525e3dbbee138a0c (patch)
tree30d450a439b3356fbb29b84189dd93bed2d10656 /crypto/bf
parent67a4728511cad54b22b871aa2674944d111f30d2 (diff)
downloadopenssl-8cd8a7b7a2cb2b69cd1ede5c525e3dbbee138a0c.tar.gz
More portable blowfish macros.
Submitted by: Andy Polyakov <appro@fy.chalmers.se>
Diffstat (limited to 'crypto/bf')
-rw-r--r--crypto/bf/bf_enc.c72
-rw-r--r--crypto/bf/bf_locl.h89
-rw-r--r--crypto/bf/blowfish.h19
3 files changed, 141 insertions, 39 deletions
diff --git a/crypto/bf/bf_enc.c b/crypto/bf/bf_enc.c
index f8a95e2142..ee01834561 100644
--- a/crypto/bf/bf_enc.c
+++ b/crypto/bf/bf_enc.c
@@ -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,
diff --git a/crypto/bf/bf_locl.h b/crypto/bf/bf_locl.h
index 7936e6c56a..3ebb145f88 100644
--- a/crypto/bf/bf_locl.h
+++ b/crypto/bf/bf_locl.h
@@ -151,56 +151,69 @@
/* 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
diff --git a/crypto/bf/blowfish.h b/crypto/bf/blowfish.h
index a18dfee1a4..02f73b2f30 100644
--- a/crypto/bf/blowfish.h
+++ b/crypto/bf/blowfish.h
@@ -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