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

Generated on Sun Mar 14 20:44:24 2004 for Crypto++ by doxygen 1.3.6-20040222