00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "pch.h"
00018 #include "misc.h"
00019 #include "des.h"
00020
00021 NAMESPACE_BEGIN(CryptoPP)
00022
00023 static inline bool CheckParity(byte b)
00024 {
00025 unsigned int a = b ^ (b >> 4);
00026 return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1;
00027 }
00028
00029 bool DES_CheckKeyParityBits(const byte *key)
00030 {
00031 for (unsigned int i=0; i<8; i++)
00032 if (!CheckParity(key[i]))
00033 return false;
00034 return true;
00035 }
00036
00037 void DES_CorrectKeyParityBits(byte *key)
00038 {
00039 for (unsigned int i=0; i<8; i++)
00040 if (!CheckParity(key[i]))
00041 key[i] ^= 1;
00042 }
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifdef notdef
00053
00054 static byte ip[] = {
00055 58, 50, 42, 34, 26, 18, 10, 2,
00056 60, 52, 44, 36, 28, 20, 12, 4,
00057 62, 54, 46, 38, 30, 22, 14, 6,
00058 64, 56, 48, 40, 32, 24, 16, 8,
00059 57, 49, 41, 33, 25, 17, 9, 1,
00060 59, 51, 43, 35, 27, 19, 11, 3,
00061 61, 53, 45, 37, 29, 21, 13, 5,
00062 63, 55, 47, 39, 31, 23, 15, 7
00063 };
00064
00065
00066 static byte fp[] = {
00067 40, 8, 48, 16, 56, 24, 64, 32,
00068 39, 7, 47, 15, 55, 23, 63, 31,
00069 38, 6, 46, 14, 54, 22, 62, 30,
00070 37, 5, 45, 13, 53, 21, 61, 29,
00071 36, 4, 44, 12, 52, 20, 60, 28,
00072 35, 3, 43, 11, 51, 19, 59, 27,
00073 34, 2, 42, 10, 50, 18, 58, 26,
00074 33, 1, 41, 9, 49, 17, 57, 25
00075 };
00076
00077 static byte ei[] = {
00078 32, 1, 2, 3, 4, 5,
00079 4, 5, 6, 7, 8, 9,
00080 8, 9, 10, 11, 12, 13,
00081 12, 13, 14, 15, 16, 17,
00082 16, 17, 18, 19, 20, 21,
00083 20, 21, 22, 23, 24, 25,
00084 24, 25, 26, 27, 28, 29,
00085 28, 29, 30, 31, 32, 1
00086 };
00087
00088 static byte sbox[8][64] = {
00089
00090 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
00091 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
00092 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
00093 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
00094
00095
00096 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
00097 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
00098 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
00099 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
00100
00101
00102 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
00103 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
00104 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
00105 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
00106
00107
00108 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
00109 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
00110 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
00111 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
00112
00113
00114 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
00115 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
00116 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
00117 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
00118
00119
00120 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
00121 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
00122 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
00123 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
00124
00125
00126 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
00127 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
00128 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
00129 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
00130
00131
00132 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
00133 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
00134 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
00135 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
00136 };
00137
00138
00139 static byte p32i[] = {
00140 16, 7, 20, 21,
00141 29, 12, 28, 17,
00142 1, 15, 23, 26,
00143 5, 18, 31, 10,
00144 2, 8, 24, 14,
00145 32, 27, 3, 9,
00146 19, 13, 30, 6,
00147 22, 11, 4, 25
00148 };
00149 #endif
00150
00151
00152 static const byte pc1[] = {
00153 57, 49, 41, 33, 25, 17, 9,
00154 1, 58, 50, 42, 34, 26, 18,
00155 10, 2, 59, 51, 43, 35, 27,
00156 19, 11, 3, 60, 52, 44, 36,
00157
00158 63, 55, 47, 39, 31, 23, 15,
00159 7, 62, 54, 46, 38, 30, 22,
00160 14, 6, 61, 53, 45, 37, 29,
00161 21, 13, 5, 28, 20, 12, 4
00162 };
00163
00164
00165 static const byte totrot[] = {
00166 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
00167 };
00168
00169
00170 static const byte pc2[] = {
00171 14, 17, 11, 24, 1, 5,
00172 3, 28, 15, 6, 21, 10,
00173 23, 19, 12, 4, 26, 8,
00174 16, 7, 27, 20, 13, 2,
00175 41, 52, 31, 37, 47, 55,
00176 30, 40, 51, 45, 33, 48,
00177 44, 49, 39, 56, 34, 53,
00178 46, 42, 50, 36, 29, 32
00179 };
00180
00181
00182
00183
00184 static const int bytebit[] = {
00185 0200,0100,040,020,010,04,02,01
00186 };
00187
00188
00189 DES::DES(const byte *key, CipherDir dir)
00190 : k(32)
00191 {
00192 SecByteBlock buffer(56+56+8);
00193 byte *const pc1m=buffer;
00194 byte *const pcr=pc1m+56;
00195 byte *const ks=pcr+56;
00196 register int i,j,l;
00197 int m;
00198
00199 for (j=0; j<56; j++) {
00200 l=pc1[j]-1;
00201 m = l & 07;
00202 pc1m[j]=(key[l>>3] &
00203 bytebit[m])
00204 ? 1 : 0;
00205 }
00206 for (i=0; i<16; i++) {
00207 memset(ks,0,8);
00208 for (j=0; j<56; j++)
00209 pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
00210
00211 for (j=0; j<48; j++){
00212
00213 if (pcr[pc2[j]-1]){
00214
00215 l= j % 6;
00216 ks[j/6] |= bytebit[l] >> 2;
00217 }
00218 }
00219
00220 k[2*i] = ((word32)ks[0] << 24)
00221 | ((word32)ks[2] << 16)
00222 | ((word32)ks[4] << 8)
00223 | ((word32)ks[6]);
00224 k[2*i+1] = ((word32)ks[1] << 24)
00225 | ((word32)ks[3] << 16)
00226 | ((word32)ks[5] << 8)
00227 | ((word32)ks[7]);
00228 }
00229
00230 if (dir==DECRYPTION)
00231 for (i=0; i<16; i+=2)
00232 {
00233 std::swap(k[i], k[32-2-i]);
00234 std::swap(k[i+1], k[32-1-i]);
00235 }
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 static inline void IPERM(word32 &left, word32 &right)
00290 {
00291 word32 work;
00292
00293 right = rotlFixed(right, 4U);
00294 work = (left ^ right) & 0xf0f0f0f0;
00295 left ^= work;
00296 right = rotrFixed(right^work, 20U);
00297 work = (left ^ right) & 0xffff0000;
00298 left ^= work;
00299 right = rotrFixed(right^work, 18U);
00300 work = (left ^ right) & 0x33333333;
00301 left ^= work;
00302 right = rotrFixed(right^work, 6U);
00303 work = (left ^ right) & 0x00ff00ff;
00304 left ^= work;
00305 right = rotlFixed(right^work, 9U);
00306 work = (left ^ right) & 0xaaaaaaaa;
00307 left = rotlFixed(left^work, 1U);
00308 right ^= work;
00309 }
00310
00311 static inline void FPERM(word32 &left, word32 &right)
00312 {
00313 word32 work;
00314
00315 right = rotrFixed(right, 1U);
00316 work = (left ^ right) & 0xaaaaaaaa;
00317 right ^= work;
00318 left = rotrFixed(left^work, 9U);
00319 work = (left ^ right) & 0x00ff00ff;
00320 right ^= work;
00321 left = rotlFixed(left^work, 6U);
00322 work = (left ^ right) & 0x33333333;
00323 right ^= work;
00324 left = rotlFixed(left^work, 18U);
00325 work = (left ^ right) & 0xffff0000;
00326 right ^= work;
00327 left = rotlFixed(left^work, 20U);
00328 work = (left ^ right) & 0xf0f0f0f0;
00329 right ^= work;
00330 left = rotrFixed(left^work, 4U);
00331 }
00332
00333 void DES::RawProcessBlock(word32 &l_, word32 &r_) const
00334 {
00335 word32 l = l_, r = r_;
00336 const word32 *kptr=k;
00337
00338 for (unsigned i=0; i<8; i++)
00339 {
00340 word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
00341 l ^= Spbox[6][(work) & 0x3f]
00342 ^ Spbox[4][(work >> 8) & 0x3f]
00343 ^ Spbox[2][(work >> 16) & 0x3f]
00344 ^ Spbox[0][(work >> 24) & 0x3f];
00345 work = r ^ kptr[4*i+1];
00346 l ^= Spbox[7][(work) & 0x3f]
00347 ^ Spbox[5][(work >> 8) & 0x3f]
00348 ^ Spbox[3][(work >> 16) & 0x3f]
00349 ^ Spbox[1][(work >> 24) & 0x3f];
00350
00351 work = rotrFixed(l, 4U) ^ kptr[4*i+2];
00352 r ^= Spbox[6][(work) & 0x3f]
00353 ^ Spbox[4][(work >> 8) & 0x3f]
00354 ^ Spbox[2][(work >> 16) & 0x3f]
00355 ^ Spbox[0][(work >> 24) & 0x3f];
00356 work = l ^ kptr[4*i+3];
00357 r ^= Spbox[7][(work) & 0x3f]
00358 ^ Spbox[5][(work >> 8) & 0x3f]
00359 ^ Spbox[3][(work >> 16) & 0x3f]
00360 ^ Spbox[1][(work >> 24) & 0x3f];
00361 }
00362
00363 l_ = l; r_ = r;
00364 }
00365
00366
00367 void DES::ProcessBlock(const byte *inBlock, byte * outBlock) const
00368 {
00369 word32 l,r;
00370 GetBlockBigEndian(inBlock, l, r);
00371 IPERM(l,r);
00372
00373 const word32 *kptr=k;
00374
00375 for (unsigned i=0; i<8; i++)
00376 {
00377 word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
00378 l ^= Spbox[6][(work) & 0x3f]
00379 ^ Spbox[4][(work >> 8) & 0x3f]
00380 ^ Spbox[2][(work >> 16) & 0x3f]
00381 ^ Spbox[0][(work >> 24) & 0x3f];
00382 work = r ^ kptr[4*i+1];
00383 l ^= Spbox[7][(work) & 0x3f]
00384 ^ Spbox[5][(work >> 8) & 0x3f]
00385 ^ Spbox[3][(work >> 16) & 0x3f]
00386 ^ Spbox[1][(work >> 24) & 0x3f];
00387
00388 work = rotrFixed(l, 4U) ^ kptr[4*i+2];
00389 r ^= Spbox[6][(work) & 0x3f]
00390 ^ Spbox[4][(work >> 8) & 0x3f]
00391 ^ Spbox[2][(work >> 16) & 0x3f]
00392 ^ Spbox[0][(work >> 24) & 0x3f];
00393 work = l ^ kptr[4*i+3];
00394 r ^= Spbox[7][(work) & 0x3f]
00395 ^ Spbox[5][(work >> 8) & 0x3f]
00396 ^ Spbox[3][(work >> 16) & 0x3f]
00397 ^ Spbox[1][(work >> 24) & 0x3f];
00398 }
00399
00400 FPERM(l,r);
00401 PutBlockBigEndian(outBlock, r, l);
00402 }
00403
00404 void DES_EDE2_Encryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
00405 {
00406 word32 l,r;
00407 GetBlockBigEndian(inBlock, l, r);
00408 IPERM(l,r);
00409 e.RawProcessBlock(l, r);
00410 d.RawProcessBlock(r, l);
00411 e.RawProcessBlock(l, r);
00412 FPERM(l,r);
00413 PutBlockBigEndian(outBlock, r, l);
00414 }
00415
00416 void DES_EDE2_Decryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
00417 {
00418 word32 l,r;
00419 GetBlockBigEndian(inBlock, l, r);
00420 IPERM(l,r);
00421 d.RawProcessBlock(l, r);
00422 e.RawProcessBlock(r, l);
00423 d.RawProcessBlock(l, r);
00424 FPERM(l,r);
00425 PutBlockBigEndian(outBlock, r, l);
00426 }
00427
00428 void DES_EDE3_Encryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
00429 {
00430 word32 l,r;
00431 GetBlockBigEndian(inBlock, l, r);
00432 IPERM(l,r);
00433 e1.RawProcessBlock(l, r);
00434 d2.RawProcessBlock(r, l);
00435 e3.RawProcessBlock(l, r);
00436 FPERM(l,r);
00437 PutBlockBigEndian(outBlock, r, l);
00438 }
00439
00440 void DES_EDE3_Decryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
00441 {
00442 word32 l,r;
00443 GetBlockBigEndian(inBlock, l, r);
00444 IPERM(l,r);
00445 d3.RawProcessBlock(l, r);
00446 e2.RawProcessBlock(r, l);
00447 d1.RawProcessBlock(l, r);
00448 FPERM(l,r);
00449 PutBlockBigEndian(outBlock, r, l);
00450 }
00451
00452 void DES_XEX3_Encryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
00453 {
00454 xorbuf(outBlock, inBlock, x1, BLOCKSIZE);
00455 e2.ProcessBlock(outBlock);
00456 xorbuf(outBlock, x3, BLOCKSIZE);
00457 }
00458
00459 void DES_XEX3_Decryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
00460 {
00461 xorbuf(outBlock, inBlock, x3, BLOCKSIZE);
00462 d2.ProcessBlock(outBlock);
00463 xorbuf(outBlock, x1, BLOCKSIZE);
00464 }
00465
00466 NAMESPACE_END