📄 twofish.c
字号:
/***************************************************************************
* File: bc_tfish.c
*
* Purpose: The TWOFISH algorithm implementation.
*
* Twofish algorithm's authors:
* Bruce Schneier, Counterpane Systems
* Doug Whiting, Hi/fn
* John Kelsey, Counterpane Systems
* Chris Hall, Counterpane Systems
* David Wagner, UC Berkeley
*
* The code is based on Doug Whiting Twofish implementation.
*
* The code is modified for using as an Encryption Module for BestCrypt system.
*
* The following changings were made:
*
* 1) BestCrypt uses a maximum encryption key length, i.e. 256 bit.
* So the Twofish implementation here is for key length equal to 256 bites only.
*
* 2) Reenterability of the BestCrypt module requires to avoid modifications
* of the extended KeyInstance structure after its initialization, so
* the ReverseRoundSubkeys procedure was completely removed from
* Mr. Doug Whiting's original sources. To compensate that, EncryptRound(K,R)
* macros was modified.
*
* The changings were made by Sergey Frolov, Jetico, Inc.
*
***************************************************************************/
/* the string MUST be commented if */
/*#include <windows.h> #ifndef __WIN95__
#include <windef.h>
#else
#include <basedef.h>
#endif
*/#include "bc_tfish.h"
#include "table.h"
#if LittleEndian
#define Bswap(x) (x) /* NOP for little-endian machines */
#define ADDR_XOR 0 /* NOP for little-endian machines */
#else
#define Bswap(x) ((ROR(x,8) & 0xFF00FF00) | (ROL(x,8) & 0x00FF00FF))
#define ADDR_XOR 3 /* convert byte address in dword */
#endif
/* Macros for extracting bytes from dwords (correct for endianness) */
#define _b(x,N) (((BYTE *)&x)[((N) & 3) ^ ADDR_XOR]) /* pick bytes out of a dword */
#define b0(x) _b(x,0) /* extract LSB of DWORD */
#define b1(x) _b(x,1)
#define b2(x) _b(x,2)
#define b3(x) _b(x,3) /* extract MSB of DWORD */
/* Rotation left (ROL) and rotation right (ROR) operations */
#define ROL(x,n) (((x) << ((n) & 0x1F)) | ((x) >> (32-((n) & 0x1F))))
#define ROR(x,n) (((x) >> ((n) & 0x1F)) | ((x) << (32-((n) & 0x1F))))
/* Macros for extracting bytes from dwords (correct for endianness):
pick bytes out of a dword
*/
#define _b(x,N) (((BYTE *)&x)[((N) & 3) ^ ADDR_XOR])
/* Global data */
int NeedToBuildMDS=1; /* is MDStab initialized yet? */
DWORD MDStab[4][256]; /* Initialized ONE time only */
#define _sBox_ key->sBox8x32
/* set a single S-box value, given the input byte */
#define sbSet(N,i,J,v) { _sBox_[N&2][2*i+(N&1)+2*J]=MDStab[N][v]; }
/* Fe32_ does a full S-box + MDS lookup. Need to #define _sBox_ before use.
Note that we "interleave" 0,1, and 2,3 to avoid cache bank collisions
in optimized assembly language.
*/
#define Fe32(x,R) (_sBox_[0][2*_b(x,R )] ^ _sBox_[0][2*_b(x,R+1)+1] ^ \ _sBox_[2][2*_b(x,R+2)] ^ _sBox_[2][2*_b(x,R+3)+1])
/* Encryption macroses */
#define EncryptRound(K,R) \ t0 = Fe32(x[K ],0); \ t1 = Fe32(x[K^1],3); \ x[K^3] = ROL (x[K^3],1); \ x[K^2]^= t0 + t1 + sk[ TOTAL_SUBKEYS - 2 - 2*(R) ]; \ x[K^3]^= t0 + 2*t1 + sk[ TOTAL_SUBKEYS - 1 - 2*(R) ]; \ x[K^2] = ROR(x[K^2],1);
#define Encrypt2(R) { EncryptRound(0,R+1); EncryptRound(2,R); }
/* Decryption macroses */
#define DecryptRound(K,R) \ t0 = Fe32(x[K ],0); \ t1 = Fe32(x[K^1],3); \ x[K^2] = ROL (x[K^2],1); \ x[K^2]^= t0 + t1 + sk[ROUND_SUBKEYS+2*(R) ]; \ x[K^3]^= t0 + 2*t1 + sk[ROUND_SUBKEYS+2*(R)+1]; \ x[K^3] = ROR (x[K^3],1); \
#define Decrypt2(R) { DecryptRound(2,R+1); DecryptRound(0,R); }
/*
+*****************************************************************************
*
* Function Name: BuildMDS
*
* Function: Initialize the MDStab array
*
* Arguments: None.
*
* Return: None.
*
* Notes:
* Here we precompute all the fixed MDS table. This only needs to be done
* one time at initialization.
*
-****************************************************************************/
void BuildMDS(void)
{
int i;
DWORD d;
BYTE m1[2],mX[2],mY[2];
if (!NeedToBuildMDS) return;
NeedToBuildMDS = 0; /* we won't modify the table again */
for (i=0;i<256;i++)
{
m1[0]=P8x8[0][i]; /* compute all the matrix elements */
mX[0]=(BYTE) Mul_X(m1[0]);
mY[0]=(BYTE) Mul_Y(m1[0]);
m1[1]=P8x8[1][i];
mX[1]=(BYTE) Mul_X(m1[1]);
mY[1]=(BYTE) Mul_Y(m1[1]);
#undef Mul_1 /* change what the pre-processor does with Mij */
#undef Mul_X
#undef Mul_Y
#define Mul_1 m1 /* It will now access m01[], m5B[], and mEF[] */
#define Mul_X mX
#define Mul_Y mY
#define SetMDS(N) \ b0(d) = M0##N[P_##N##0]; \ b1(d) = M1##N[P_##N##0]; \ b2(d) = M2##N[P_##N##0]; \ b3(d) = M3##N[P_##N##0]; \ MDStab[N][i] = d;
SetMDS(0); /* fill in the matrix with elements computed above */
SetMDS(1);
SetMDS(2);
SetMDS(3);
}
#undef Mul_1
#undef Mul_X
#undef Mul_Y
#define Mul_1 Mx_1 /* re-enable true multiply */
#define Mul_X Mx_X
#define Mul_Y Mx_Y
}
/*
+*****************************************************************************
*
* Function Name: RS_MDS_encode
*
* Function: Use (12,8) Reed-Solomon code over GF(256) to produce
* a key S-box dword from two key material dwords.
*
* Arguments: k0 = 1st dword
* k1 = 2nd dword
*
* Return: Remainder polynomial generated using RS code
*
* Notes:
* Since this computation is done only once per reKey per 64 bits of key,
* the performance impact of this routine is imperceptible. The RS code
* chosen has "simple" coefficients to allow smartcard/hardware implementation
* without lookup tables.
*
-****************************************************************************/
DWORD RS_MDS_Encode(DWORD k0,DWORD k1)
{
int i,j;
DWORD r;
for (i=r=0;i<2;i++)
{
r ^= (i) ? k0 : k1; /* merge in 32 more key bits */
for (j=0;j<4;j++) /* shift one byte at a time */
RS_rem(r);
}
return r;
}
/*
+*****************************************************************************
*
* Function Name: Xor256
*
* Function: Copy an 8-bit permutation (256 bytes), xoring with a byte
*
* Arguments: dst = where to put result
* src = where to get data (can be same asa dst)
* b = byte to xor
*
* Return: None
*
-****************************************************************************/
#define X_8(N) { d[N]=s[N] ^ x; d[N+1]=s[N+1] ^ x; }
#define X_32(N) { X_8(N); X_8(N+2); X_8(N+4); X_8(N+6); }
void Xor256(void *dst,void *src,BYTE b)
{
register DWORD x=b*0x01010101u; /* replicate byte to all four bytes */
register DWORD *d=(DWORD *)dst;
register DWORD *s=(DWORD *)src;
X_32(0 ); X_32( 8); X_32(16); X_32(24); /* all inline */
d+=32; /* keep offsets small! */
s+=32;
X_32(0 ); X_32( 8); X_32(16); X_32(24); /* all inline */
}
/*
+*****************************************************************************
*
* Function Name: reKey
*
* Function: Initialize the Twofish key schedule from key32
*
* Arguments: key = ptr to keyInstance to be initialized
*
* Return: TRUE on success
*
* Notes:
* Here we precompute all the round subkeys, although that is not actually
* required. For example, on a smartcard, the round subkeys can
* be generated on-the-fly using f32()
*
-****************************************************************************/
/* F32 macros is working for 256 bits only */
#define F32(res,x,k32) \{ \ DWORD t=x; \ b0(t) = p8(04)[b0(t)] ^ b0(k32[3]); \ b1(t) = p8(14)[b1(t)] ^ b1(k32[3]); \ b2(t) = p8(24)[b2(t)] ^ b2(k32[3]); \ b3(t) = p8(34)[b3(t)] ^ b3(k32[3]); \ \ b0(t) = p8(03)[b0(t)] ^ b0(k32[2]); \ b1(t) = p8(13)[b1(t)] ^ b1(k32[2]); \ b2(t) = p8(23)[b2(t)] ^ b2(k32[2]); \ b3(t) = p8(33)[b3(t)] ^ b3(k32[2]); \ \ res= MDStab[0][p8(01)[p8(02)[b0(t)] ^ b0(k32[1])] ^ b0(k32[0])] ^ \ MDStab[1][p8(11)[p8(12)[b1(t)] ^ b1(k32[1])] ^ b1(k32[0])] ^ \ MDStab[2][p8(21)[p8(22)[b2(t)] ^ b2(k32[1])] ^ b2(k32[0])] ^ \ MDStab[3][p8(31)[p8(32)[b3(t)] ^ b3(k32[1])] ^ b3(k32[0])] ; \}
#define one256(N,J) sbSet(N,i,J,p8(N##1)[p8(N##2)[L0[i+J]]^k1]^k0)
#define sb256(N) \{ Xor256(L1,p8(N##4),b##N(sKey[3])); \ for (i=0;i<256;i+=2) \ { L0[i ]=p8(N##3)[L1[i]]; \ L0[i+1]=p8(N##3)[L1[i+1]]; \ } \ Xor256(L0,L0,b##N(sKey[2])); \ { register DWORD k0=b##N(sKey[0]);\ register DWORD k1=b##N(sKey[1]);\ for (i=0;i<256;i+=2) \ { one256(N,0); one256(N,1); \ } \ } \}
BOOL reKey( DWORD *keyInput, /* 256-bit key that has to be prepared for using */
KeyInstance *key /* Key data that will be used to encrypt/decrypt later */
)
{
int i,j;
DWORD A,B,q;
DWORD sKey[MAX_KEY_BITS/64],
k32e[MAX_KEY_BITS/64],
k32o[MAX_KEY_BITS/64];
BYTE L0[256],
L1[256]; /* small local 8-bit permutations */
BuildMDS();
/* number of 64-bit key words k == 256 / 64 == 4 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -