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