c2a7cce93b0fba61ba627f871bf3b766b1b73367
[platform/upstream/gcc48.git] / libjava / classpath / gnu / javax / crypto / cipher / Anubis.java
1 /* Anubis.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  * Anubis is a 128-bit block cipher that accepts a variable-length key. The
53  * cipher is a uniform substitution-permutation network whose inverse only
54  * differs from the forward operation in the key schedule. The design of both
55  * the round transformation and the key schedule is based upon the Wide Trail
56  * strategy and permits a wide variety of implementation trade-offs.
57  * <p>
58  * References:
59  * <ol>
60  * <li><a
61  * href="http://planeta.terra.com.br/informatica/paulobarreto/AnubisPage.html">The
62  * ANUBIS Block Cipher</a>.<br>
63  * <a href="mailto:paulo.barreto@terra.com.br">Paulo S.L.M. Barreto</a> and <a
64  * href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a>.</li>
65  * </ol>
66  */
67 public final class Anubis
68     extends BaseCipher
69 {
70   private static final Logger log = Configuration.DEBUG ?
71                         Logger.getLogger(Anubis.class.getName()) : null;
72   private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes
73   private static final int DEFAULT_KEY_SIZE = 16; // in bytes
74   private static final String Sd = // p. 25 [ANUBIS]
75       "\uBA54\u2F74\u53D3\uD24D\u50AC\u8DBF\u7052\u9A4C"
76     + "\uEAD5\u97D1\u3351\u5BA6\uDE48\uA899\uDB32\uB7FC"
77     + "\uE39E\u919B\uE2BB\u416E\uA5CB\u6B95\uA1F3\uB102"
78     + "\uCCC4\u1D14\uC363\uDA5D\u5FDC\u7DCD\u7F5A\u6C5C"
79     + "\uF726\uFFED\uE89D\u6F8E\u19A0\uF089\u0F07\uAFFB"
80     + "\u0815\u0D04\u0164\uDF76\u79DD\u3D16\u3F37\u6D38"
81     + "\uB973\uE935\u5571\u7B8C\u7288\uF62A\u3E5E\u2746"
82     + "\u0C65\u6861\u03C1\u57D6\uD958\uD866\uD73A\uC83C"
83     + "\uFA96\uA798\uECB8\uC7AE\u694B\uABA9\u670A\u47F2"
84     + "\uB522\uE5EE\uBE2B\u8112\u831B\u0E23\uF545\u21CE"
85     + "\u492C\uF9E6\uB628\u1782\u1A8B\uFE8A\u09C9\u874E"
86     + "\uE12E\uE4E0\uEB90\uA41E\u8560\u0025\uF4F1\u940B"
87     + "\uE775\uEF34\u31D4\uD086\u7EAD\uFD29\u303B\u9FF8"
88     + "\uC613\u0605\uC511\u777C\u7A78\u361C\u3959\u1856"
89     + "\uB3B0\u2420\uB292\uA3C0\u4462\u10B4\u8443\u93C2"
90     + "\u4ABD\u8F2D\uBC9C\u6A40\uCFA2\u804F\u1FCA\uAA42";
91   private static final byte[] S = new byte[256];
92   private static final int[] T0 = new int[256];
93   private static final int[] T1 = new int[256];
94   private static final int[] T2 = new int[256];
95   private static final int[] T3 = new int[256];
96   private static final int[] T4 = new int[256];
97   private static final int[] T5 = new int[256];
98   /**
99    * Anubis round constants. This is the largest possible considering that we
100    * always use R values, R = 8 + N, and 4 &lt;= N &lt;= 10.
101    */
102   private static final int[] rc = new int[18];
103   /**
104    * KAT vector (from ecb_vk): I=83
105    * KEY=000000000000000000002000000000000000000000000000
106    * CT=2E66AB15773F3D32FB6C697509460DF4
107    */
108   private static final byte[] KAT_KEY =
109       Util.toBytesFromString("000000000000000000002000000000000000000000000000");
110   private static final byte[] KAT_CT =
111       Util.toBytesFromString("2E66AB15773F3D32FB6C697509460DF4");
112   /** caches the result of the correctness test, once executed. */
113   private static Boolean valid;
114
115   static
116     {
117       long time = System.currentTimeMillis();
118       int ROOT = 0x11d; // para. 2.1 [ANUBIS]
119       int i, s, s2, s4, s6, s8, t;
120       char c;
121       for (i = 0; i < 256; i++)
122         {
123           c = Sd.charAt(i >>> 1);
124           s = ((i & 1) == 0 ? c >>> 8 : c) & 0xFF;
125           S[i] = (byte) s;
126           s2 = s << 1;
127           if (s2 > 0xFF)
128             s2 ^= ROOT;
129           s4 = s2 << 1;
130           if (s4 > 0xFF)
131             s4 ^= ROOT;
132           s6 = s4 ^ s2;
133           s8 = s4 << 1;
134           if (s8 > 0xFF)
135             s8 ^= ROOT;
136           T0[i] = s  << 24 | s2 << 16 | s4 << 8 | s6;
137           T1[i] = s2 << 24 | s  << 16 | s6 << 8 | s4;
138           T2[i] = s4 << 24 | s6 << 16 | s  << 8 | s2;
139           T3[i] = s6 << 24 | s4 << 16 | s2 << 8 | s;
140           T4[i] = s  << 24 | s  << 16 | s  << 8 | s;
141           T5[s] = s  << 24 | s2 << 16 | s6 << 8 | s8;
142         }
143       // compute round constant
144       for (i = 0, s = 0; i < 18;)
145         rc[i++] =  S[(s++) & 0xFF]         << 24
146                 | (S[(s++) & 0xFF] & 0xFF) << 16
147                 | (S[(s++) & 0xFF] & 0xFF) << 8
148                 | (S[(s++) & 0xFF] & 0xFF);
149       time = System.currentTimeMillis() - time;
150       if (Configuration.DEBUG)
151         {
152           log.fine("Static data");
153           log.fine("T0[]:");
154           StringBuilder sb;
155           for (i = 0; i < 64; i++)
156             {
157               sb = new StringBuilder();
158               for (t = 0; t < 4; t++)
159                 sb.append("0x").append(Util.toString(T0[i * 4 + t])).append(", ");
160               log.fine(sb.toString());
161             }
162           log.fine("T1[]:");
163           for (i = 0; i < 64; i++)
164             {
165               sb = new StringBuilder();
166               for (t = 0; t < 4; t++)
167                 sb.append("0x").append(Util.toString(T1[i * 4 + t])).append(", ");
168               log.fine(sb.toString());
169             }
170           log.fine("T2[]:");
171           for (i = 0; i < 64; i++)
172             {
173               sb = new StringBuilder();
174               for (t = 0; t < 4; t++)
175                 sb.append("0x").append(Util.toString(T2[i * 4 + t])).append(", ");
176               log.fine(sb.toString());
177             }
178           log.fine("T3[]:");
179           for (i = 0; i < 64; i++)
180             {
181               sb = new StringBuilder();
182               for (t = 0; t < 4; t++)
183                 sb.append("0x").append(Util.toString(T3[i * 4 + t])).append(", ");
184               log.fine(sb.toString());
185             }
186           log.fine("T4[]:");
187           for (i = 0; i < 64; i++)
188             {
189               sb = new StringBuilder();
190               for (t = 0; t < 4; t++)
191                 sb.append("0x").append(Util.toString(T4[i * 4 + t])).append(", ");
192               log.fine(sb.toString());
193             }
194           log.fine("T5[]:");
195           for (i = 0; i < 64; i++)
196             {
197               sb = new StringBuilder();
198               for (t = 0; t < 4; t++)
199                 sb.append("0x").append(Util.toString(T5[i * 4 + t])).append(", ");
200               log.fine(sb.toString());
201             }
202           log.fine("rc[]:");
203           for (i = 0; i < 18; i++)
204             log.fine("0x" + Util.toString(rc[i]));
205           log.fine("Total initialization time: " + time + " ms.");
206         }
207     }
208
209   /** Trivial 0-arguments constructor. */
210   public Anubis()
211   {
212     super(Registry.ANUBIS_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
213   }
214
215   private static void anubis(byte[] in, int i, byte[] out, int j, int[][] K)
216   {
217     // extract encryption round keys
218     int R = K.length - 1;
219     int[] Ker = K[0];
220     // mu function + affine key addition
221     int a0 = (in[i++]         << 24
222            | (in[i++] & 0xFF) << 16
223            | (in[i++] & 0xFF) <<  8
224            | (in[i++] & 0xFF)      ) ^ Ker[0];
225     int a1 = (in[i++]         << 24
226            | (in[i++] & 0xFF) << 16
227            | (in[i++] & 0xFF) <<  8
228            | (in[i++] & 0xFF)      ) ^ Ker[1];
229     int a2 = (in[i++]         << 24
230            | (in[i++] & 0xFF) << 16
231            | (in[i++] & 0xFF) <<  8
232            | (in[i++] & 0xFF)      ) ^ Ker[2];
233     int a3 = (in[i++]         << 24
234            | (in[i++] & 0xFF) << 16
235            | (in[i++] & 0xFF) <<  8
236            | (in[i] & 0xFF)        ) ^ Ker[3];
237     int b0, b1, b2, b3;
238     // round function
239     for (int r = 1; r < R; r++)
240       {
241         Ker = K[r];
242         b0 = T0[ a0 >>> 24        ]
243            ^ T1[ a1 >>> 24        ]
244            ^ T2[ a2 >>> 24        ]
245            ^ T3[ a3 >>> 24        ] ^ Ker[0];
246         b1 = T0[(a0 >>> 16) & 0xFF]
247            ^ T1[(a1 >>> 16) & 0xFF]
248            ^ T2[(a2 >>> 16) & 0xFF]
249            ^ T3[(a3 >>> 16) & 0xFF] ^ Ker[1];
250         b2 = T0[(a0 >>>  8) & 0xFF]
251            ^ T1[(a1 >>>  8) & 0xFF]
252            ^ T2[(a2 >>>  8) & 0xFF]
253            ^ T3[(a3 >>>  8) & 0xFF] ^ Ker[2];
254         b3 = T0[ a0         & 0xFF]
255            ^ T1[ a1         & 0xFF]
256            ^ T2[ a2         & 0xFF]
257            ^ T3[ a3         & 0xFF] ^ Ker[3];
258         a0 = b0;
259         a1 = b1;
260         a2 = b2;
261         a3 = b3;
262         if (Configuration.DEBUG)
263           log.fine("T" + r + "=" + Util.toString(a0) + Util.toString(a1)
264                    + Util.toString(a2) + Util.toString(a3));
265       }
266     // last round function
267     Ker = K[R];
268     int tt = Ker[0];
269     out[j++] = (byte)(S[ a0 >>> 24        ] ^ (tt >>> 24));
270     out[j++] = (byte)(S[ a1 >>> 24        ] ^ (tt >>> 16));
271     out[j++] = (byte)(S[ a2 >>> 24        ] ^ (tt >>> 8));
272     out[j++] = (byte)(S[ a3 >>> 24        ] ^  tt);
273     tt = Ker[1];
274     out[j++] = (byte)(S[(a0 >>> 16) & 0xFF] ^ (tt >>> 24));
275     out[j++] = (byte)(S[(a1 >>> 16) & 0xFF] ^ (tt >>> 16));
276     out[j++] = (byte)(S[(a2 >>> 16) & 0xFF] ^ (tt >>> 8));
277     out[j++] = (byte)(S[(a3 >>> 16) & 0xFF] ^  tt);
278     tt = Ker[2];
279     out[j++] = (byte)(S[(a0 >>>  8) & 0xFF] ^ (tt >>> 24));
280     out[j++] = (byte)(S[(a1 >>>  8) & 0xFF] ^ (tt >>> 16));
281     out[j++] = (byte)(S[(a2 >>>  8) & 0xFF] ^ (tt >>> 8));
282     out[j++] = (byte)(S[(a3 >>>  8) & 0xFF] ^  tt);
283     tt = Ker[3];
284     out[j++] = (byte)(S[ a0         & 0xFF] ^ (tt >>> 24));
285     out[j++] = (byte)(S[ a1         & 0xFF] ^ (tt >>> 16));
286     out[j++] = (byte)(S[ a2         & 0xFF] ^ (tt >>> 8));
287     out[j  ] = (byte)(S[ a3         & 0xFF] ^  tt);
288     if (Configuration.DEBUG)
289       log.fine("T=" + Util.toString(out, j - 15, 16) + "\n");
290   }
291
292   public Object clone()
293   {
294     Anubis result = new Anubis();
295     result.currentBlockSize = this.currentBlockSize;
296
297     return result;
298   }
299
300   public Iterator blockSizes()
301   {
302     ArrayList al = new ArrayList();
303     al.add(Integer.valueOf(DEFAULT_BLOCK_SIZE));
304
305     return Collections.unmodifiableList(al).iterator();
306   }
307
308   public Iterator keySizes()
309   {
310     ArrayList al = new ArrayList();
311     for (int n = 4; n < 10; n++)
312       al.add(Integer.valueOf(n * 32 / 8));
313     return Collections.unmodifiableList(al).iterator();
314   }
315
316   /**
317    * Expands a user-supplied key material into a session key for a designated
318    * <i>block size</i>.
319    *
320    * @param uk the 32N-bit user-supplied key material; 4 &lt;= N &lt;= 10.
321    * @param bs the desired block size in bytes.
322    * @return an Object encapsulating the session key.
323    * @exception IllegalArgumentException if the block size is not 16 (128-bit).
324    * @exception InvalidKeyException if the key data is invalid.
325    */
326   public Object makeKey(byte[] uk, int bs) throws InvalidKeyException
327   {
328     if (bs != DEFAULT_BLOCK_SIZE)
329       throw new IllegalArgumentException();
330     if (uk == null)
331       throw new InvalidKeyException("Empty key");
332     if ((uk.length % 4) != 0)
333       throw new InvalidKeyException("Key is not multiple of 32-bit.");
334     int N = uk.length / 4;
335     if (N < 4 || N > 10)
336       throw new InvalidKeyException("Key is not 32N; 4 <= N <= 10");
337     int R = 8 + N;
338     int[][] Ke = new int[R + 1][4]; // encryption round keys
339     int[][] Kd = new int[R + 1][4]; // decryption round keys
340     int[] tk = new int[N];
341     int[] kk = new int[N];
342     int r, i, j, k, k0, k1, k2, k3, tt;
343     // apply mu to k0
344     for (r = 0, i = 0; r < N;)
345       tk[r++] =  uk[i++]         << 24
346               | (uk[i++] & 0xFF) << 16
347               | (uk[i++] & 0xFF) << 8
348               | (uk[i++] & 0xFF);
349     for (r = 0; r <= R; r++)
350       {
351         if (r > 0)
352           {
353             // psi = key evolution function
354             kk[0] = T0[(tk[0    ] >>> 24)       ]
355                   ^ T1[(tk[N - 1] >>> 16) & 0xFF]
356                   ^ T2[(tk[N - 2] >>>  8) & 0xFF]
357                   ^ T3[ tk[N - 3]         & 0xFF];
358             kk[1] = T0[(tk[1    ] >>> 24)       ]
359                   ^ T1[(tk[0    ] >>> 16) & 0xFF]
360                   ^ T2[(tk[N - 1] >>>  8) & 0xFF]
361                   ^ T3[ tk[N - 2]         & 0xFF];
362             kk[2] = T0[(tk[2    ] >>> 24)       ]
363                   ^ T1[(tk[1    ] >>> 16) & 0xFF]
364                   ^ T2[(tk[0    ] >>>  8) & 0xFF]
365                   ^ T3[ tk[N - 1]         & 0xFF];
366             kk[3] = T0[(tk[3    ] >>> 24)       ]
367                   ^ T1[(tk[2    ] >>> 16) & 0xFF]
368                   ^ T2[(tk[1    ] >>>  8) & 0xFF]
369                   ^ T3[ tk[0    ]         & 0xFF];
370             for (i = 4; i < N; i++)
371               kk[i] = T0[ tk[i    ] >>> 24        ]
372                     ^ T1[(tk[i - 1] >>> 16) & 0xFF]
373                     ^ T2[(tk[i - 2] >>>  8) & 0xFF]
374                     ^ T3[ tk[i - 3]         & 0xFF];
375             // apply sigma (affine addition) to round constant
376             tk[0] = rc[r - 1] ^ kk[0];
377             for (i = 1; i < N; i++)
378               tk[i] = kk[i];
379           }
380         // phi = key selection function
381         tt = tk[N - 1];
382         k0 = T4[ tt >>> 24        ];
383         k1 = T4[(tt >>> 16) & 0xFF];
384         k2 = T4[(tt >>>  8) & 0xFF];
385         k3 = T4[ tt         & 0xFF];
386         for (k = N - 2; k >= 0; k--)
387           {
388             tt = tk[k];
389             k0 =  T4[ tt >>> 24        ]
390                ^ (T5[(k0 >>> 24) & 0xFF] & 0xFF000000)
391                ^ (T5[(k0 >>> 16) & 0xFF] & 0x00FF0000)
392                ^ (T5[(k0 >>>  8) & 0xFF] & 0x0000FF00)
393                ^ (T5 [k0         & 0xFF] & 0x000000FF);
394             k1 =  T4[(tt >>> 16) & 0xFF]
395                ^ (T5[(k1 >>> 24) & 0xFF] & 0xFF000000)
396                ^ (T5[(k1 >>> 16) & 0xFF] & 0x00FF0000)
397                ^ (T5[(k1 >>>  8) & 0xFF] & 0x0000FF00)
398                ^ (T5[ k1         & 0xFF] & 0x000000FF);
399             k2 =  T4[(tt >>>  8) & 0xFF]
400                ^ (T5[(k2 >>> 24) & 0xFF] & 0xFF000000)
401                ^ (T5[(k2 >>> 16) & 0xFF] & 0x00FF0000)
402                ^ (T5[(k2 >>>  8) & 0xFF] & 0x0000FF00)
403                ^ (T5[ k2         & 0xFF] & 0x000000FF);
404             k3 =  T4[ tt         & 0xFF]
405                ^ (T5[(k3 >>> 24) & 0xFF] & 0xFF000000)
406                ^ (T5[(k3 >>> 16) & 0xFF] & 0x00FF0000)
407                ^ (T5[(k3 >>>  8) & 0xFF] & 0x0000FF00)
408                ^ (T5[ k3         & 0xFF] & 0x000000FF);
409           }
410         Ke[r][0] = k0;
411         Ke[r][1] = k1;
412         Ke[r][2] = k2;
413         Ke[r][3] = k3;
414         if (r == 0 || r == R)
415           {
416             Kd[R - r][0] = k0;
417             Kd[R - r][1] = k1;
418             Kd[R - r][2] = k2;
419             Kd[R - r][3] = k3;
420           }
421         else
422           {
423             Kd[R - r][0] = T0[S[ k0 >>> 24        ] & 0xFF]
424                          ^ T1[S[(k0 >>> 16) & 0xFF] & 0xFF]
425                          ^ T2[S[(k0 >>>  8) & 0xFF] & 0xFF]
426                          ^ T3[S[ k0         & 0xFF] & 0xFF];
427             Kd[R - r][1] = T0[S[ k1 >>> 24        ] & 0xFF]
428                          ^ T1[S[(k1 >>> 16) & 0xFF] & 0xFF]
429                          ^ T2[S[(k1 >>>  8) & 0xFF] & 0xFF]
430                          ^ T3[S[ k1         & 0xFF] & 0xFF];
431             Kd[R - r][2] = T0[S[ k2 >>> 24        ] & 0xFF]
432                          ^ T1[S[(k2 >>> 16) & 0xFF] & 0xFF]
433                          ^ T2[S[(k2 >>>  8) & 0xFF] & 0xFF]
434                          ^ T3[S[ k2         & 0xFF] & 0xFF];
435             Kd[R - r][3] = T0[S[ k3 >>> 24        ] & 0xFF]
436                          ^ T1[S[(k3 >>> 16) & 0xFF] & 0xFF]
437                          ^ T2[S[(k3 >>>  8) & 0xFF] & 0xFF]
438                          ^ T3[S[ k3         & 0xFF] & 0xFF];
439           }
440       }
441     if (Configuration.DEBUG)
442       {
443         log.fine("Key schedule");
444         log.fine("Ke[]:");
445         StringBuilder sb;
446         for (r = 0; r < R + 1; r++)
447           {
448             sb = new StringBuilder("#").append(r).append(": ");
449             for (j = 0; j < 4; j++)
450               sb.append("0x").append(Util.toString(Ke[r][j])).append(", ");
451             log.fine(sb.toString());
452           }
453         log.fine("Kd[]:");
454         for (r = 0; r < R + 1; r++)
455           {
456             sb = new StringBuilder("#").append(r).append(": ");
457             for (j = 0; j < 4; j++)
458               sb.append("0x").append(Util.toString(Kd[r][j])).append(", ");
459             log.fine(sb.toString());
460           }
461       }
462     return new Object[] { Ke, Kd };
463   }
464
465   public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
466   {
467     if (bs != DEFAULT_BLOCK_SIZE)
468       throw new IllegalArgumentException();
469     int[][] K = (int[][])((Object[]) k)[0];
470     anubis(in, i, out, j, K);
471   }
472
473   public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
474   {
475     if (bs != DEFAULT_BLOCK_SIZE)
476       throw new IllegalArgumentException();
477     int[][] K = (int[][])((Object[]) k)[1];
478     anubis(in, i, out, j, K);
479   }
480
481   public boolean selfTest()
482   {
483     if (valid == null)
484       {
485         boolean result = super.selfTest(); // do symmetry tests
486         if (result)
487           result = testKat(KAT_KEY, KAT_CT);
488         valid = Boolean.valueOf(result);
489       }
490     return valid.booleanValue();
491   }
492 }