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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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