1
0

rijndael.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /**************************************************************************
  2. * This code is based on Szymon Stefanek public domain AES implementation *
  3. **************************************************************************/
  4. #include "rar.hpp"
  5. #ifdef USE_SSE
  6. #include <wmmintrin.h>
  7. #endif
  8. static byte S[256]=
  9. {
  10. 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
  11. 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
  12. 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
  13. 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
  14. 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
  15. 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
  16. 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
  17. 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
  18. 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
  19. 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
  20. 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
  21. 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
  22. 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
  23. 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
  24. 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
  25. 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
  26. };
  27. static byte S5[256];
  28. // Round constants. 10 items are used by AES-128, 8 by AES-192, 7 by AES-256.
  29. static byte rcon[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
  30. static byte T1[256][4],T2[256][4],T3[256][4],T4[256][4];
  31. static byte T5[256][4],T6[256][4],T7[256][4],T8[256][4];
  32. static byte U1[256][4],U2[256][4],U3[256][4],U4[256][4];
  33. inline void Xor128(void *dest,const void *arg1,const void *arg2)
  34. {
  35. #ifdef ALLOW_MISALIGNED
  36. ((uint32*)dest)[0]=((uint32*)arg1)[0]^((uint32*)arg2)[0];
  37. ((uint32*)dest)[1]=((uint32*)arg1)[1]^((uint32*)arg2)[1];
  38. ((uint32*)dest)[2]=((uint32*)arg1)[2]^((uint32*)arg2)[2];
  39. ((uint32*)dest)[3]=((uint32*)arg1)[3]^((uint32*)arg2)[3];
  40. #else
  41. for (int I=0;I<16;I++)
  42. ((byte*)dest)[I]=((byte*)arg1)[I]^((byte*)arg2)[I];
  43. #endif
  44. }
  45. inline void Xor128(byte *dest,const byte *arg1,const byte *arg2,
  46. const byte *arg3,const byte *arg4)
  47. {
  48. #ifdef ALLOW_MISALIGNED
  49. (*(uint32*)dest)=(*(uint32*)arg1)^(*(uint32*)arg2)^(*(uint32*)arg3)^(*(uint32*)arg4);
  50. #else
  51. for (int I=0;I<4;I++)
  52. dest[I]=arg1[I]^arg2[I]^arg3[I]^arg4[I];
  53. #endif
  54. }
  55. inline void Copy128(byte *dest,const byte *src)
  56. {
  57. #ifdef ALLOW_MISALIGNED
  58. ((uint32*)dest)[0]=((uint32*)src)[0];
  59. ((uint32*)dest)[1]=((uint32*)src)[1];
  60. ((uint32*)dest)[2]=((uint32*)src)[2];
  61. ((uint32*)dest)[3]=((uint32*)src)[3];
  62. #else
  63. for (int I=0;I<16;I++)
  64. dest[I]=src[I];
  65. #endif
  66. }
  67. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  68. // API
  69. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  70. Rijndael::Rijndael()
  71. {
  72. if (S5[0]==0)
  73. GenerateTables();
  74. CBCMode = true; // Always true for RAR.
  75. }
  76. void Rijndael::Init(bool Encrypt,const byte *key,uint keyLen,const byte * initVector)
  77. {
  78. #ifdef USE_SSE
  79. // Check SSE here instead of constructor, so if object is a part of some
  80. // structure memset'ed before use, this variable is not lost.
  81. int CPUInfo[4];
  82. __cpuid(CPUInfo, 0x80000000); // Get the maximum supported cpuid function.
  83. if ((CPUInfo[0] & 0x7fffffff)>=1)
  84. {
  85. __cpuid(CPUInfo, 1);
  86. AES_NI=(CPUInfo[2] & 0x2000000)!=0;
  87. }
  88. else
  89. AES_NI=false;
  90. #endif
  91. // Other developers asked us to initialize it to suppress "may be used
  92. // uninitialized" warning in code below in some compilers.
  93. uint uKeyLenInBytes=0;
  94. switch(keyLen)
  95. {
  96. case 128:
  97. uKeyLenInBytes = 16;
  98. m_uRounds = 10;
  99. break;
  100. case 192:
  101. uKeyLenInBytes = 24;
  102. m_uRounds = 12;
  103. break;
  104. case 256:
  105. uKeyLenInBytes = 32;
  106. m_uRounds = 14;
  107. break;
  108. }
  109. byte keyMatrix[_MAX_KEY_COLUMNS][4];
  110. for(uint i = 0; i < uKeyLenInBytes; i++)
  111. keyMatrix[i >> 2][i & 3] = key[i];
  112. if (initVector==NULL)
  113. memset(m_initVector, 0, sizeof(m_initVector));
  114. else
  115. for(int i = 0; i < MAX_IV_SIZE; i++)
  116. m_initVector[i] = initVector[i];
  117. keySched(keyMatrix);
  118. if(!Encrypt)
  119. keyEncToDec();
  120. }
  121. void Rijndael::blockEncrypt(const byte *input,size_t inputLen,byte *outBuffer)
  122. {
  123. if (inputLen <= 0)
  124. return;
  125. size_t numBlocks = inputLen/16;
  126. #ifdef USE_SSE
  127. if (AES_NI)
  128. {
  129. blockEncryptSSE(input,numBlocks,outBuffer);
  130. return;
  131. }
  132. #endif
  133. byte *prevBlock = m_initVector;
  134. for(size_t i = numBlocks;i > 0;i--)
  135. {
  136. byte block[16];
  137. if (CBCMode)
  138. Xor128(block,prevBlock,input);
  139. else
  140. Copy128(block,input);
  141. byte temp[4][4];
  142. Xor128(temp,block,m_expandedKey[0]);
  143. Xor128(outBuffer, T1[temp[0][0]],T2[temp[1][1]],T3[temp[2][2]],T4[temp[3][3]]);
  144. Xor128(outBuffer+4, T1[temp[1][0]],T2[temp[2][1]],T3[temp[3][2]],T4[temp[0][3]]);
  145. Xor128(outBuffer+8, T1[temp[2][0]],T2[temp[3][1]],T3[temp[0][2]],T4[temp[1][3]]);
  146. Xor128(outBuffer+12,T1[temp[3][0]],T2[temp[0][1]],T3[temp[1][2]],T4[temp[2][3]]);
  147. for(int r = 1; r < m_uRounds-1; r++)
  148. {
  149. Xor128(temp,outBuffer,m_expandedKey[r]);
  150. Xor128(outBuffer, T1[temp[0][0]],T2[temp[1][1]],T3[temp[2][2]],T4[temp[3][3]]);
  151. Xor128(outBuffer+4, T1[temp[1][0]],T2[temp[2][1]],T3[temp[3][2]],T4[temp[0][3]]);
  152. Xor128(outBuffer+8, T1[temp[2][0]],T2[temp[3][1]],T3[temp[0][2]],T4[temp[1][3]]);
  153. Xor128(outBuffer+12,T1[temp[3][0]],T2[temp[0][1]],T3[temp[1][2]],T4[temp[2][3]]);
  154. }
  155. Xor128(temp,outBuffer,m_expandedKey[m_uRounds-1]);
  156. outBuffer[ 0] = T1[temp[0][0]][1];
  157. outBuffer[ 1] = T1[temp[1][1]][1];
  158. outBuffer[ 2] = T1[temp[2][2]][1];
  159. outBuffer[ 3] = T1[temp[3][3]][1];
  160. outBuffer[ 4] = T1[temp[1][0]][1];
  161. outBuffer[ 5] = T1[temp[2][1]][1];
  162. outBuffer[ 6] = T1[temp[3][2]][1];
  163. outBuffer[ 7] = T1[temp[0][3]][1];
  164. outBuffer[ 8] = T1[temp[2][0]][1];
  165. outBuffer[ 9] = T1[temp[3][1]][1];
  166. outBuffer[10] = T1[temp[0][2]][1];
  167. outBuffer[11] = T1[temp[1][3]][1];
  168. outBuffer[12] = T1[temp[3][0]][1];
  169. outBuffer[13] = T1[temp[0][1]][1];
  170. outBuffer[14] = T1[temp[1][2]][1];
  171. outBuffer[15] = T1[temp[2][3]][1];
  172. Xor128(outBuffer,outBuffer,m_expandedKey[m_uRounds]);
  173. prevBlock=outBuffer;
  174. outBuffer += 16;
  175. input += 16;
  176. }
  177. Copy128(m_initVector,prevBlock);
  178. }
  179. #ifdef USE_SSE
  180. void Rijndael::blockEncryptSSE(const byte *input,size_t numBlocks,byte *outBuffer)
  181. {
  182. __m128i v = _mm_loadu_si128((__m128i*)m_initVector);
  183. __m128i *src=(__m128i*)input;
  184. __m128i *dest=(__m128i*)outBuffer;
  185. __m128i *rkey=(__m128i*)m_expandedKey;
  186. while (numBlocks > 0)
  187. {
  188. __m128i d = _mm_loadu_si128(src++);
  189. if (CBCMode)
  190. v = _mm_xor_si128(v, d);
  191. else
  192. v = d;
  193. __m128i r0 = _mm_loadu_si128(rkey);
  194. v = _mm_xor_si128(v, r0);
  195. for (int i=1; i<m_uRounds; i++)
  196. {
  197. __m128i ri = _mm_loadu_si128(rkey + i);
  198. v = _mm_aesenc_si128(v, ri);
  199. }
  200. __m128i rl = _mm_loadu_si128(rkey + m_uRounds);
  201. v = _mm_aesenclast_si128(v, rl);
  202. _mm_storeu_si128(dest++,v);
  203. numBlocks--;
  204. }
  205. _mm_storeu_si128((__m128i*)m_initVector,v);
  206. }
  207. #endif
  208. void Rijndael::blockDecrypt(const byte *input, size_t inputLen, byte *outBuffer)
  209. {
  210. if (inputLen <= 0)
  211. return;
  212. size_t numBlocks=inputLen/16;
  213. #ifdef USE_SSE
  214. if (AES_NI)
  215. {
  216. blockDecryptSSE(input,numBlocks,outBuffer);
  217. return;
  218. }
  219. #endif
  220. byte block[16], iv[4][4];
  221. memcpy(iv,m_initVector,16);
  222. for (size_t i = numBlocks; i > 0; i--)
  223. {
  224. byte temp[4][4];
  225. Xor128(temp,input,m_expandedKey[m_uRounds]);
  226. Xor128(block, T5[temp[0][0]],T6[temp[3][1]],T7[temp[2][2]],T8[temp[1][3]]);
  227. Xor128(block+4, T5[temp[1][0]],T6[temp[0][1]],T7[temp[3][2]],T8[temp[2][3]]);
  228. Xor128(block+8, T5[temp[2][0]],T6[temp[1][1]],T7[temp[0][2]],T8[temp[3][3]]);
  229. Xor128(block+12,T5[temp[3][0]],T6[temp[2][1]],T7[temp[1][2]],T8[temp[0][3]]);
  230. for(int r = m_uRounds-1; r > 1; r--)
  231. {
  232. Xor128(temp,block,m_expandedKey[r]);
  233. Xor128(block, T5[temp[0][0]],T6[temp[3][1]],T7[temp[2][2]],T8[temp[1][3]]);
  234. Xor128(block+4, T5[temp[1][0]],T6[temp[0][1]],T7[temp[3][2]],T8[temp[2][3]]);
  235. Xor128(block+8, T5[temp[2][0]],T6[temp[1][1]],T7[temp[0][2]],T8[temp[3][3]]);
  236. Xor128(block+12,T5[temp[3][0]],T6[temp[2][1]],T7[temp[1][2]],T8[temp[0][3]]);
  237. }
  238. Xor128(temp,block,m_expandedKey[1]);
  239. block[ 0] = S5[temp[0][0]];
  240. block[ 1] = S5[temp[3][1]];
  241. block[ 2] = S5[temp[2][2]];
  242. block[ 3] = S5[temp[1][3]];
  243. block[ 4] = S5[temp[1][0]];
  244. block[ 5] = S5[temp[0][1]];
  245. block[ 6] = S5[temp[3][2]];
  246. block[ 7] = S5[temp[2][3]];
  247. block[ 8] = S5[temp[2][0]];
  248. block[ 9] = S5[temp[1][1]];
  249. block[10] = S5[temp[0][2]];
  250. block[11] = S5[temp[3][3]];
  251. block[12] = S5[temp[3][0]];
  252. block[13] = S5[temp[2][1]];
  253. block[14] = S5[temp[1][2]];
  254. block[15] = S5[temp[0][3]];
  255. Xor128(block,block,m_expandedKey[0]);
  256. if (CBCMode)
  257. Xor128(block,block,iv);
  258. Copy128((byte*)iv,input);
  259. Copy128(outBuffer,block);
  260. input += 16;
  261. outBuffer += 16;
  262. }
  263. memcpy(m_initVector,iv,16);
  264. }
  265. #ifdef USE_SSE
  266. void Rijndael::blockDecryptSSE(const byte *input, size_t numBlocks, byte *outBuffer)
  267. {
  268. __m128i initVector = _mm_loadu_si128((__m128i*)m_initVector);
  269. __m128i *src=(__m128i*)input;
  270. __m128i *dest=(__m128i*)outBuffer;
  271. __m128i *rkey=(__m128i*)m_expandedKey;
  272. while (numBlocks > 0)
  273. {
  274. __m128i rl = _mm_loadu_si128(rkey + m_uRounds);
  275. __m128i d = _mm_loadu_si128(src++);
  276. __m128i v = _mm_xor_si128(rl, d);
  277. for (int i=m_uRounds-1; i>0; i--)
  278. {
  279. __m128i ri = _mm_loadu_si128(rkey + i);
  280. v = _mm_aesdec_si128(v, ri);
  281. }
  282. __m128i r0 = _mm_loadu_si128(rkey);
  283. v = _mm_aesdeclast_si128(v, r0);
  284. if (CBCMode)
  285. v = _mm_xor_si128(v, initVector);
  286. initVector = d;
  287. _mm_storeu_si128(dest++,v);
  288. numBlocks--;
  289. }
  290. _mm_storeu_si128((__m128i*)m_initVector,initVector);
  291. }
  292. #endif
  293. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  294. // ALGORITHM
  295. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  296. void Rijndael::keySched(byte key[_MAX_KEY_COLUMNS][4])
  297. {
  298. int j,rconpointer = 0;
  299. // Calculate the necessary round keys
  300. // The number of calculations depends on keyBits and blockBits
  301. int uKeyColumns = m_uRounds - 6;
  302. byte tempKey[_MAX_KEY_COLUMNS][4];
  303. // Copy the input key to the temporary key matrix
  304. memcpy(tempKey,key,sizeof(tempKey));
  305. int r = 0;
  306. int t = 0;
  307. // copy values into round key array
  308. for(j = 0;(j < uKeyColumns) && (r <= m_uRounds); )
  309. {
  310. for(;(j < uKeyColumns) && (t < 4); j++, t++)
  311. for (int k=0;k<4;k++)
  312. m_expandedKey[r][t][k]=tempKey[j][k];
  313. if(t == 4)
  314. {
  315. r++;
  316. t = 0;
  317. }
  318. }
  319. while(r <= m_uRounds)
  320. {
  321. tempKey[0][0] ^= S[tempKey[uKeyColumns-1][1]];
  322. tempKey[0][1] ^= S[tempKey[uKeyColumns-1][2]];
  323. tempKey[0][2] ^= S[tempKey[uKeyColumns-1][3]];
  324. tempKey[0][3] ^= S[tempKey[uKeyColumns-1][0]];
  325. tempKey[0][0] ^= rcon[rconpointer++];
  326. if (uKeyColumns != 8)
  327. for(j = 1; j < uKeyColumns; j++)
  328. for (int k=0;k<4;k++)
  329. tempKey[j][k] ^= tempKey[j-1][k];
  330. else
  331. {
  332. for(j = 1; j < uKeyColumns/2; j++)
  333. for (int k=0;k<4;k++)
  334. tempKey[j][k] ^= tempKey[j-1][k];
  335. tempKey[uKeyColumns/2][0] ^= S[tempKey[uKeyColumns/2 - 1][0]];
  336. tempKey[uKeyColumns/2][1] ^= S[tempKey[uKeyColumns/2 - 1][1]];
  337. tempKey[uKeyColumns/2][2] ^= S[tempKey[uKeyColumns/2 - 1][2]];
  338. tempKey[uKeyColumns/2][3] ^= S[tempKey[uKeyColumns/2 - 1][3]];
  339. for(j = uKeyColumns/2 + 1; j < uKeyColumns; j++)
  340. for (int k=0;k<4;k++)
  341. tempKey[j][k] ^= tempKey[j-1][k];
  342. }
  343. for(j = 0; (j < uKeyColumns) && (r <= m_uRounds); )
  344. {
  345. for(; (j < uKeyColumns) && (t < 4); j++, t++)
  346. for (int k=0;k<4;k++)
  347. m_expandedKey[r][t][k] = tempKey[j][k];
  348. if(t == 4)
  349. {
  350. r++;
  351. t = 0;
  352. }
  353. }
  354. }
  355. }
  356. void Rijndael::keyEncToDec()
  357. {
  358. for(int r = 1; r < m_uRounds; r++)
  359. {
  360. byte n_expandedKey[4][4];
  361. for (int i = 0; i < 4; i++)
  362. for (int j = 0; j < 4; j++)
  363. {
  364. byte *w=m_expandedKey[r][j];
  365. n_expandedKey[j][i]=U1[w[0]][i]^U2[w[1]][i]^U3[w[2]][i]^U4[w[3]][i];
  366. }
  367. memcpy(m_expandedKey[r],n_expandedKey,sizeof(m_expandedKey[0]));
  368. }
  369. }
  370. static byte gmul(byte a, byte b) // Galois field "peasant's algorithm" multiplication.
  371. {
  372. const byte poly=0x1b; // Lower byte of AES 0x11b irreducible polynomial.
  373. byte result = 0;
  374. while (b>0)
  375. {
  376. if ((b & 1) != 0)
  377. result ^= a;
  378. a = (a & 0x80) ? (a<<1)^poly : a<<1;
  379. b >>= 1;
  380. }
  381. return result;
  382. }
  383. // 2021-09-24: changed to slower and simpler code without interim tables.
  384. // It is still fast enough for our purpose.
  385. void Rijndael::GenerateTables()
  386. {
  387. for (int I=0;I<256;I++)
  388. S5[S[I]]=I;
  389. for (int I=0;I<256;I++)
  390. {
  391. byte s=S[I];
  392. T1[I][1]=T1[I][2]=T2[I][2]=T2[I][3]=T3[I][0]=T3[I][3]=T4[I][0]=T4[I][1]=s;
  393. T1[I][0]=T2[I][1]=T3[I][2]=T4[I][3]=gmul(s,2);
  394. T1[I][3]=T2[I][0]=T3[I][1]=T4[I][2]=gmul(s,3);
  395. byte b=S5[I];
  396. U1[b][3]=U2[b][0]=U3[b][1]=U4[b][2]=T5[I][3]=T6[I][0]=T7[I][1]=T8[I][2]=gmul(b,0xb);
  397. U1[b][1]=U2[b][2]=U3[b][3]=U4[b][0]=T5[I][1]=T6[I][2]=T7[I][3]=T8[I][0]=gmul(b,0x9);
  398. U1[b][2]=U2[b][3]=U3[b][0]=U4[b][1]=T5[I][2]=T6[I][3]=T7[I][0]=T8[I][1]=gmul(b,0xd);
  399. U1[b][0]=U2[b][1]=U3[b][2]=U4[b][3]=T5[I][0]=T6[I][1]=T7[I][2]=T8[I][3]=gmul(b,0xe);
  400. }
  401. }
  402. #if 0
  403. static void TestRijndael();
  404. struct TestRij {TestRij() {TestRijndael();exit(0);}} GlobalTestRij;
  405. // Test CBC encryption according to NIST 800-38A.
  406. void TestRijndael()
  407. {
  408. byte IV[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
  409. byte PT[64]={
  410. 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,
  411. 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51,
  412. 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef,
  413. 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10,
  414. };
  415. byte Key128[16]={0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c};
  416. byte Chk128[16]={0x3f,0xf1,0xca,0xa1,0x68,0x1f,0xac,0x09,0x12,0x0e,0xca,0x30,0x75,0x86,0xe1,0xa7};
  417. byte Key192[24]={0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52,0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5,0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b};
  418. byte Chk192[16]={0x08,0xb0,0xe2,0x79,0x88,0x59,0x88,0x81,0xd9,0x20,0xa9,0xe6,0x4f,0x56,0x15,0xcd};
  419. byte Key256[32]={0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4};
  420. byte Chk256[16]={0xb2,0xeb,0x05,0xe2,0xc3,0x9b,0xe9,0xfc,0xda,0x6c,0x19,0x07,0x8c,0x6a,0x9d,0x1b};
  421. byte *Key[3]={Key128,Key192,Key256};
  422. byte *Chk[3]={Chk128,Chk192,Chk256};
  423. Rijndael rij; // Declare outside of loop to test re-initialization.
  424. for (uint L=0;L<3;L++)
  425. {
  426. byte Out[16];
  427. wchar Str[sizeof(Out)*2+1];
  428. uint KeyLength=128+L*64;
  429. rij.Init(true,Key[L],KeyLength,IV);
  430. for (uint I=0;I<sizeof(PT);I+=16)
  431. rij.blockEncrypt(PT+I,16,Out);
  432. BinToHex(Chk[L],16,NULL,Str,ASIZE(Str));
  433. mprintf(L"\nAES-%d expected: %s",KeyLength,Str);
  434. BinToHex(Out,sizeof(Out),NULL,Str,ASIZE(Str));
  435. mprintf(L"\nAES-%d result: %s",KeyLength,Str);
  436. if (memcmp(Out,Chk[L],16)==0)
  437. mprintf(L" OK");
  438. else
  439. {
  440. mprintf(L" FAILED");
  441. getchar();
  442. }
  443. }
  444. }
  445. #endif