001: /*
002: *
003: *
004: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
005: * Reserved. Use is subject to license terms.
006: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License version
010: * 2 only, as published by the Free Software Foundation.
011: *
012: * This program is distributed in the hope that it will be useful, but
013: * WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * General Public License version 2 for more details (a copy is
016: * included at /legal/license.txt).
017: *
018: * You should have received a copy of the GNU General Public License
019: * version 2 along with this work; if not, write to the Free Software
020: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
021: * 02110-1301 USA
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
024: * Clara, CA 95054 or visit www.sun.com if you need additional
025: * information or have any questions.
026: *
027: * Copyright (c) 1995-2005 The Cryptix Foundation Limited.
028: * All rights reserved.
029: *
030: * Redistribution and use in source and binary forms, with or without
031: * modification, are permitted provided that the following conditions are
032: * met:
033: *
034: * 1. Redistributions of source code must retain the copyright notice,
035: * this list of conditions and the following disclaimer.
036: * 2. Redistributions in binary form must reproduce the above copyright
037: * notice, this list of conditions and the following disclaimer in
038: * the documentation and/or other materials provided with the
039: * distribution.
040: *
041: * THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED AND
042: * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
043: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
044: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
045: * IN NO EVENT SHALL THE CRYPTIX FOUNDATION LIMITED OR CONTRIBUTORS BE
046: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
047: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
048: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
049: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
050: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
051: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
052: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
053: */
054:
055: package com.sun.midp.crypto;
056:
057: /**
058: * This class is an implementation of AES cipher in ECB mode.
059: */
060: public class AES_ECB extends BlockCipherBase {
061:
062: /** Substitution values. */
063: private static final byte[] SBox = Util
064: .unpackBytes("c|w{rkoE0\001g+~W+vJ\002I}zYGp-T\042/\034$r@7}\023&6?wL4%"
065: + "eqqX1\025\004G#C\030\026\005\032\007\022\000bk'2u\011\003"
066: + ",\032\033nZ\040R;V3)c/\004SQ\000m\040|1[jK>9JLXOPo*{CM3"
067: + "\005Ey\002P<\037(Q#@\017\022\0358u<6Z!\020sRM\014\023l_"
068: + "\027D\027D'~=d]\031s`\001O\134\042*\020\010Fn8\024^^\013["
069: + "`2:\012I\006$\134BS,b\021\025dygH7m\015UN)lVtjez.\010:x%."
070: + "\034&4Fh]t\037K=\013\012p>5fH\003v\016a5W9\006A\035\036ax"
071: + "\030\021iY\016\024\033\036\007iNU(_\014!\011\015?fBhA\031"
072: + "-\0170T;\026\020a]|{X\013U\134\0042Ufp#a:O'\031\040Ye\000"
073: + "wf2\012>\034\021\134g;^\021\005");
074:
075: /** Inverse substitution table. */
076: private static final byte[] ISBox;
077:
078: static {
079: ISBox = new byte[256];
080: for (int i = 0; i < 256; i++) {
081: ISBox[SBox[i] & 0xff] = (byte) i;
082: }
083: }
084:
085: /** Precalculated table for matrix multiplication. */
086: private int[] SB0;
087: /** Precalculated table for matrix multiplication. */
088: private int[] SB1;
089: /** Precalculated table for matrix multiplication. */
090: private int[] SB2;
091: /** Precalculated table for matrix multiplication. */
092: private int[] SB3;
093:
094: /**
095: * Round constants.
096: */
097: private static final byte[] Rcon = Util
098: .unpackBytes("\000\001\002\004\010\020\040@\000\0336l\000\002");
099:
100: /** AES ciphers encrypt/decrypt in block size of 16 bytes. */
101: static final int BLOCK_SIZE = 16;
102:
103: /** Number of columns (32-bit words) comprising the state. */
104: private static final int Nb = 4;
105:
106: /**
107: * Number of 32-bit words comprising the key (4, 6, 8 for 128, 192
108: * and 256 bits).
109: */
110: private int Nk;
111:
112: /** Number of rounds (10, 12, 14). */
113: private int Nr;
114:
115: /**
116: * Key Schedule. Length depends on Block and Key length.
117: * Block length = 128 bits or 16 bytes. For 128 bit key
118: * W.length = Nb * (Nr + 1) == 4(10 + 1) = 44 Words = 44 * 4 bytes =
119: * 176 bytes
120: */
121: private int[] W;
122:
123: /** Internal buffer. */
124: protected byte[] state;
125:
126: /**
127: * Constructor.
128: */
129: public AES_ECB() {
130: super (BLOCK_SIZE);
131: state = new byte[BLOCK_SIZE];
132: SB0 = new int[256];
133: SB1 = new int[256];
134: SB2 = new int[256];
135: SB3 = new int[256];
136: }
137:
138: /**
139: * Called by the factory method to set the mode and padding parameters.
140: * Need because Class.newInstance does not take args.
141: *
142: * @param mode the mode parsed from the transformation parameter of
143: * getInstance and upper cased
144: * @param padding the paddinge parsed from the transformation parameter of
145: * getInstance and upper cased
146: */
147: protected void setChainingModeAndPadding(String mode, String padding)
148: throws NoSuchPaddingException {
149: // Note: The chaining mode is implicitly set by using this class.
150:
151: setPadding(padding);
152: }
153:
154: /**
155: * Initializes this cipher with a key and a set of algorithm
156: * parameters.
157: * @param mode the operation mode of this cipher
158: * @param key the encryption key
159: * @param params the algorithm parameters
160: * @exception java.security.InvalidKeyException if the given key
161: * is inappropriate for initializing this cipher
162: * @exception java.security.InvalidAlgorithmParameterException
163: * if the given algorithm parameters are inappropriate for this cipher
164: */
165: public void init(int mode, Key key, CryptoParameter params)
166: throws InvalidKeyException,
167: InvalidAlgorithmParameterException {
168:
169: doInit(mode, "AES", key, false, null);
170: }
171:
172: /**
173: * Initializes key.
174: * @param data key data
175: * @param mode cipher mode
176: * @exception InvalidKeyException if the given key is inappropriate
177: * for this cipher
178: */
179: void initKey(byte[] data, int mode) throws InvalidKeyException {
180:
181: // Min key 128 bits, max key 256 bits
182: if (data.length != 16 && data.length != 24 && data.length != 32) {
183: throw new InvalidKeyException();
184: }
185:
186: Nk = data.length >> 2;
187: Nr = 6 + Nk;
188:
189: int row = 0x0e090d0b;
190: byte[] box = ISBox;
191: if (mode == Cipher.ENCRYPT_MODE) {
192: row = 0x02010103;
193: box = SBox;
194: }
195:
196: if (multiply(row, box[0]) != SB0[0]) {
197: for (int i = 0; i < 256; i++) {
198: int j;
199: SB0[i] = j = multiply(row, box[i]);
200: SB1[i] = (j >>> 8) | (j << 24);
201: SB2[i] = (j >>> 16) | (j << 16);
202: SB3[i] = (j >>> 24) | (j << 8);
203: }
204: }
205:
206: KeyExpansion(data, mode);
207: }
208:
209: /**
210: * Calculates values for matrix multiplication.
211: * @param a represents a matrix column (4 bytes).
212: * @param b multiplier
213: * @return result of multiplication.
214: */
215: private static int multiply(int a, int b) {
216: int result = 0;
217: b &= 0xff;
218: for (int i = 0; i < 4; i++) {
219: result ^= ((a >> i) & 0x01010101) * b;
220: b = b < 128 ? b << 1 : (b << 1) ^ 0x11b;
221: }
222: return result;
223: }
224:
225: /**
226: * Depending on the mode, either encrypts or decrypts data block.
227: * @param out will contain the result of encryption
228: * or decryption operation
229: * @param offset is the offset in out
230: */
231: protected void processBlock(byte[] out, int offset) {
232:
233: holdCount = 0;
234:
235: if (mode == Cipher.ENCRYPT_MODE) {
236: cipherBlock();
237: } else {
238: decipherBlock();
239: }
240:
241: System.arraycopy(state, 0, out, offset, BLOCK_SIZE);
242: }
243:
244: /**
245: * Performs the encryption of data.
246: */
247: protected void cipherBlock() {
248:
249: int t0 = Util.getInt(holdData, 0) ^ W[0];
250: int t1 = Util.getInt(holdData, 4) ^ W[1];
251: int t2 = Util.getInt(holdData, 8) ^ W[2];
252: int t3 = Util.getInt(holdData, 12) ^ W[3];
253:
254: int j = 4;
255: for (int i = 1; i < Nr; i++) {
256: int v0, v1, v2;
257: t0 = SB0[(v0 = t0) >>> 24] ^ SB1[(v1 = t1) >>> 16 & 0xff]
258: ^ SB2[(v2 = t2) >>> 8 & 0xff] ^ SB3[t3 & 0xff]
259: ^ W[j];
260: t1 = SB0[v1 >>> 24] ^ SB1[v2 >>> 16 & 0xff]
261: ^ SB2[t3 >>> 8 & 0xff] ^ SB3[v0 & 0xff] ^ W[j + 1];
262: t2 = SB0[v2 >>> 24] ^ SB1[t3 >>> 16 & 0xff]
263: ^ SB2[v0 >>> 8 & 0xff] ^ SB3[v1 & 0xff] ^ W[j + 2];
264: t3 = SB0[t3 >>> 24] ^ SB1[v0 >>> 16 & 0xff]
265: ^ SB2[v1 >>> 8 & 0xff] ^ SB3[v2 & 0xff] ^ W[j + 3];
266: j += 4;
267: }
268:
269: int k;
270: byte out[];
271: (out = state)[0] = (byte) (SBox[t0 >>> 24] ^ (k = W[j]) >>> 24);
272: out[1] = (byte) (SBox[t1 >>> 16 & 0xff] ^ k >>> 16);
273: out[2] = (byte) (SBox[t2 >>> 8 & 0xff] ^ k >>> 8);
274: out[3] = (byte) (SBox[t3 & 0xff] ^ k);
275: out[4] = (byte) (SBox[t1 >>> 24] ^ (k = W[j + 1]) >>> 24);
276: out[5] = (byte) (SBox[t2 >>> 16 & 0xff] ^ k >>> 16);
277: out[6] = (byte) (SBox[t3 >>> 8 & 0xff] ^ k >>> 8);
278: out[7] = (byte) (SBox[t0 & 0xff] ^ k);
279: out[8] = (byte) (SBox[t2 >>> 24] ^ (k = W[j + 2]) >>> 24);
280: out[9] = (byte) (SBox[t3 >>> 16 & 0xff] ^ k >>> 16);
281: out[10] = (byte) (SBox[t0 >>> 8 & 0xff] ^ k >>> 8);
282: out[11] = (byte) (SBox[t1 & 0xff] ^ k);
283: out[12] = (byte) (SBox[t3 >>> 24] ^ (k = W[j + 3]) >>> 24);
284: out[13] = (byte) (SBox[t0 >>> 16 & 0xff] ^ k >>> 16);
285: out[14] = (byte) (SBox[t1 >>> 8 & 0xff] ^ k >>> 8);
286: out[15] = (byte) (SBox[t2 & 0xff] ^ k);
287: }
288:
289: /**
290: * Performs the decryption of data.
291: */
292: protected void decipherBlock() {
293:
294: int j;
295: int t0 = Util.getInt(holdData, 0) ^ W[j = Nr * 4];
296: int t1 = Util.getInt(holdData, 4) ^ W[j + 1];
297: int t2 = Util.getInt(holdData, 8) ^ W[j + 2];
298: int t3 = Util.getInt(holdData, 12) ^ W[j + 3];
299:
300: for (int i = 1; i < Nr; i++) {
301: int v0, v1, v2;
302: t0 = SB0[(v0 = t0) >>> 24] ^ SB1[t3 >>> 16 & 0xff]
303: ^ SB2[(v2 = t2) >>> 8 & 0xff]
304: ^ SB3[(v1 = t1) & 0xff] ^ W[j = j - 4];
305: t1 = SB0[v1 >>> 24] ^ SB1[v0 >>> 16 & 0xff]
306: ^ SB2[t3 >>> 8 & 0xff] ^ SB3[v2 & 0xff] ^ W[j + 1];
307: t2 = SB0[v2 >>> 24] ^ SB1[v1 >>> 16 & 0xff]
308: ^ SB2[v0 >>> 8 & 0xff] ^ SB3[t3 & 0xff] ^ W[j + 2];
309: t3 = SB0[t3 >>> 24] ^ SB1[v2 >>> 16 & 0xff]
310: ^ SB2[v1 >>> 8 & 0xff] ^ SB3[v0 & 0xff] ^ W[j + 3];
311: }
312:
313: int k;
314: byte out[];
315: (out = state)[0] = (byte) (ISBox[t0 >>> 24] ^ (k = W[0]) >>> 24);
316: out[1] = (byte) (ISBox[t3 >>> 16 & 0xff] ^ k >>> 16);
317: out[2] = (byte) (ISBox[t2 >>> 8 & 0xff] ^ k >>> 8);
318: out[3] = (byte) (ISBox[t1 & 0xff] ^ k);
319: out[4] = (byte) (ISBox[t1 >>> 24] ^ (k = W[1]) >>> 24);
320: out[5] = (byte) (ISBox[t0 >>> 16 & 0xff] ^ k >>> 16);
321: out[6] = (byte) (ISBox[t3 >>> 8 & 0xff] ^ k >>> 8);
322: out[7] = (byte) (ISBox[t2 & 0xff] ^ k);
323: out[8] = (byte) (ISBox[t2 >>> 24] ^ (k = W[2]) >>> 24);
324: out[9] = (byte) (ISBox[t1 >>> 16 & 0xff] ^ k >>> 16);
325: out[10] = (byte) (ISBox[t0 >>> 8 & 0xff] ^ k >>> 8);
326: out[11] = (byte) (ISBox[t3 & 0xff] ^ k);
327: out[12] = (byte) (ISBox[t3 >>> 24] ^ (k = W[3]) >>> 24);
328: out[13] = (byte) (ISBox[t2 >>> 16 & 0xff] ^ k >>> 16);
329: out[14] = (byte) (ISBox[t1 >>> 8 & 0xff] ^ k >>> 8);
330: out[15] = (byte) (ISBox[t0 & 0xff] ^ k);
331: }
332:
333: /**
334: * Generates KeySchedule.
335: * @param data key data
336: * @param mode cipher mode
337: */
338: private void KeyExpansion(byte[] data, int mode) {
339:
340: byte[] W = new byte[Nb * (Nr + 1) << 2];
341:
342: int diff;
343: System.arraycopy(data, 0, W, 0, (diff = Nk << 2));
344:
345: int round = 1;
346: for (int i = Nk; i < Nb * (Nr + 1); i++) {
347:
348: int v = i << 2;
349:
350: if (i % Nk == 0) {
351: int u = v - 1;
352: for (int j = 0; j < 4; j++, v++) {
353: W[v] = (byte) ((W[v - diff] ^ SBox[W[u
354: - ((6 - j) & 3)] & 0xff]));
355: }
356: W[i << 2] ^= Rcon[round++];
357: } else if (Nk > 6 && i % Nk == 4) {
358: for (int j = 0; j < 4; j++, v++) {
359: W[v] = (byte) (W[v - diff] ^ SBox[W[v - 4] & 0xff]);
360: }
361: } else {
362: for (int j = 0; j < 4; j++, v++) {
363: W[v] = (byte) (W[v - diff] ^ W[v - 4]);
364: }
365: }
366: }
367:
368: int[] V = (this .W = new int[W.length >> 2]);
369: for (int i = 0; i < V.length; i++) {
370: V[i] = Util.getInt(W, i * 4);
371: }
372:
373: if (mode == Cipher.DECRYPT_MODE) {
374: for (int i = 4; i < Nr * 4; i++) {
375: V[i] = SB0[SBox[W[i * 4] & 0xff] & 0xff]
376: ^ SB1[SBox[W[i * 4 + 1] & 0xff] & 0xff]
377: ^ SB2[SBox[W[i * 4 + 2] & 0xff] & 0xff]
378: ^ SB3[SBox[W[i * 4 + 3] & 0xff] & 0xff];
379: }
380: }
381: }
382: }
|