OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [crypto/] [cipher/] [Twofish.java] - Blame information for rev 769

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.