More portable blowfish macros.

Submitted by: Andy Polyakov <appro@fy.chalmers.se>
This commit is contained in:
Ulf Möller 1999-04-27 21:17:18 +00:00
parent 67a4728511
commit 8cd8a7b7a2
4 changed files with 142 additions and 60 deletions

View 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,

View File

@ -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 */
#define BF_ENC(LL,R,S,P) \
LL^=P; \
/*
* 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, \
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

View 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

View File

@ -58,27 +58,7 @@
#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)