Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / gnu / javax / crypto / mode / BaseMode.java
blob0a9ab2dab1cb4ee25a9b82f5ac3e6ea74d6e4730
1 /* BaseMode.java --
2 Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
4 This file is a part of GNU Classpath.
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.
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.
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
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.
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. */
39 package gnu.javax.crypto.mode;
41 import gnu.javax.crypto.cipher.IBlockCipher;
43 import java.security.InvalidKeyException;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.Iterator;
49 import java.util.Map;
51 /**
52 * <p>A basic abstract class to facilitate implementing block cipher modes of
53 * operations.</p>
55 public abstract class BaseMode implements IMode
58 // Constants and variables
59 // -------------------------------------------------------------------------
61 /** The canonical name prefix of this mode. */
62 protected String name;
64 /** The state indicator of this instance. */
65 protected int state;
67 /** The underlying block cipher implementation. */
68 protected IBlockCipher cipher;
70 /** The block size, in bytes, to operate the underlying block cipher in. */
71 protected int cipherBlockSize;
73 /** The block size, in bytes, in which to operate the mode instance. */
74 protected int modeBlockSize;
76 /** The initialisation vector value. */
77 protected byte[] iv;
79 /** The instance lock. */
80 protected Object lock = new Object();
82 // Constructor(s)
83 // -------------------------------------------------------------------------
85 /**
86 * <p>Trivial constructor for use by concrete subclasses.</p>
88 * @param name the canonical name prefix of this mode.
89 * @param underlyingCipher the implementation of the underlying cipher.
90 * @param cipherBlockSize the block size, in bytes, in which to operate the
91 * underlying cipher.
93 protected BaseMode(String name, IBlockCipher underlyingCipher,
94 int cipherBlockSize)
96 super();
98 this.name = name;
99 this.cipher = underlyingCipher;
100 this.cipherBlockSize = cipherBlockSize;
101 state = -1;
104 // Class methods
105 // -------------------------------------------------------------------------
107 // Instance methods
108 // -------------------------------------------------------------------------
110 // IMode interface implementation ------------------------------------------
112 public void update(byte[] in, int inOffset, byte[] out, int outOffset)
113 throws IllegalStateException
115 synchronized (lock)
117 switch (state)
119 case ENCRYPTION:
120 encryptBlock(in, inOffset, out, outOffset);
121 break;
122 case DECRYPTION:
123 decryptBlock(in, inOffset, out, outOffset);
124 break;
125 default:
126 throw new IllegalStateException();
131 // IBlockCipher interface implementation -----------------------------------
133 public String name()
135 return new StringBuffer().append(name).append('(').append(cipher.name()).append(
136 ')').toString();
140 * <p>Returns the default value, in bytes, of the mode's block size. This
141 * value is part of the construction arguments passed to the Factory methods
142 * in {@link ModeFactory}. Unless changed by an invocation of any of the
143 * <code>init()</code> methods, a <i>Mode</i> instance would operate with
144 * the same block size as its underlying block cipher. As mentioned earlier,
145 * the block size of the underlying block cipher itself is specified in one
146 * of the method(s) available in the factory class.</p>
148 * @return the default value, in bytes, of the mode's block size.
149 * @see gnu.crypto.mode.ModeFactory
151 public int defaultBlockSize()
153 return cipherBlockSize;
157 * <p>Returns the default value, in bytes, of the underlying block cipher
158 * key size.</p>
160 * @return the default value, in bytes, of the underlying cipher's key size.
162 public int defaultKeySize()
164 return cipher.defaultKeySize();
168 * <p>Returns an {@link Iterator} over the supported block sizes. Each
169 * element returned by this object is an {@link Integer}.</p>
171 * <p>The default behaviour is to return an iterator with just one value,
172 * which is that currently configured for the underlying block cipher.
173 * Concrete implementations may override this behaviour to signal their
174 * ability to support other values.</p>
176 * @return an {@link Iterator} over the supported block sizes.
178 public Iterator blockSizes()
180 ArrayList al = new ArrayList();
181 al.add(new Integer(cipherBlockSize));
183 return Collections.unmodifiableList(al).iterator();
187 * <p>Returns an {@link Iterator} over the supported underlying block cipher
188 * key sizes. Each element returned by this object is an instance of
189 * {@link Integer}.</p>
191 * @return an {@link Iterator} over the supported key sizes.
193 public Iterator keySizes()
195 return cipher.keySizes();
198 public void init(Map attributes) throws InvalidKeyException,
199 IllegalStateException
201 synchronized (lock)
203 if (state != -1)
205 throw new IllegalStateException();
208 Integer want = (Integer) attributes.get(STATE);
209 if (want != null)
211 switch (want.intValue())
213 case ENCRYPTION:
214 state = ENCRYPTION;
215 break;
216 case DECRYPTION:
217 state = DECRYPTION;
218 break;
219 default:
220 throw new IllegalArgumentException();
224 Integer bs = (Integer) attributes.get(MODE_BLOCK_SIZE);
225 modeBlockSize = (bs == null ? cipherBlockSize : bs.intValue());
227 byte[] iv = (byte[]) attributes.get(IV);
228 if (iv != null)
230 this.iv = (byte[]) iv.clone();
232 else
234 this.iv = new byte[modeBlockSize];
237 cipher.init(attributes);
238 setup();
242 public int currentBlockSize()
244 if (state == -1)
246 throw new IllegalStateException();
248 return modeBlockSize;
251 public void reset()
253 synchronized (lock)
255 state = -1;
256 iv = null;
257 cipher.reset();
259 teardown();
263 public boolean selfTest()
265 int ks;
266 Iterator bit;
267 for (Iterator kit = keySizes(); kit.hasNext();)
269 ks = ((Integer) kit.next()).intValue();
270 for (bit = blockSizes(); bit.hasNext();)
272 if (!testSymmetry(ks, ((Integer) bit.next()).intValue()))
274 return false;
279 return true;
282 // methods to be implemented by concrete subclasses ------------------------
284 public abstract Object clone();
286 /** The initialisation phase of the concrete mode implementation. */
287 public abstract void setup();
289 /** The termination phase of the concrete mode implementation. */
290 public abstract void teardown();
292 public abstract void encryptBlock(byte[] in, int i, byte[] out, int o);
294 public abstract void decryptBlock(byte[] in, int i, byte[] out, int o);
296 // own methods -------------------------------------------------------------
298 private boolean testSymmetry(int ks, int bs)
302 IMode mode = (IMode) this.clone();
303 byte[] iv = new byte[cipherBlockSize]; // all zeroes
304 byte[] k = new byte[ks];
305 int i;
306 for (i = 0; i < ks; i++)
308 k[i] = (byte) i;
311 int blockCount = 5;
312 int limit = blockCount * bs;
313 byte[] pt = new byte[limit];
314 for (i = 0; i < limit; i++)
316 pt[i] = (byte) i;
318 byte[] ct = new byte[limit];
319 byte[] cpt = new byte[limit];
321 Map map = new HashMap();
322 map.put(KEY_MATERIAL, k);
323 map.put(CIPHER_BLOCK_SIZE, new Integer(cipherBlockSize));
324 map.put(STATE, new Integer(ENCRYPTION));
325 map.put(IV, iv);
326 map.put(MODE_BLOCK_SIZE, new Integer(bs));
328 mode.reset();
329 mode.init(map);
330 for (i = 0; i < blockCount; i++)
332 mode.update(pt, i * bs, ct, i * bs);
335 mode.reset();
336 map.put(STATE, new Integer(DECRYPTION));
337 mode.init(map);
338 for (i = 0; i < blockCount; i++)
340 mode.update(ct, i * bs, cpt, i * bs);
343 return Arrays.equals(pt, cpt);
346 catch (Exception x)
348 x.printStackTrace(System.err);
349 return false;