Rijndael.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /* Rijndael.java --
  2. Copyright (C) 2001, 2002, 2003, 2006, 2010 Free Software Foundation, Inc.
  3. This file is a part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or (at
  7. your option) any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  15. USA
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package gnu.javax.crypto.cipher;
  32. import gnu.java.security.Configuration;
  33. import gnu.java.security.Registry;
  34. import gnu.java.security.util.Util;
  35. import java.security.InvalidKeyException;
  36. import java.util.ArrayList;
  37. import java.util.Collections;
  38. import java.util.Iterator;
  39. import java.util.logging.Logger;
  40. /**
  41. * Rijndael --pronounced Reindaal-- is the AES. It is a variable block-size
  42. * (128-, 192- and 256-bit), variable key-size (128-, 192- and 256-bit)
  43. * symmetric key block cipher.
  44. * <p>
  45. * References:
  46. * <ol>
  47. * <li><a href="http://www.esat.kuleuven.ac.be/~rijmen/rijndael/">The Rijndael
  48. * Block Cipher - AES Proposal</a>.<br>
  49. * <a href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a> and
  50. * <a href="mailto:daemen.j@protonworld.com">Joan Daemen</a>.</li>
  51. * </ol>
  52. */
  53. public final class Rijndael
  54. extends BaseCipher
  55. {
  56. private static final Logger log = Configuration.DEBUG ?
  57. Logger.getLogger(Rijndael.class.getName()) : null;
  58. private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes
  59. private static final int DEFAULT_KEY_SIZE = 16; // in bytes
  60. private static final String SS =
  61. "\u637C\u777B\uF26B\u6FC5\u3001\u672B\uFED7\uAB76"
  62. + "\uCA82\uC97D\uFA59\u47F0\uADD4\uA2AF\u9CA4\u72C0"
  63. + "\uB7FD\u9326\u363F\uF7CC\u34A5\uE5F1\u71D8\u3115"
  64. + "\u04C7\u23C3\u1896\u059A\u0712\u80E2\uEB27\uB275"
  65. + "\u0983\u2C1A\u1B6E\u5AA0\u523B\uD6B3\u29E3\u2F84"
  66. + "\u53D1\u00ED\u20FC\uB15B\u6ACB\uBE39\u4A4C\u58CF"
  67. + "\uD0EF\uAAFB\u434D\u3385\u45F9\u027F\u503C\u9FA8"
  68. + "\u51A3\u408F\u929D\u38F5\uBCB6\uDA21\u10FF\uF3D2"
  69. + "\uCD0C\u13EC\u5F97\u4417\uC4A7\u7E3D\u645D\u1973"
  70. + "\u6081\u4FDC\u222A\u9088\u46EE\uB814\uDE5E\u0BDB"
  71. + "\uE032\u3A0A\u4906\u245C\uC2D3\uAC62\u9195\uE479"
  72. + "\uE7C8\u376D\u8DD5\u4EA9\u6C56\uF4EA\u657A\uAE08"
  73. + "\uBA78\u252E\u1CA6\uB4C6\uE8DD\u741F\u4BBD\u8B8A"
  74. + "\u703E\uB566\u4803\uF60E\u6135\u57B9\u86C1\u1D9E"
  75. + "\uE1F8\u9811\u69D9\u8E94\u9B1E\u87E9\uCE55\u28DF"
  76. + "\u8CA1\u890D\uBFE6\u4268\u4199\u2D0F\uB054\uBB16";
  77. private static final byte[] S = new byte[256];
  78. private static final byte[] Si = new byte[256];
  79. private static final int[] T1 = new int[256];
  80. private static final int[] T2 = new int[256];
  81. private static final int[] T3 = new int[256];
  82. private static final int[] T4 = new int[256];
  83. private static final int[] T5 = new int[256];
  84. private static final int[] T6 = new int[256];
  85. private static final int[] T7 = new int[256];
  86. private static final int[] T8 = new int[256];
  87. private static final int[] U1 = new int[256];
  88. private static final int[] U2 = new int[256];
  89. private static final int[] U3 = new int[256];
  90. private static final int[] U4 = new int[256];
  91. private static final byte[] rcon = new byte[30];
  92. private static final int[][][] shifts = new int[][][] {
  93. { { 0, 0 }, { 1, 3 }, { 2, 2 }, { 3, 1 } },
  94. { { 0, 0 }, { 1, 5 }, { 2, 4 }, { 3, 3 } },
  95. { { 0, 0 }, { 1, 7 }, { 3, 5 }, { 4, 4 } } };
  96. /**
  97. * KAT vector (from ecb_vk): I=96
  98. * KEY=0000000000000000000000010000000000000000000000000000000000000000
  99. * CT=E44429474D6FC3084EB2A6B8B46AF754
  100. */
  101. private static final byte[] KAT_KEY = Util.toBytesFromString(
  102. "0000000000000000000000010000000000000000000000000000000000000000");
  103. private static final byte[] KAT_CT = Util.toBytesFromString(
  104. "E44429474D6FC3084EB2A6B8B46AF754");
  105. /** caches the result of the correctness test, once executed. */
  106. private static Boolean valid;
  107. static
  108. {
  109. long time = System.currentTimeMillis();
  110. int ROOT = 0x11B;
  111. int i, j = 0;
  112. // S-box, inverse S-box, T-boxes, U-boxes
  113. int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t;
  114. char c;
  115. for (i = 0; i < 256; i++)
  116. {
  117. c = SS.charAt(i >>> 1);
  118. S[i] = (byte)(((i & 1) == 0) ? c >>> 8 : c & 0xFF);
  119. s = S[i] & 0xFF;
  120. Si[s] = (byte) i;
  121. s2 = s << 1;
  122. if (s2 >= 0x100)
  123. s2 ^= ROOT;
  124. s3 = s2 ^ s;
  125. i2 = i << 1;
  126. if (i2 >= 0x100)
  127. i2 ^= ROOT;
  128. i4 = i2 << 1;
  129. if (i4 >= 0x100)
  130. i4 ^= ROOT;
  131. i8 = i4 << 1;
  132. if (i8 >= 0x100)
  133. i8 ^= ROOT;
  134. i9 = i8 ^ i;
  135. ib = i9 ^ i2;
  136. id = i9 ^ i4;
  137. ie = i8 ^ i4 ^ i2;
  138. T1[i] = t = (s2 << 24) | (s << 16) | (s << 8) | s3;
  139. T2[i] = (t >>> 8) | (t << 24);
  140. T3[i] = (t >>> 16) | (t << 16);
  141. T4[i] = (t >>> 24) | (t << 8);
  142. T5[s] = U1[i] = t = (ie << 24) | (i9 << 16) | (id << 8) | ib;
  143. T6[s] = U2[i] = (t >>> 8) | (t << 24);
  144. T7[s] = U3[i] = (t >>> 16) | (t << 16);
  145. T8[s] = U4[i] = (t >>> 24) | (t << 8);
  146. }
  147. // round constants
  148. int r = 1;
  149. rcon[0] = 1;
  150. for (i = 1; i < 30; i++)
  151. {
  152. r <<= 1;
  153. if (r >= 0x100)
  154. r ^= ROOT;
  155. rcon[i] = (byte) r;
  156. }
  157. time = System.currentTimeMillis() - time;
  158. if (Configuration.DEBUG)
  159. {
  160. log.fine("Static Data");
  161. log.fine("S[]:");
  162. StringBuilder sb;
  163. for (i = 0; i < 16; i++)
  164. {
  165. sb = new StringBuilder();
  166. for (j = 0; j < 16; j++)
  167. sb.append("0x").append(Util.toString(S[i * 16 + j])).append(", ");
  168. log.fine(sb.toString());
  169. }
  170. log.fine("Si[]:");
  171. for (i = 0; i < 16; i++)
  172. {
  173. sb = new StringBuilder();
  174. for (j = 0; j < 16; j++)
  175. sb.append("0x").append(Util.toString(Si[i * 16 + j])).append(", ");
  176. log.fine(sb.toString());
  177. }
  178. log.fine("T1[]:");
  179. for (i = 0; i < 64; i++)
  180. {
  181. sb = new StringBuilder();
  182. for (j = 0; j < 4; j++)
  183. sb.append("0x").append(Util.toString(T1[i * 4 + j])).append(", ");
  184. log.fine(sb.toString());
  185. }
  186. log.fine("T2[]:");
  187. for (i = 0; i < 64; i++)
  188. {
  189. sb = new StringBuilder();
  190. for (j = 0; j < 4; j++)
  191. sb.append("0x").append(Util.toString(T2[i * 4 + j])).append(", ");
  192. log.fine(sb.toString());
  193. }
  194. log.fine("T3[]:");
  195. for (i = 0; i < 64; i++)
  196. {
  197. sb = new StringBuilder();
  198. for (j = 0; j < 4; j++)
  199. sb.append("0x").append(Util.toString(T3[i * 4 + j])).append(", ");
  200. log.fine(sb.toString());
  201. }
  202. log.fine("T4[]:");
  203. for (i = 0; i < 64; i++)
  204. {
  205. sb = new StringBuilder();
  206. for (j = 0; j < 4; j++)
  207. sb.append("0x").append(Util.toString(T4[i * 4 + j])).append(", ");
  208. log.fine(sb.toString());
  209. }
  210. log.fine("T5[]:");
  211. for (i = 0; i < 64; i++)
  212. {
  213. sb = new StringBuilder();
  214. for (j = 0; j < 4; j++)
  215. sb.append("0x").append(Util.toString(T5[i * 4 + j])).append(", ");
  216. log.fine(sb.toString());
  217. }
  218. log.fine("T6[]:");
  219. for (i = 0; i < 64; i++)
  220. {
  221. sb = new StringBuilder();
  222. for (j = 0; j < 4; j++)
  223. sb.append("0x").append(Util.toString(T6[i * 4 + j])).append(", ");
  224. log.fine(sb.toString());
  225. }
  226. log.fine("T7[]:");
  227. for (i = 0; i < 64; i++)
  228. {
  229. sb = new StringBuilder();
  230. for (j = 0; j < 4; j++)
  231. sb.append("0x").append(Util.toString(T7[i * 4 + j])).append(", ");
  232. log.fine(sb.toString());
  233. }
  234. log.fine("T8[]:");
  235. for (i = 0; i < 64; i++)
  236. {
  237. sb = new StringBuilder();
  238. for (j = 0; j < 4; j++)
  239. sb.append("0x").append(Util.toString(T8[i * 4 + j])).append(", ");
  240. log.fine(sb.toString());
  241. }
  242. log.fine("U1[]:");
  243. for (i = 0; i < 64; i++)
  244. {
  245. sb = new StringBuilder();
  246. for (j = 0; j < 4; j++)
  247. sb.append("0x").append(Util.toString(U1[i * 4 + j])).append(", ");
  248. log.fine(sb.toString());
  249. }
  250. log.fine("U2[]:");
  251. for (i = 0; i < 64; i++)
  252. {
  253. sb = new StringBuilder();
  254. for (j = 0; j < 4; j++)
  255. sb.append("0x").append(Util.toString(U2[i * 4 + j])).append(", ");
  256. log.fine(sb.toString());
  257. }
  258. log.fine("U3[]:");
  259. for (i = 0; i < 64; i++)
  260. {
  261. sb = new StringBuilder();
  262. for (j = 0; j < 4; j++)
  263. sb.append("0x").append(Util.toString(U3[i * 4 + j])).append(", ");
  264. log.fine(sb.toString());
  265. }
  266. log.fine("U4[]:");
  267. for (i = 0; i < 64; i++)
  268. {
  269. sb = new StringBuilder();
  270. for (j = 0; j < 4; j++)
  271. sb.append("0x").append(Util.toString(U4[i * 4 + j])).append(", ");
  272. log.fine(sb.toString());
  273. }
  274. log.fine("rcon[]:");
  275. for (i = 0; i < 5; i++)
  276. {
  277. sb = new StringBuilder();
  278. for (j = 0; j < 6; j++)
  279. sb.append("0x").append(Util.toString(rcon[i * 6 + j])).append(", ");
  280. log.fine(sb.toString());
  281. }
  282. log.fine("Total initialization time: " + time + " ms.");
  283. }
  284. }
  285. /** Trivial 0-arguments constructor. */
  286. public Rijndael()
  287. {
  288. super(Registry.RIJNDAEL_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
  289. }
  290. /**
  291. * Returns the number of rounds for a given Rijndael's key and block sizes.
  292. *
  293. * @param ks the size of the user key material in bytes.
  294. * @param bs the desired block size in bytes.
  295. * @return the number of rounds for a given Rijndael's key and block sizes.
  296. */
  297. public static int getRounds(int ks, int bs)
  298. {
  299. switch (ks)
  300. {
  301. case 16:
  302. return bs == 16 ? 10 : (bs == 24 ? 12 : 14);
  303. case 24:
  304. return bs != 32 ? 12 : 14;
  305. default: // 32 bytes = 256 bits
  306. return 14;
  307. }
  308. }
  309. private static void rijndaelEncrypt(byte[] in, int inOffset, byte[] out,
  310. int outOffset, Object sessionKey, int bs)
  311. {
  312. Object[] sKey = (Object[]) sessionKey; // extract encryption round keys
  313. int[][] Ke = (int[][]) sKey[0];
  314. int BC = bs / 4;
  315. int ROUNDS = Ke.length - 1;
  316. int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
  317. int s1 = shifts[SC][1][0];
  318. int s2 = shifts[SC][2][0];
  319. int s3 = shifts[SC][3][0];
  320. int[] a = new int[BC];
  321. int[] t = new int[BC]; // temporary work array
  322. int i, tt;
  323. for (i = 0; i < BC; i++) // plaintext to ints + key
  324. t[i] = (in[inOffset++] << 24
  325. | (in[inOffset++] & 0xFF) << 16
  326. | (in[inOffset++] & 0xFF) << 8
  327. | (in[inOffset++] & 0xFF) ) ^ Ke[0][i];
  328. for (int r = 1; r < ROUNDS; r++) // apply round transforms
  329. {
  330. for (i = 0; i < BC; i++)
  331. a[i] = (T1[(t[ i ] >>> 24) ]
  332. ^ T2[(t[(i + s1) % BC] >>> 16) & 0xFF]
  333. ^ T3[(t[(i + s2) % BC] >>> 8) & 0xFF]
  334. ^ T4[ t[(i + s3) % BC] & 0xFF]) ^ Ke[r][i];
  335. System.arraycopy(a, 0, t, 0, BC);
  336. if (Configuration.DEBUG)
  337. log.fine("CT" + r + "=" + Util.toString(t));
  338. }
  339. for (i = 0; i < BC; i++) // last round is special
  340. {
  341. tt = Ke[ROUNDS][i];
  342. out[outOffset++] = (byte)(S[(t[ i ] >>> 24) ] ^ (tt >>> 24));
  343. out[outOffset++] = (byte)(S[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16));
  344. out[outOffset++] = (byte)(S[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8));
  345. out[outOffset++] = (byte)(S[ t[(i + s3) % BC] & 0xFF] ^ tt );
  346. }
  347. if (Configuration.DEBUG)
  348. log.fine("CT=" + Util.toString(out, outOffset - bs, bs));
  349. }
  350. private static void rijndaelDecrypt(byte[] in, int inOffset, byte[] out,
  351. int outOffset, Object sessionKey, int bs)
  352. {
  353. Object[] sKey = (Object[]) sessionKey; // extract decryption round keys
  354. int[][] Kd = (int[][]) sKey[1];
  355. int BC = bs / 4;
  356. int ROUNDS = Kd.length - 1;
  357. int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
  358. int s1 = shifts[SC][1][1];
  359. int s2 = shifts[SC][2][1];
  360. int s3 = shifts[SC][3][1];
  361. int[] a = new int[BC];
  362. int[] t = new int[BC]; // temporary work array
  363. int i, tt;
  364. for (i = 0; i < BC; i++) // ciphertext to ints + key
  365. t[i] = (in[inOffset++] << 24
  366. | (in[inOffset++] & 0xFF) << 16
  367. | (in[inOffset++] & 0xFF) << 8
  368. | (in[inOffset++] & 0xFF) ) ^ Kd[0][i];
  369. for (int r = 1; r < ROUNDS; r++) // apply round transforms
  370. {
  371. for (i = 0; i < BC; i++)
  372. a[i] = (T5[(t[ i ] >>> 24) ]
  373. ^ T6[(t[(i + s1) % BC] >>> 16) & 0xFF]
  374. ^ T7[(t[(i + s2) % BC] >>> 8) & 0xFF]
  375. ^ T8[ t[(i + s3) % BC] & 0xFF]) ^ Kd[r][i];
  376. System.arraycopy(a, 0, t, 0, BC);
  377. if (Configuration.DEBUG)
  378. log.fine("PT" + r + "=" + Util.toString(t));
  379. }
  380. for (i = 0; i < BC; i++) // last round is special
  381. {
  382. tt = Kd[ROUNDS][i];
  383. out[outOffset++] = (byte)(Si[(t[ i ] >>> 24) ] ^ (tt >>> 24));
  384. out[outOffset++] = (byte)(Si[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16));
  385. out[outOffset++] = (byte)(Si[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8));
  386. out[outOffset++] = (byte)(Si[ t[(i + s3) % BC] & 0xFF] ^ tt );
  387. }
  388. if (Configuration.DEBUG)
  389. log.fine("PT=" + Util.toString(out, outOffset - bs, bs));
  390. }
  391. private static void aesEncrypt(byte[] in, int i, byte[] out, int j, Object key)
  392. {
  393. int[][] Ke = (int[][])((Object[]) key)[0]; // extract encryption round keys
  394. int ROUNDS = Ke.length - 1;
  395. int[] Ker = Ke[0];
  396. // plaintext to ints + key
  397. int t0 = (in[i++] << 24
  398. | (in[i++] & 0xFF) << 16
  399. | (in[i++] & 0xFF) << 8
  400. | (in[i++] & 0xFF) ) ^ Ker[0];
  401. int t1 = (in[i++] << 24
  402. | (in[i++] & 0xFF) << 16
  403. | (in[i++] & 0xFF) << 8
  404. | (in[i++] & 0xFF) ) ^ Ker[1];
  405. int t2 = (in[i++] << 24
  406. | (in[i++] & 0xFF) << 16
  407. | (in[i++] & 0xFF) << 8
  408. | (in[i++] & 0xFF) ) ^ Ker[2];
  409. int t3 = (in[i++] << 24
  410. | (in[i++] & 0xFF) << 16
  411. | (in[i++] & 0xFF) << 8
  412. | (in[i++] & 0xFF) ) ^ Ker[3];
  413. int a0, a1, a2, a3;
  414. for (int r = 1; r < ROUNDS; r++) // apply round transforms
  415. {
  416. Ker = Ke[r];
  417. a0 = (T1[(t0 >>> 24) ]
  418. ^ T2[(t1 >>> 16) & 0xFF]
  419. ^ T3[(t2 >>> 8) & 0xFF]
  420. ^ T4[ t3 & 0xFF]) ^ Ker[0];
  421. a1 = (T1[(t1 >>> 24) ]
  422. ^ T2[(t2 >>> 16) & 0xFF]
  423. ^ T3[(t3 >>> 8) & 0xFF]
  424. ^ T4[ t0 & 0xFF]) ^ Ker[1];
  425. a2 = (T1[(t2 >>> 24) ]
  426. ^ T2[(t3 >>> 16) & 0xFF]
  427. ^ T3[(t0 >>> 8) & 0xFF]
  428. ^ T4[ t1 & 0xFF]) ^ Ker[2];
  429. a3 = (T1[(t3 >>> 24) ]
  430. ^ T2[(t0 >>> 16) & 0xFF]
  431. ^ T3[(t1 >>> 8) & 0xFF]
  432. ^ T4[ t2 & 0xFF]) ^ Ker[3];
  433. t0 = a0;
  434. t1 = a1;
  435. t2 = a2;
  436. t3 = a3;
  437. if (Configuration.DEBUG)
  438. log.fine("CT" + r + "=" + Util.toString(t0) + Util.toString(t1)
  439. + Util.toString(t2) + Util.toString(t3));
  440. }
  441. // last round is special
  442. Ker = Ke[ROUNDS];
  443. int tt = Ker[0];
  444. out[j++] = (byte)(S[(t0 >>> 24) ] ^ (tt >>> 24));
  445. out[j++] = (byte)(S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
  446. out[j++] = (byte)(S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
  447. out[j++] = (byte)(S[ t3 & 0xFF] ^ tt );
  448. tt = Ker[1];
  449. out[j++] = (byte)(S[(t1 >>> 24) ] ^ (tt >>> 24));
  450. out[j++] = (byte)(S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
  451. out[j++] = (byte)(S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
  452. out[j++] = (byte)(S[ t0 & 0xFF] ^ tt );
  453. tt = Ker[2];
  454. out[j++] = (byte)(S[(t2 >>> 24) ] ^ (tt >>> 24));
  455. out[j++] = (byte)(S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
  456. out[j++] = (byte)(S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
  457. out[j++] = (byte)(S[ t1 & 0xFF] ^ tt );
  458. tt = Ker[3];
  459. out[j++] = (byte)(S[(t3 >>> 24) ] ^ (tt >>> 24));
  460. out[j++] = (byte)(S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
  461. out[j++] = (byte)(S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
  462. out[j++] = (byte)(S[ t2 & 0xFF] ^ tt );
  463. if (Configuration.DEBUG)
  464. log.fine("CT=" + Util.toString(out, j - 16, 16));
  465. }
  466. private static void aesDecrypt(byte[] in, int i, byte[] out, int j, Object key)
  467. {
  468. int[][] Kd = (int[][])((Object[]) key)[1]; // extract decryption round keys
  469. int ROUNDS = Kd.length - 1;
  470. int[] Kdr = Kd[0];
  471. // ciphertext to ints + key
  472. int t0 = (in[i++] << 24
  473. | (in[i++] & 0xFF) << 16
  474. | (in[i++] & 0xFF) << 8
  475. | (in[i++] & 0xFF) ) ^ Kdr[0];
  476. int t1 = (in[i++] << 24
  477. | (in[i++] & 0xFF) << 16
  478. | (in[i++] & 0xFF) << 8
  479. | (in[i++] & 0xFF) ) ^ Kdr[1];
  480. int t2 = (in[i++] << 24
  481. | (in[i++] & 0xFF) << 16
  482. | (in[i++] & 0xFF) << 8
  483. | (in[i++] & 0xFF) ) ^ Kdr[2];
  484. int t3 = (in[i++] << 24
  485. | (in[i++] & 0xFF) << 16
  486. | (in[i++] & 0xFF) << 8
  487. | (in[i++] & 0xFF) ) ^ Kdr[3];
  488. int a0, a1, a2, a3;
  489. for (int r = 1; r < ROUNDS; r++) // apply round transforms
  490. {
  491. Kdr = Kd[r];
  492. a0 = (T5[(t0 >>> 24) ]
  493. ^ T6[(t3 >>> 16) & 0xFF]
  494. ^ T7[(t2 >>> 8) & 0xFF]
  495. ^ T8[ t1 & 0xFF]) ^ Kdr[0];
  496. a1 = (T5[(t1 >>> 24) ]
  497. ^ T6[(t0 >>> 16) & 0xFF]
  498. ^ T7[(t3 >>> 8) & 0xFF]
  499. ^ T8[ t2 & 0xFF]) ^ Kdr[1];
  500. a2 = (T5[(t2 >>> 24) ]
  501. ^ T6[(t1 >>> 16) & 0xFF]
  502. ^ T7[(t0 >>> 8) & 0xFF]
  503. ^ T8[ t3 & 0xFF]) ^ Kdr[2];
  504. a3 = (T5[(t3 >>> 24) ]
  505. ^ T6[(t2 >>> 16) & 0xFF]
  506. ^ T7[(t1 >>> 8) & 0xFF]
  507. ^ T8[ t0 & 0xFF]) ^ Kdr[3];
  508. t0 = a0;
  509. t1 = a1;
  510. t2 = a2;
  511. t3 = a3;
  512. if (Configuration.DEBUG)
  513. log.fine("PT" + r + "=" + Util.toString(t0) + Util.toString(t1)
  514. + Util.toString(t2) + Util.toString(t3));
  515. }
  516. // last round is special
  517. Kdr = Kd[ROUNDS];
  518. int tt = Kdr[0];
  519. out[j++] = (byte)(Si[(t0 >>> 24) ] ^ (tt >>> 24));
  520. out[j++] = (byte)(Si[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
  521. out[j++] = (byte)(Si[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
  522. out[j++] = (byte)(Si[ t1 & 0xFF] ^ tt );
  523. tt = Kdr[1];
  524. out[j++] = (byte)(Si[(t1 >>> 24) ] ^ (tt >>> 24));
  525. out[j++] = (byte)(Si[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
  526. out[j++] = (byte)(Si[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
  527. out[j++] = (byte)(Si[ t2 & 0xFF] ^ tt );
  528. tt = Kdr[2];
  529. out[j++] = (byte)(Si[(t2 >>> 24) ] ^ (tt >>> 24));
  530. out[j++] = (byte)(Si[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
  531. out[j++] = (byte)(Si[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
  532. out[j++] = (byte)(Si[ t3 & 0xFF] ^ tt );
  533. tt = Kdr[3];
  534. out[j++] = (byte)(Si[(t3 >>> 24) ] ^ (tt >>> 24));
  535. out[j++] = (byte)(Si[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
  536. out[j++] = (byte)(Si[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
  537. out[j++] = (byte)(Si[ t0 & 0xFF] ^ tt );
  538. if (Configuration.DEBUG)
  539. log.fine("PT=" + Util.toString(out, j - 16, 16));
  540. }
  541. public Object clone()
  542. {
  543. Rijndael result = new Rijndael();
  544. result.currentBlockSize = this.currentBlockSize;
  545. return result;
  546. }
  547. public Iterator blockSizes()
  548. {
  549. ArrayList al = new ArrayList();
  550. al.add(Integer.valueOf(128 / 8));
  551. al.add(Integer.valueOf(192 / 8));
  552. al.add(Integer.valueOf(256 / 8));
  553. return Collections.unmodifiableList(al).iterator();
  554. }
  555. public Iterator keySizes()
  556. {
  557. ArrayList al = new ArrayList();
  558. al.add(Integer.valueOf(128 / 8));
  559. al.add(Integer.valueOf(192 / 8));
  560. al.add(Integer.valueOf(256 / 8));
  561. return Collections.unmodifiableList(al).iterator();
  562. }
  563. /**
  564. * Expands a user-supplied key material into a session key for a designated
  565. * <i>block size</i>.
  566. *
  567. * @param k the 128/192/256-bit user-key to use.
  568. * @param bs the block size in bytes of this Rijndael.
  569. * @return an Object encapsulating the session key.
  570. * @exception IllegalArgumentException if the block size is not 16, 24 or 32.
  571. * @exception InvalidKeyException if the key data is invalid.
  572. */
  573. public Object makeKey(byte[] k, int bs) throws InvalidKeyException
  574. {
  575. if (k == null)
  576. throw new InvalidKeyException("Empty key");
  577. if (! (k.length == 16 || k.length == 24 || k.length == 32))
  578. throw new InvalidKeyException("Incorrect key length");
  579. if (! (bs == 16 || bs == 24 || bs == 32))
  580. throw new IllegalArgumentException();
  581. int ROUNDS = getRounds(k.length, bs);
  582. int BC = bs / 4;
  583. int[][] Ke = new int[ROUNDS + 1][BC]; // encryption round keys
  584. int[][] Kd = new int[ROUNDS + 1][BC]; // decryption round keys
  585. int ROUND_KEY_COUNT = (ROUNDS + 1) * BC;
  586. int KC = k.length / 4;
  587. int[] tk = new int[KC];
  588. int i, j;
  589. // copy user material bytes into temporary ints
  590. for (i = 0, j = 0; i < KC;)
  591. tk[i++] = k[j++] << 24
  592. | (k[j++] & 0xFF) << 16
  593. | (k[j++] & 0xFF) << 8
  594. | (k[j++] & 0xFF);
  595. // copy values into round key arrays
  596. int t = 0;
  597. for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
  598. {
  599. Ke[t / BC][t % BC] = tk[j];
  600. Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
  601. }
  602. int tt, rconpointer = 0;
  603. while (t < ROUND_KEY_COUNT)
  604. {
  605. // extrapolate using phi (the round key evolution function)
  606. tt = tk[KC - 1];
  607. tk[0] ^= (S[(tt >>> 16) & 0xFF] & 0xFF) << 24
  608. ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 16
  609. ^ (S[ tt & 0xFF] & 0xFF) << 8
  610. ^ (S[(tt >>> 24) ] & 0xFF) ^ rcon[rconpointer++] << 24;
  611. if (KC != 8)
  612. for (i = 1, j = 0; i < KC;)
  613. tk[i++] ^= tk[j++];
  614. else
  615. {
  616. for (i = 1, j = 0; i < KC / 2;)
  617. tk[i++] ^= tk[j++];
  618. tt = tk[KC / 2 - 1];
  619. tk[KC / 2] ^= (S[ tt & 0xFF] & 0xFF)
  620. ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 8
  621. ^ (S[(tt >>> 16) & 0xFF] & 0xFF) << 16
  622. ^ S[(tt >>> 24) & 0xFF] << 24;
  623. for (j = KC / 2, i = j + 1; i < KC;)
  624. tk[i++] ^= tk[j++];
  625. }
  626. // copy values into round key arrays
  627. for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
  628. {
  629. Ke[t / BC][t % BC] = tk[j];
  630. Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
  631. }
  632. }
  633. for (int r = 1; r < ROUNDS; r++) // inverse MixColumn where needed
  634. for (j = 0; j < BC; j++)
  635. {
  636. tt = Kd[r][j];
  637. Kd[r][j] = U1[(tt >>> 24) ]
  638. ^ U2[(tt >>> 16) & 0xFF]
  639. ^ U3[(tt >>> 8) & 0xFF]
  640. ^ U4[ tt & 0xFF];
  641. }
  642. return new Object[] { Ke, Kd };
  643. }
  644. public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
  645. {
  646. if (! (bs == 16 || bs == 24 || bs == 32))
  647. throw new IllegalArgumentException();
  648. if (bs == DEFAULT_BLOCK_SIZE)
  649. aesEncrypt(in, i, out, j, k);
  650. else
  651. rijndaelEncrypt(in, i, out, j, k, bs);
  652. }
  653. public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
  654. {
  655. if (! (bs == 16 || bs == 24 || bs == 32))
  656. throw new IllegalArgumentException();
  657. if (bs == DEFAULT_BLOCK_SIZE)
  658. aesDecrypt(in, i, out, j, k);
  659. else
  660. rijndaelDecrypt(in, i, out, j, k, bs);
  661. }
  662. public boolean selfTest()
  663. {
  664. if (valid == null)
  665. {
  666. boolean result = super.selfTest(); // do symmetry tests
  667. if (result)
  668. result = testKat(KAT_KEY, KAT_CT);
  669. valid = Boolean.valueOf(result);
  670. }
  671. return valid.booleanValue();
  672. }
  673. }