Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

cast.cpp

00001 // cast.cpp - written and placed in the public domain by Wei Dai and Leonard Janke
00002 // based on Steve Reid's public domain cast.c
00003 
00004 #include "pch.h"
00005 #include "cast.h"
00006 
00007 NAMESPACE_BEGIN(CryptoPP)
00008 
00009 /* Macros to access 8-bit bytes out of a 32-bit word */
00010 #define U8a(x) GETBYTE(x,3)
00011 #define U8b(x) GETBYTE(x,2)
00012 #define U8c(x) GETBYTE(x,1)
00013 #define U8d(x) GETBYTE(x,0)
00014 
00015 /* CAST uses three different round functions */
00016 #define f1(l, r, km, kr) \
00017         t = rotlVariable(km + r, kr); \
00018         l ^= ((S[0][U8a(t)] ^ S[1][U8b(t)]) - \
00019          S[2][U8c(t)]) + S[3][U8d(t)];
00020 #define f2(l, r, km, kr) \
00021         t = rotlVariable(km ^ r, kr); \
00022         l ^= ((S[0][U8a(t)] - S[1][U8b(t)]) + \
00023          S[2][U8c(t)]) ^ S[3][U8d(t)];
00024 #define f3(l, r, km, kr) \
00025         t = rotlVariable(km - r, kr); \
00026         l ^= ((S[0][U8a(t)] + S[1][U8b(t)]) ^ \
00027          S[2][U8c(t)]) - S[3][U8d(t)];
00028 
00029 #define F1(l, r, i, j) f1(l, r, K[i], K[i+j])
00030 #define F2(l, r, i, j) f2(l, r, K[i], K[i+j])
00031 #define F3(l, r, i, j) f3(l, r, K[i], K[i+j])
00032 
00033 void CAST128Encryption::ProcessBlock(const byte *inBlock, byte * outBlock) const
00034 {
00035         word32 t, l, r;
00036 
00037         /* Get inblock into l,r */
00038         GetBlockBigEndian(inBlock,l,r);
00039         /* Do the work */
00040         F1(l, r,  0, 16);
00041         F2(r, l,  1, 16);
00042         F3(l, r,  2, 16);
00043         F1(r, l,  3, 16);
00044         F2(l, r,  4, 16);
00045         F3(r, l,  5, 16);
00046         F1(l, r,  6, 16);
00047         F2(r, l,  7, 16);
00048         F3(l, r,  8, 16);
00049         F1(r, l,  9, 16);
00050         F2(l, r, 10, 16);
00051         F3(r, l, 11, 16);
00052         /* Only do full 16 rounds if key length > 80 bits */
00053         if (!reduced) {
00054                 F1(l, r, 12, 16);
00055                 F2(r, l, 13, 16);
00056                 F3(l, r, 14, 16);
00057                 F1(r, l, 15, 16);
00058         }
00059         /* Put l,r into outblock */
00060         PutBlockBigEndian(outBlock,r,l);
00061         /* Wipe clean */
00062         t = l = r = 0;
00063 }
00064 
00065 void CAST128Decryption::ProcessBlock(const byte *inBlock, byte * outBlock) const
00066 {
00067         word32 t, l, r;
00068 
00069         /* Get inblock into l,r */
00070         GetBlockBigEndian(inBlock,r,l);
00071         /* Only do full 16 rounds if key length > 80 bits */
00072         if (!reduced) {
00073                 F1(r, l, 15, 16);
00074                 F3(l, r, 14, 16);
00075                 F2(r, l, 13, 16);
00076                 F1(l, r, 12, 16);
00077         }
00078         F3(r, l, 11, 16);
00079         F2(l, r, 10, 16);
00080         F1(r, l,  9, 16);
00081         F3(l, r,  8, 16);
00082         F2(r, l,  7, 16);
00083         F1(l, r,  6, 16);
00084         F3(r, l,  5, 16);
00085         F2(l, r,  4, 16);
00086         F1(r, l,  3, 16);
00087         F3(l, r,  2, 16);
00088         F2(r, l,  1, 16);
00089         F1(l, r,  0, 16);
00090         /* Put l,r into outblock */
00091         PutBlockBigEndian(outBlock,l,r);
00092         /* Wipe clean */
00093         t = l = r = 0;
00094 }
00095 
00096 CAST128::CAST128(const byte *userKey, unsigned int keylength)
00097         : reduced(keylength <= 10), K(32)
00098 {
00099         assert(keylength == KeyLength(keylength));
00100 
00101         word32 X[4], Z[4];
00102         GetUserKeyBigEndian(X, 4, userKey, keylength);
00103 
00104 #define x(i) GETBYTE(X[i/4], 3-i%4)
00105 #define z(i) GETBYTE(Z[i/4], 3-i%4)
00106 
00107         unsigned int i;
00108         for (i=0; i<=16; i+=16)
00109         {
00110                 // this part is copied directly from RFC 2144 (with some search and replace) by Wei Dai
00111                 Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)];
00112                 Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)];
00113                 Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)];
00114                 Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)];
00115                 K[i+0] = S[4][z(0x8)] ^ S[5][z(0x9)] ^ S[6][z(0x7)] ^ S[7][z(0x6)] ^ S[4][z(0x2)];
00116                 K[i+1] = S[4][z(0xA)] ^ S[5][z(0xB)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[5][z(0x6)];
00117                 K[i+2] = S[4][z(0xC)] ^ S[5][z(0xD)] ^ S[6][z(0x3)] ^ S[7][z(0x2)] ^ S[6][z(0x9)];
00118                 K[i+3] = S[4][z(0xE)] ^ S[5][z(0xF)] ^ S[6][z(0x1)] ^ S[7][z(0x0)] ^ S[7][z(0xC)];
00119                 X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)];
00120                 X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)];
00121                 X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)];
00122                 X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)];
00123                 K[i+4] = S[4][x(0x3)] ^ S[5][x(0x2)] ^ S[6][x(0xC)] ^ S[7][x(0xD)] ^ S[4][x(0x8)];
00124                 K[i+5] = S[4][x(0x1)] ^ S[5][x(0x0)] ^ S[6][x(0xE)] ^ S[7][x(0xF)] ^ S[5][x(0xD)];
00125                 K[i+6] = S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x8)] ^ S[7][x(0x9)] ^ S[6][x(0x3)];
00126                 K[i+7] = S[4][x(0x5)] ^ S[5][x(0x4)] ^ S[6][x(0xA)] ^ S[7][x(0xB)] ^ S[7][x(0x7)];
00127                 Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)];
00128                 Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)];
00129                 Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)];
00130                 Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)];
00131                 K[i+8] = S[4][z(0x3)] ^ S[5][z(0x2)] ^ S[6][z(0xC)] ^ S[7][z(0xD)] ^ S[4][z(0x9)];
00132                 K[i+9] = S[4][z(0x1)] ^ S[5][z(0x0)] ^ S[6][z(0xE)] ^ S[7][z(0xF)] ^ S[5][z(0xC)];
00133                 K[i+10] = S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x8)] ^ S[7][z(0x9)] ^ S[6][z(0x2)];
00134                 K[i+11] = S[4][z(0x5)] ^ S[5][z(0x4)] ^ S[6][z(0xA)] ^ S[7][z(0xB)] ^ S[7][z(0x6)];
00135                 X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)];
00136                 X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)];
00137                 X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)];
00138                 X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)];
00139                 K[i+12] = S[4][x(0x8)] ^ S[5][x(0x9)] ^ S[6][x(0x7)] ^ S[7][x(0x6)] ^ S[4][x(0x3)];
00140                 K[i+13] = S[4][x(0xA)] ^ S[5][x(0xB)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[5][x(0x7)];
00141                 K[i+14] = S[4][x(0xC)] ^ S[5][x(0xD)] ^ S[6][x(0x3)] ^ S[7][x(0x2)] ^ S[6][x(0x8)];
00142                 K[i+15] = S[4][x(0xE)] ^ S[5][x(0xF)] ^ S[6][x(0x1)] ^ S[7][x(0x0)] ^ S[7][x(0xD)];
00143         }
00144 
00145         for (i=16; i<32; i++)
00146                 K[i] &= 0x1f;
00147 }
00148 
00149 // The following CAST-256 implementation was contributed by Leonard Janke
00150 
00151 const word32 CAST256::t_m[8][24]={
00152         0x5a827999, 0xd151d6a1, 0x482133a9, 0xbef090b1, 0x35bfedb9, 0xac8f4ac1, 
00153         0x235ea7c9, 0x9a2e04d1, 0x10fd61d9, 0x87ccbee1, 0xfe9c1be9, 0x756b78f1, 
00154         0xec3ad5f9, 0x630a3301, 0xd9d99009, 0x50a8ed11, 0xc7784a19, 0x3e47a721, 
00155         0xb5170429, 0x2be66131, 0xa2b5be39, 0x19851b41, 0x90547849, 0x0723d551, 
00156         0xc95c653a, 0x402bc242, 0xb6fb1f4a, 0x2dca7c52, 0xa499d95a, 0x1b693662, 
00157         0x9238936a, 0x0907f072, 0x7fd74d7a, 0xf6a6aa82, 0x6d76078a, 0xe4456492, 
00158         0x5b14c19a, 0xd1e41ea2, 0x48b37baa, 0xbf82d8b2, 0x365235ba, 0xad2192c2, 
00159         0x23f0efca, 0x9ac04cd2, 0x118fa9da, 0x885f06e2, 0xff2e63ea, 0x75fdc0f2, 
00160         0x383650db, 0xaf05ade3, 0x25d50aeb, 0x9ca467f3, 0x1373c4fb, 0x8a432203, 
00161         0x01127f0b, 0x77e1dc13, 0xeeb1391b, 0x65809623, 0xdc4ff32b, 0x531f5033, 
00162         0xc9eead3b, 0x40be0a43, 0xb78d674b, 0x2e5cc453, 0xa52c215b, 0x1bfb7e63, 
00163         0x92cadb6b, 0x099a3873, 0x8069957b, 0xf738f283, 0x6e084f8b, 0xe4d7ac93, 
00164         0xa7103c7c, 0x1ddf9984, 0x94aef68c, 0x0b7e5394, 0x824db09c, 0xf91d0da4, 
00165         0x6fec6aac, 0xe6bbc7b4, 0x5d8b24bc, 0xd45a81c4, 0x4b29decc, 0xc1f93bd4, 
00166         0x38c898dc, 0xaf97f5e4, 0x266752ec, 0x9d36aff4, 0x14060cfc, 0x8ad56a04, 
00167         0x01a4c70c, 0x78742414, 0xef43811c, 0x6612de24, 0xdce23b2c, 0x53b19834, 
00168         0x15ea281d, 0x8cb98525, 0x0388e22d, 0x7a583f35, 0xf1279c3d, 0x67f6f945, 
00169         0xdec6564d, 0x5595b355, 0xcc65105d, 0x43346d65, 0xba03ca6d, 0x30d32775, 
00170         0xa7a2847d, 0x1e71e185, 0x95413e8d, 0x0c109b95, 0x82dff89d, 0xf9af55a5, 
00171         0x707eb2ad, 0xe74e0fb5, 0x5e1d6cbd, 0xd4ecc9c5, 0x4bbc26cd, 0xc28b83d5, 
00172         0x84c413be, 0xfb9370c6, 0x7262cdce, 0xe9322ad6, 0x600187de, 0xd6d0e4e6, 
00173         0x4da041ee, 0xc46f9ef6, 0x3b3efbfe, 0xb20e5906, 0x28ddb60e, 0x9fad1316, 
00174         0x167c701e, 0x8d4bcd26, 0x041b2a2e, 0x7aea8736, 0xf1b9e43e, 0x68894146, 
00175         0xdf589e4e, 0x5627fb56, 0xccf7585e, 0x43c6b566, 0xba96126e, 0x31656f76, 
00176         0xf39dff5f, 0x6a6d5c67, 0xe13cb96f, 0x580c1677, 0xcedb737f, 0x45aad087, 
00177         0xbc7a2d8f, 0x33498a97, 0xaa18e79f, 0x20e844a7, 0x97b7a1af, 0x0e86feb7, 
00178         0x85565bbf, 0xfc25b8c7, 0x72f515cf, 0xe9c472d7, 0x6093cfdf, 0xd7632ce7, 
00179         0x4e3289ef, 0xc501e6f7, 0x3bd143ff, 0xb2a0a107, 0x296ffe0f, 0xa03f5b17, 
00180         0x6277eb00, 0xd9474808, 0x5016a510, 0xc6e60218, 0x3db55f20, 0xb484bc28, 
00181         0x2b541930, 0xa2237638, 0x18f2d340, 0x8fc23048, 0x06918d50, 0x7d60ea58, 
00182         0xf4304760, 0x6affa468, 0xe1cf0170, 0x589e5e78, 0xcf6dbb80, 0x463d1888, 
00183         0xbd0c7590, 0x33dbd298, 0xaaab2fa0, 0x217a8ca8, 0x9849e9b0, 0x0f1946b8 
00184 };
00185 
00186 const unsigned int CAST256::t_r[8][24]={ 
00187         19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 
00188         4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 
00189         21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 
00190         6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 
00191         23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 
00192         8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 
00193         25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 
00194         10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2 
00195 };
00196 
00197 #define Q(i) \
00198         F1(block[2],block[3],8*i+4,-4); \
00199         F2(block[1],block[2],8*i+5,-4); \
00200         F3(block[0],block[1],8*i+6,-4); \
00201         F1(block[3],block[0],8*i+7,-4);
00202 
00203 #define QBar(i) \
00204         F1(block[3],block[0],8*i+7,-4); \
00205         F3(block[0],block[1],8*i+6,-4); \
00206         F2(block[1],block[2],8*i+5,-4); \
00207         F1(block[2],block[3],8*i+4,-4);
00208 
00209 /* CAST256's encrypt/decrypt functions  are identical except for the order that
00210 the keys are used */
00211 
00212 void CAST256::ProcessBlock(const byte *inBlock, byte * outBlock) const
00213 {
00214         word32 t, block[4];
00215         GetBlockBigEndian(inBlock,block[0],block[1],block[2],block[3]);
00216 
00217         // Perform 6 forward quad rounds
00218         Q(0);
00219         Q(1);
00220         Q(2);
00221         Q(3);
00222         Q(4);
00223         Q(5);
00224 
00225         // Perform 6 reverse quad rounds
00226         QBar(6);
00227         QBar(7);
00228         QBar(8);
00229         QBar(9);
00230         QBar(10);
00231         QBar(11);
00232 
00233         PutBlockBigEndian(outBlock,block[0],block[1],block[2],block[3]);
00234 }
00235 
00236 /* Set up a CAST-256 key */
00237 
00238 void CAST256::Omega(int i, word32 kappa[8])
00239 {
00240         word32 t;
00241 
00242         f1(kappa[6],kappa[7],t_m[0][i],t_r[0][i]);
00243         f2(kappa[5],kappa[6],t_m[1][i],t_r[1][i]);
00244         f3(kappa[4],kappa[5],t_m[2][i],t_r[2][i]);
00245         f1(kappa[3],kappa[4],t_m[3][i],t_r[3][i]);
00246         f2(kappa[2],kappa[3],t_m[4][i],t_r[4][i]);
00247         f3(kappa[1],kappa[2],t_m[5][i],t_r[5][i]);
00248         f1(kappa[0],kappa[1],t_m[6][i],t_r[6][i]);
00249         f2(kappa[7],kappa[0],t_m[7][i],t_r[7][i]);
00250 }
00251 
00252 CAST256::CAST256(const byte *userKey, unsigned int keylength)
00253         : K(8*12)
00254 {
00255         assert(keylength == KeyLength(keylength));
00256 
00257         word32 kappa[8];
00258         GetUserKeyBigEndian(kappa, 8, userKey, keylength);
00259 
00260         for(int i=0; i<12; ++i)
00261         {
00262                 Omega(2*i,kappa);
00263                 Omega(2*i+1,kappa);
00264                 
00265                 K[8*i]=kappa[0] & 31;
00266                 K[8*i+1]=kappa[2] & 31;
00267                 K[8*i+2]=kappa[4] & 31;
00268                 K[8*i+3]=kappa[6] & 31;
00269                 K[8*i+4]=kappa[7];
00270                 K[8*i+5]=kappa[5];
00271                 K[8*i+6]=kappa[3];
00272                 K[8*i+7]=kappa[1];
00273         }
00274 
00275         memset(kappa, 0, sizeof(kappa));
00276 }
00277 
00278 CAST256Decryption::CAST256Decryption(const byte *userKey, unsigned int keylength)
00279         : CAST256(userKey, keylength) 
00280 {
00281         for(int j=0; j<6; ++j)
00282         {
00283                 for(int i=0; i<4; ++i)
00284                 {
00285                         int i1=8*j+i;
00286                         int i2=8*(11-j)+i;
00287 
00288                         assert(i1<i2);
00289 
00290                         std::swap(K[i1],K[i2]); 
00291                         std::swap(K[i1+4],K[i2+4]); 
00292                 }
00293         }
00294 }
00295 
00296 NAMESPACE_END

Generated at Mon Jan 15 01:16:29 2001 for Crypto++ by doxygen1.2.4 written by Dimitri van Heesch, © 1997-2000