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