1 /* Twofish.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 * Twofish is a balanced 128-bit Feistel cipher, consisting of 16 rounds. In 53 * each round, a 64-bit S-box value is computed from 64 bits of the block, and 54 * this value is xored into the other half of the block. The two half-blocks are 55 * then exchanged, and the next round begins. Before the first round, all input 56 * bits are xored with key-dependent "whitening" subkeys, and after the final 57 * round the output bits are xored with other key-dependent whitening subkeys; 58 * these subkeys are not used anywhere else in the algorithm. 59 * <p> 60 * Twofish is designed by Bruce Schneier, Doug Whiting, John Kelsey, Chris 61 * Hall, David Wagner and Niels Ferguson. 62 * <p> 63 * References: 64 * <ol> 65 * <li><a href="http://www.counterpane.com/twofish-paper.html">Twofish: A 66 * 128-bit Block Cipher</a>.</li> 67 * </ol> 68 */ 69 public final class Twofish 70 extends BaseCipher 71 { 72 private static final Logger log = Configuration.DEBUG ? 73 Logger.getLogger(Twofish.class.getName()) : null; 74 private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes 75 private static final int DEFAULT_KEY_SIZE = 16; // in bytes 76 private static final int MAX_ROUNDS = 16; // max # rounds (for allocating subkeys) 77 private static final int ROUNDS = MAX_ROUNDS; 78 // subkey array indices 79 private static final int INPUT_WHITEN = 0; 80 private static final int OUTPUT_WHITEN = INPUT_WHITEN + DEFAULT_BLOCK_SIZE / 4; 81 private static final int ROUND_SUBKEYS = OUTPUT_WHITEN + DEFAULT_BLOCK_SIZE / 4; 82 private static final int SK_STEP = 0x02020202; 83 private static final int SK_BUMP = 0x01010101; 84 private static final int SK_ROTL = 9; 85 private static final String[] Pm = new String[] { 86 // p0 87 "\uA967\uB3E8\u04FD\uA376\u9A92\u8078\uE4DD\uD138" 88 + "\u0DC6\u3598\u18F7\uEC6C\u4375\u3726\uFA13\u9448" 89 + "\uF2D0\u8B30\u8454\uDF23\u195B\u3D59\uF3AE\uA282" 90 + "\u6301\u832E\uD951\u9B7C\uA6EB\uA5BE\u160C\uE361" 91 + "\uC08C\u3AF5\u732C\u250B\uBB4E\u896B\u536A\uB4F1" 92 + "\uE1E6\uBD45\uE2F4\uB666\uCC95\u0356\uD41C\u1ED7" 93 + "\uFBC3\u8EB5\uE9CF\uBFBA\uEA77\u39AF\u33C9\u6271" 94 + "\u8179\u09AD\u24CD\uF9D8\uE5C5\uB94D\u4408\u86E7" 95 + "\uA11D\uAAED\u0670\uB2D2\u417B\uA011\u31C2\u2790" 96 + "\u20F6\u60FF\u965C\uB1AB\u9E9C\u521B\u5F93\u0AEF" 97 + "\u9185\u49EE\u2D4F\u8F3B\u4787\u6D46\uD63E\u6964" 98 + "\u2ACE\uCB2F\uFC97\u057A\uAC7F\uD51A\u4B0E\uA75A" 99 + "\u2814\u3F29\u883C\u4C02\uB8DA\uB017\u551F\u8A7D" 100 + "\u57C7\u8D74\uB7C4\u9F72\u7E15\u2212\u5807\u9934" 101 + "\u6E50\uDE68\u65BC\uDBF8\uC8A8\u2B40\uDCFE\u32A4" 102 + "\uCA10\u21F0\uD35D\u0F00\u6F9D\u3642\u4A5E\uC1E0", 103 // p1 104 "\u75F3\uC6F4\uDB7B\uFBC8\u4AD3\uE66B\u457D\uE84B" 105 + "\uD632\uD8FD\u3771\uF1E1\u300F\uF81B\u87FA\u063F" 106 + "\u5EBA\uAE5B\u8A00\uBC9D\u6DC1\uB10E\u805D\uD2D5" 107 + "\uA084\u0714\uB590\u2CA3\uB273\u4C54\u9274\u3651" 108 + "\u38B0\uBD5A\uFC60\u6296\u6C42\uF710\u7C28\u278C" 109 + "\u1395\u9CC7\u2446\u3B70\uCAE3\u85CB\u11D0\u93B8" 110 + "\uA683\u20FF\u9F77\uC3CC\u036F\u08BF\u40E7\u2BE2" 111 + "\u790C\uAA82\u413A\uEAB9\uE49A\uA497\u7EDA\u7A17" 112 + "\u6694\uA11D\u3DF0\uDEB3\u0B72\uA71C\uEFD1\u533E" 113 + "\u8F33\u265F\uEC76\u2A49\u8188\uEE21\uC41A\uEBD9" 114 + "\uC539\u99CD\uAD31\u8B01\u1823\uDD1F\u4E2D\uF948" 115 + "\u4FF2\u658E\u785C\u5819\u8DE5\u9857\u677F\u0564" 116 + "\uAF63\uB6FE\uF5B7\u3CA5\uCEE9\u6844\uE04D\u4369" 117 + "\u292E\uAC15\u59A8\u0A9E\u6E47\uDF34\u356A\uCFDC" 118 + "\u22C9\uC09B\u89D4\uEDAB\u12A2\u0D52\uBB02\u2FA9" 119 + "\uD761\u1EB4\u5004\uF6C2\u1625\u8656\u5509\uBE91" }; 120 /** Fixed 8x8 permutation S-boxes */ 121 private static final byte[][] P = new byte[2][256]; // blank final 122 /** 123 * Define the fixed p0/p1 permutations used in keyed S-box lookup. By 124 * changing the following constant definitions, the S-boxes will 125 * automatically get changed in the Twofish engine. 126 */ 127 private static final int P_00 = 1; 128 private static final int P_01 = 0; 129 private static final int P_02 = 0; 130 private static final int P_03 = P_01 ^ 1; 131 private static final int P_04 = 1; 132 private static final int P_10 = 0; 133 private static final int P_11 = 0; 134 private static final int P_12 = 1; 135 private static final int P_13 = P_11 ^ 1; 136 private static final int P_14 = 0; 137 private static final int P_20 = 1; 138 private static final int P_21 = 1; 139 private static final int P_22 = 0; 140 private static final int P_23 = P_21 ^ 1; 141 private static final int P_24 = 0; 142 private static final int P_30 = 0; 143 private static final int P_31 = 1; 144 private static final int P_32 = 1; 145 private static final int P_33 = P_31 ^ 1; 146 private static final int P_34 = 1; 147 /** Primitive polynomial for GF(256) */ 148 private static final int GF256_FDBK_2 = 0x169 / 2; 149 private static final int GF256_FDBK_4 = 0x169 / 4; 150 /** MDS matrix */ 151 private static final int[][] MDS = new int[4][256]; // blank final 152 private static final int RS_GF_FDBK = 0x14D; // field generator 153 /** 154 * KAT vector (from ecb_vk): 155 * I=183 156 * KEY=0000000000000000000000000000000000000000000002000000000000000000 157 * CT=F51410475B33FBD3DB2117B5C17C82D4 158 */ 159 private static final byte[] KAT_KEY = Util.toBytesFromString( 160 "0000000000000000000000000000000000000000000002000000000000000000"); 161 private static final byte[] KAT_CT = 162 Util.toBytesFromString("F51410475B33FBD3DB2117B5C17C82D4"); 163 /** caches the result of the correctness test, once executed. */ 164 private static Boolean valid; 165 static 166 { 167 long time = System.currentTimeMillis(); 168 // expand the P arrays 169 int i; 170 char c; 171 for (i = 0; i < 256; i++) 172 { 173 c = Pm[0].charAt(i >>> 1); 174 P[0][i] = (byte)((i & 1) == 0 ? c >>> 8 : c); 175 c = Pm[1].charAt(i >>> 1); 176 P[1][i] = (byte)((i & 1) == 0 ? c >>> 8 : c); 177 } 178 // precompute the MDS matrix 179 int[] m1 = new int[2]; 180 int[] mX = new int[2]; 181 int[] mY = new int[2]; 182 int j; 183 for (i = 0; i < 256; i++) 184 { 185 j = P[0][i] & 0xFF; // compute all the matrix elements 186 m1[0] = j; 187 mX[0] = Mx_X(j) & 0xFF; 188 mY[0] = Mx_Y(j) & 0xFF; 189 j = P[1][i] & 0xFF; 190 m1[1] = j; 191 mX[1] = Mx_X(j) & 0xFF; 192 mY[1] = Mx_Y(j) & 0xFF; 193 MDS[0][i] = m1[P_00] << 0 194 | mX[P_00] << 8 195 | mY[P_00] << 16 196 | mY[P_00] << 24; 197 MDS[1][i] = mY[P_10] << 0 198 | mY[P_10] << 8 199 | mX[P_10] << 16 200 | m1[P_10] << 24; 201 MDS[2][i] = mX[P_20] << 0 202 | mY[P_20] << 8 203 | m1[P_20] << 16 204 | mY[P_20] << 24; 205 MDS[3][i] = mX[P_30] << 0 206 | m1[P_30] << 8 207 | mY[P_30] << 16 208 | mX[P_30] << 24; 209 } 210 time = System.currentTimeMillis() - time; 211 if (Configuration.DEBUG) 212 { 213 log.fine("Static Data"); 214 log.fine("MDS[0][]:"); 215 StringBuilder sb; 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(MDS[0][i * 4 + j])).append(", "); sb.toString()221 log.fine(sb.toString()); 222 } 223 log.fine("MDS[1][]:"); 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(MDS[1][i * 4 + j])).append(", "); sb.toString()229 log.fine(sb.toString()); 230 } 231 log.fine("MDS[2][]:"); 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(MDS[2][i * 4 + j])).append(", "); sb.toString()237 log.fine(sb.toString()); 238 } 239 log.fine("MDS[3][]:"); 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(MDS[3][i * 4 + j])).append(", "); sb.toString()245 log.fine(sb.toString()); 246 } 247 log.fine("Total initialization time: " + time + " ms."); 248 } 249 } 250 LFSR1(int x)251 private static final int LFSR1(int x) 252 { 253 return (x >> 1) ^ ((x & 0x01) != 0 ? GF256_FDBK_2 : 0); 254 } 255 LFSR2(int x)256 private static final int LFSR2(int x) 257 { 258 return (x >> 2) 259 ^ ((x & 0x02) != 0 ? GF256_FDBK_2 : 0) 260 ^ ((x & 0x01) != 0 ? GF256_FDBK_4 : 0); 261 } 262 Mx_X(int x)263 private static final int Mx_X(int x) 264 { // 5B 265 return x ^ LFSR2(x); 266 } 267 Mx_Y(int x)268 private static final int Mx_Y(int x) 269 { // EF 270 return x ^ LFSR1(x) ^ LFSR2(x); 271 } 272 273 /** Trivial 0-arguments constructor. */ Twofish()274 public Twofish() 275 { 276 super(Registry.TWOFISH_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE); 277 } 278 b0(int x)279 private static final int b0(int x) 280 { 281 return x & 0xFF; 282 } 283 b1(int x)284 private static final int b1(int x) 285 { 286 return (x >>> 8) & 0xFF; 287 } 288 b2(int x)289 private static final int b2(int x) 290 { 291 return (x >>> 16) & 0xFF; 292 } 293 b3(int x)294 private static final int b3(int x) 295 { 296 return (x >>> 24) & 0xFF; 297 } 298 299 /** 300 * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box 32-bit 301 * entity from two key material 32-bit entities. 302 * 303 * @param k0 1st 32-bit entity. 304 * @param k1 2nd 32-bit entity. 305 * @return remainder polynomial generated using RS code 306 */ RS_MDS_Encode(int k0, int k1)307 private static final int RS_MDS_Encode(int k0, int k1) 308 { 309 int r = k1; 310 int i; 311 for (i = 0; i < 4; i++) // shift 1 byte at a time 312 r = RS_rem(r); 313 r ^= k0; 314 for (i = 0; i < 4; i++) 315 r = RS_rem(r); 316 return r; 317 } 318 319 /** 320 * Reed-Solomon code parameters: (12, 8) reversible code:<p> 321 * <pre> 322 * g(x) = x**4 + (a + 1/a) x**3 + a x**2 + (a + 1/a) x + 1 323 * </pre> 324 * where a = primitive root of field generator 0x14D 325 */ RS_rem(int x)326 private static final int RS_rem(int x) 327 { 328 int b = (x >>> 24) & 0xFF; 329 int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xFF; 330 int g3 = (b >>> 1) ^ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0) ^ g2; 331 int result = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b; 332 return result; 333 } 334 F32(int k64Cnt, int x, int[] k32)335 private static final int F32(int k64Cnt, int x, int[] k32) 336 { 337 int b0 = b0(x); 338 int b1 = b1(x); 339 int b2 = b2(x); 340 int b3 = b3(x); 341 int k0 = k32[0]; 342 int k1 = k32[1]; 343 int k2 = k32[2]; 344 int k3 = k32[3]; 345 int result = 0; 346 switch (k64Cnt & 3) 347 { 348 case 1: 349 result = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)] 350 ^ MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)] 351 ^ MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)] 352 ^ MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)]; 353 break; 354 case 0: // same as 4 355 b0 = (P[P_04][b0] & 0xFF) ^ b0(k3); 356 b1 = (P[P_14][b1] & 0xFF) ^ b1(k3); 357 b2 = (P[P_24][b2] & 0xFF) ^ b2(k3); 358 b3 = (P[P_34][b3] & 0xFF) ^ b3(k3); 359 case 3: 360 b0 = (P[P_03][b0] & 0xFF) ^ b0(k2); 361 b1 = (P[P_13][b1] & 0xFF) ^ b1(k2); 362 b2 = (P[P_23][b2] & 0xFF) ^ b2(k2); 363 b3 = (P[P_33][b3] & 0xFF) ^ b3(k2); 364 case 2: // 128-bit keys (optimize for this case) 365 result = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)] 366 ^ MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)] 367 ^ MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)] 368 ^ MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)]; 369 break; 370 } 371 return result; 372 } 373 Fe32(int[] sBox, int x, int R)374 private static final int Fe32(int[] sBox, int x, int R) 375 { 376 return sBox[ 2 * _b(x, R ) ] 377 ^ sBox[ 2 * _b(x, R + 1) + 1] 378 ^ sBox[0x200 + 2 * _b(x, R + 2) ] 379 ^ sBox[0x200 + 2 * _b(x, R + 3) + 1]; 380 } 381 _b(int x, int N)382 private static final int _b(int x, int N) 383 { 384 switch (N % 4) 385 { 386 case 0: 387 return x & 0xFF; 388 case 1: 389 return (x >>> 8) & 0xFF; 390 case 2: 391 return (x >>> 16) & 0xFF; 392 default: 393 return x >>> 24; 394 } 395 } 396 clone()397 public Object clone() 398 { 399 Twofish result = new Twofish(); 400 result.currentBlockSize = this.currentBlockSize; 401 return result; 402 } 403 blockSizes()404 public Iterator blockSizes() 405 { 406 ArrayList al = new ArrayList(); 407 al.add(Integer.valueOf(DEFAULT_BLOCK_SIZE)); 408 return Collections.unmodifiableList(al).iterator(); 409 } 410 keySizes()411 public Iterator keySizes() 412 { 413 ArrayList al = new ArrayList(); 414 al.add(Integer.valueOf(8)); // 64-bit 415 al.add(Integer.valueOf(16)); // 128-bit 416 al.add(Integer.valueOf(24)); // 192-bit 417 al.add(Integer.valueOf(32)); // 256-bit 418 return Collections.unmodifiableList(al).iterator(); 419 } 420 421 /** 422 * Expands a user-supplied key material into a session key for a designated 423 * <i>block size</i>. 424 * 425 * @param k the 64/128/192/256-bit user-key to use. 426 * @param bs the desired block size in bytes. 427 * @return an Object encapsulating the session key. 428 * @exception IllegalArgumentException if the block size is not 16 (128-bit). 429 * @exception InvalidKeyException if the key data is invalid. 430 */ makeKey(byte[] k, int bs)431 public Object makeKey(byte[] k, int bs) throws InvalidKeyException 432 { 433 if (bs != DEFAULT_BLOCK_SIZE) 434 throw new IllegalArgumentException(); 435 if (k == null) 436 throw new InvalidKeyException("Empty key"); 437 int length = k.length; 438 if (! (length == 8 || length == 16 || length == 24 || length == 32)) 439 throw new InvalidKeyException("Incorrect key length"); 440 int k64Cnt = length / 8; 441 int subkeyCnt = ROUND_SUBKEYS + 2 * ROUNDS; 442 int[] k32e = new int[4]; // even 32-bit entities 443 int[] k32o = new int[4]; // odd 32-bit entities 444 int[] sBoxKey = new int[4]; 445 // split user key material into even and odd 32-bit entities and 446 // compute S-box keys using (12, 8) Reed-Solomon code over GF(256) 447 int i, j, offset = 0; 448 for (i = 0, j = k64Cnt - 1; i < 4 && offset < length; i++, j--) 449 { 450 k32e[i] = (k[offset++] & 0xFF) 451 | (k[offset++] & 0xFF) << 8 452 | (k[offset++] & 0xFF) << 16 453 | (k[offset++] & 0xFF) << 24; 454 k32o[i] = (k[offset++] & 0xFF) 455 | (k[offset++] & 0xFF) << 8 456 | (k[offset++] & 0xFF) << 16 457 | (k[offset++] & 0xFF) << 24; 458 sBoxKey[j] = RS_MDS_Encode(k32e[i], k32o[i]); // reverse order 459 } 460 // compute the round decryption subkeys for PHT. these same subkeys 461 // will be used in encryption but will be applied in reverse order. 462 int q, A, B; 463 int[] subKeys = new int[subkeyCnt]; 464 for (i = q = 0; i < subkeyCnt / 2; i++, q += SK_STEP) 465 { 466 A = F32(k64Cnt, q, k32e); // A uses even key entities 467 B = F32(k64Cnt, q + SK_BUMP, k32o); // B uses odd key entities 468 B = B << 8 | B >>> 24; 469 A += B; 470 subKeys[2 * i] = A; // combine with a PHT 471 A += B; 472 subKeys[2 * i + 1] = A << SK_ROTL | A >>> (32 - SK_ROTL); 473 } 474 // fully expand the table for speed 475 int k0 = sBoxKey[0]; 476 int k1 = sBoxKey[1]; 477 int k2 = sBoxKey[2]; 478 int k3 = sBoxKey[3]; 479 int b0, b1, b2, b3; 480 int[] sBox = new int[4 * 256]; 481 for (i = 0; i < 256; i++) 482 { 483 b0 = b1 = b2 = b3 = i; 484 switch (k64Cnt & 3) 485 { 486 case 1: 487 sBox[ 2 * i ] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)]; 488 sBox[ 2 * i + 1] = MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)]; 489 sBox[0x200 + 2 * i ] = MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)]; 490 sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)]; 491 break; 492 case 0: // same as 4 493 b0 = (P[P_04][b0] & 0xFF) ^ b0(k3); 494 b1 = (P[P_14][b1] & 0xFF) ^ b1(k3); 495 b2 = (P[P_24][b2] & 0xFF) ^ b2(k3); 496 b3 = (P[P_34][b3] & 0xFF) ^ b3(k3); 497 case 3: 498 b0 = (P[P_03][b0] & 0xFF) ^ b0(k2); 499 b1 = (P[P_13][b1] & 0xFF) ^ b1(k2); 500 b2 = (P[P_23][b2] & 0xFF) ^ b2(k2); 501 b3 = (P[P_33][b3] & 0xFF) ^ b3(k2); 502 case 2: // 128-bit keys 503 sBox[ 2 * i ] = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) 504 ^ b0(k1)] & 0xFF) ^ b0(k0)]; 505 sBox[ 2 * i + 1] = MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) 506 ^ b1(k1)] & 0xFF) ^ b1(k0)]; 507 sBox[0x200 + 2 * i ] = MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) 508 ^ b2(k1)] & 0xFF) ^ b2(k0)]; 509 sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) 510 ^ b3(k1)] & 0xFF) ^ b3(k0)]; 511 } 512 } 513 if (Configuration.DEBUG) 514 { 515 StringBuilder sb; 516 log.fine("S-box[]:"); 517 for (i = 0; i < 64; i++) 518 { 519 sb = new StringBuilder(); 520 for (j = 0; j < 4; j++) 521 sb.append("0x").append(Util.toString(sBox[i * 4 + j])).append(", "); 522 log.fine(sb.toString()); 523 } 524 log.fine(""); 525 for (i = 0; i < 64; i++) 526 { 527 sb = new StringBuilder(); 528 for (j = 0; j < 4; j++) 529 sb.append("0x").append(Util.toString(sBox[256 + i * 4 + j])).append(", "); 530 log.fine(sb.toString()); 531 } 532 log.fine(""); 533 for (i = 0; i < 64; i++) 534 { 535 sb = new StringBuilder(); 536 for (j = 0; j < 4; j++) 537 sb.append("0x").append(Util.toString(sBox[512 + i * 4 + j])).append(", "); 538 log.fine(sb.toString()); 539 } 540 log.fine(""); 541 for (i = 0; i < 64; i++) 542 { 543 sb = new StringBuilder(); 544 for (j = 0; j < 4; j++) 545 sb.append("0x").append(Util.toString(sBox[768 + i * 4 + j])).append(", "); 546 log.fine(sb.toString()); 547 } 548 log.fine("User (odd, even) keys --> S-Box keys:"); 549 for (i = 0; i < k64Cnt; i++) 550 log.fine("0x" + Util.toString(k32o[i]) 551 + " 0x" + Util.toString(k32e[i]) 552 + " --> 0x" + Util.toString(sBoxKey[k64Cnt - 1 - i])); 553 log.fine("Round keys:"); 554 for (i = 0; i < ROUND_SUBKEYS + 2 * ROUNDS; i += 2) 555 log.fine("0x" + Util.toString(subKeys[i]) 556 + " 0x" + Util.toString(subKeys[i + 1])); 557 } 558 return new Object[] { sBox, subKeys }; 559 } 560 encrypt(byte[] in, int inOffset, byte[] out, int outOffset, Object sessionKey, int bs)561 public void encrypt(byte[] in, int inOffset, byte[] out, int outOffset, 562 Object sessionKey, int bs) 563 { 564 if (bs != DEFAULT_BLOCK_SIZE) 565 throw new IllegalArgumentException(); 566 Object[] sk = (Object[]) sessionKey; // extract S-box and session key 567 int[] sBox = (int[]) sk[0]; 568 int[] sKey = (int[]) sk[1]; 569 if (Configuration.DEBUG) 570 log.fine("PT=" + Util.toString(in, inOffset, bs)); 571 int x0 = (in[inOffset++] & 0xFF) 572 | (in[inOffset++] & 0xFF) << 8 573 | (in[inOffset++] & 0xFF) << 16 574 | (in[inOffset++] & 0xFF) << 24; 575 int x1 = (in[inOffset++] & 0xFF) 576 | (in[inOffset++] & 0xFF) << 8 577 | (in[inOffset++] & 0xFF) << 16 578 | (in[inOffset++] & 0xFF) << 24; 579 int x2 = (in[inOffset++] & 0xFF) 580 | (in[inOffset++] & 0xFF) << 8 581 | (in[inOffset++] & 0xFF) << 16 582 | (in[inOffset++] & 0xFF) << 24; 583 int x3 = (in[inOffset++] & 0xFF) 584 | (in[inOffset++] & 0xFF) << 8 585 | (in[inOffset++] & 0xFF) << 16 586 | (in[inOffset++] & 0xFF) << 24; 587 x0 ^= sKey[INPUT_WHITEN]; 588 x1 ^= sKey[INPUT_WHITEN + 1]; 589 x2 ^= sKey[INPUT_WHITEN + 2]; 590 x3 ^= sKey[INPUT_WHITEN + 3]; 591 if (Configuration.DEBUG) 592 log.fine("PTw=" + Util.toString(x0) + Util.toString(x1) 593 + Util.toString(x2) + Util.toString(x3)); 594 int t0, t1; 595 int k = ROUND_SUBKEYS; 596 for (int R = 0; R < ROUNDS; R += 2) 597 { 598 t0 = Fe32(sBox, x0, 0); 599 t1 = Fe32(sBox, x1, 3); 600 x2 ^= t0 + t1 + sKey[k++]; 601 x2 = x2 >>> 1 | x2 << 31; 602 x3 = x3 << 1 | x3 >>> 31; 603 x3 ^= t0 + 2 * t1 + sKey[k++]; 604 if (Configuration.DEBUG) 605 log.fine("CT" + (R) + "=" + Util.toString(x0) + Util.toString(x1) 606 + Util.toString(x2) + Util.toString(x3)); 607 t0 = Fe32(sBox, x2, 0); 608 t1 = Fe32(sBox, x3, 3); 609 x0 ^= t0 + t1 + sKey[k++]; 610 x0 = x0 >>> 1 | x0 << 31; 611 x1 = x1 << 1 | x1 >>> 31; 612 x1 ^= t0 + 2 * t1 + sKey[k++]; 613 if (Configuration.DEBUG) 614 log.fine("CT" + (R + 1) + "=" + Util.toString(x0) + Util.toString(x1) 615 + Util.toString(x2) + Util.toString(x3)); 616 } 617 x2 ^= sKey[OUTPUT_WHITEN]; 618 x3 ^= sKey[OUTPUT_WHITEN + 1]; 619 x0 ^= sKey[OUTPUT_WHITEN + 2]; 620 x1 ^= sKey[OUTPUT_WHITEN + 3]; 621 if (Configuration.DEBUG) 622 log.fine("CTw=" + Util.toString(x0) + Util.toString(x1) 623 + Util.toString(x2) + Util.toString(x3)); 624 out[outOffset++] = (byte) x2; 625 out[outOffset++] = (byte)(x2 >>> 8); 626 out[outOffset++] = (byte)(x2 >>> 16); 627 out[outOffset++] = (byte)(x2 >>> 24); 628 out[outOffset++] = (byte) x3; 629 out[outOffset++] = (byte)(x3 >>> 8); 630 out[outOffset++] = (byte)(x3 >>> 16); 631 out[outOffset++] = (byte)(x3 >>> 24); 632 out[outOffset++] = (byte) x0; 633 out[outOffset++] = (byte)(x0 >>> 8); 634 out[outOffset++] = (byte)(x0 >>> 16); 635 out[outOffset++] = (byte)(x0 >>> 24); 636 out[outOffset++] = (byte) x1; 637 out[outOffset++] = (byte)(x1 >>> 8); 638 out[outOffset++] = (byte)(x1 >>> 16); 639 out[outOffset ] = (byte)(x1 >>> 24); 640 if (Configuration.DEBUG) 641 log.fine("CT=" + Util.toString(out, outOffset - 15, 16) + "\n"); 642 } 643 decrypt(byte[] in, int inOffset, byte[] out, int outOffset, Object sessionKey, int bs)644 public void decrypt(byte[] in, int inOffset, byte[] out, int outOffset, 645 Object sessionKey, int bs) 646 { 647 if (bs != DEFAULT_BLOCK_SIZE) 648 throw new IllegalArgumentException(); 649 Object[] sk = (Object[]) sessionKey; // extract S-box and session key 650 int[] sBox = (int[]) sk[0]; 651 int[] sKey = (int[]) sk[1]; 652 if (Configuration.DEBUG) 653 log.fine("CT=" + Util.toString(in, inOffset, bs)); 654 int x2 = (in[inOffset++] & 0xFF) 655 | (in[inOffset++] & 0xFF) << 8 656 | (in[inOffset++] & 0xFF) << 16 657 | (in[inOffset++] & 0xFF) << 24; 658 int x3 = (in[inOffset++] & 0xFF) 659 | (in[inOffset++] & 0xFF) << 8 660 | (in[inOffset++] & 0xFF) << 16 661 | (in[inOffset++] & 0xFF) << 24; 662 int x0 = (in[inOffset++] & 0xFF) 663 | (in[inOffset++] & 0xFF) << 8 664 | (in[inOffset++] & 0xFF) << 16 665 | (in[inOffset++] & 0xFF) << 24; 666 int x1 = (in[inOffset++] & 0xFF) 667 | (in[inOffset++] & 0xFF) << 8 668 | (in[inOffset++] & 0xFF) << 16 669 | (in[inOffset++] & 0xFF) << 24; 670 x2 ^= sKey[OUTPUT_WHITEN]; 671 x3 ^= sKey[OUTPUT_WHITEN + 1]; 672 x0 ^= sKey[OUTPUT_WHITEN + 2]; 673 x1 ^= sKey[OUTPUT_WHITEN + 3]; 674 if (Configuration.DEBUG) 675 log.fine("CTw=" + Util.toString(x2) + Util.toString(x3) 676 + Util.toString(x0) + Util.toString(x1)); 677 int k = ROUND_SUBKEYS + 2 * ROUNDS - 1; 678 int t0, t1; 679 for (int R = 0; R < ROUNDS; R += 2) 680 { 681 t0 = Fe32(sBox, x2, 0); 682 t1 = Fe32(sBox, x3, 3); 683 x1 ^= t0 + 2 * t1 + sKey[k--]; 684 x1 = x1 >>> 1 | x1 << 31; 685 x0 = x0 << 1 | x0 >>> 31; 686 x0 ^= t0 + t1 + sKey[k--]; 687 if (Configuration.DEBUG) 688 log.fine("PT" + (ROUNDS - R) + "=" + Util.toString(x2) 689 + Util.toString(x3) + Util.toString(x0) + Util.toString(x1)); 690 t0 = Fe32(sBox, x0, 0); 691 t1 = Fe32(sBox, x1, 3); 692 x3 ^= t0 + 2 * t1 + sKey[k--]; 693 x3 = x3 >>> 1 | x3 << 31; 694 x2 = x2 << 1 | x2 >>> 31; 695 x2 ^= t0 + t1 + sKey[k--]; 696 if (Configuration.DEBUG) 697 log.fine("PT" + (ROUNDS - R - 1) + "=" + Util.toString(x2) 698 + Util.toString(x3) + Util.toString(x0) + Util.toString(x1)); 699 } 700 x0 ^= sKey[INPUT_WHITEN]; 701 x1 ^= sKey[INPUT_WHITEN + 1]; 702 x2 ^= sKey[INPUT_WHITEN + 2]; 703 x3 ^= sKey[INPUT_WHITEN + 3]; 704 if (Configuration.DEBUG) 705 log.fine("PTw=" + Util.toString(x2) + Util.toString(x3) 706 + Util.toString(x0) + Util.toString(x1)); 707 out[outOffset++] = (byte) x0; 708 out[outOffset++] = (byte)(x0 >>> 8); 709 out[outOffset++] = (byte)(x0 >>> 16); 710 out[outOffset++] = (byte)(x0 >>> 24); 711 out[outOffset++] = (byte) x1; 712 out[outOffset++] = (byte)(x1 >>> 8); 713 out[outOffset++] = (byte)(x1 >>> 16); 714 out[outOffset++] = (byte)(x1 >>> 24); 715 out[outOffset++] = (byte) x2; 716 out[outOffset++] = (byte)(x2 >>> 8); 717 out[outOffset++] = (byte)(x2 >>> 16); 718 out[outOffset++] = (byte)(x2 >>> 24); 719 out[outOffset++] = (byte) x3; 720 out[outOffset++] = (byte)(x3 >>> 8); 721 out[outOffset++] = (byte)(x3 >>> 16); 722 out[outOffset ] = (byte)(x3 >>> 24); 723 if (Configuration.DEBUG) 724 log.fine("PT=" + Util.toString(out, outOffset - 15, 16) + "\n"); 725 } 726 selfTest()727 public boolean selfTest() 728 { 729 if (valid == null) 730 { 731 boolean result = super.selfTest(); // do symmetry tests 732 if (result) 733 result = testKat(KAT_KEY, KAT_CT); 734 valid = Boolean.valueOf(result); 735 } 736 return valid.booleanValue(); 737 } 738 } 739