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 Wed Jul 28 08:07:06 2004 for Crypto++ by doxygen 1.3.7