summaryrefslogtreecommitdiff
path: root/gnu/javax/crypto/mode/BaseMode.java
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/javax/crypto/mode/BaseMode.java')
-rw-r--r--gnu/javax/crypto/mode/BaseMode.java352
1 files changed, 352 insertions, 0 deletions
diff --git a/gnu/javax/crypto/mode/BaseMode.java b/gnu/javax/crypto/mode/BaseMode.java
new file mode 100644
index 000000000..0a9ab2dab
--- /dev/null
+++ b/gnu/javax/crypto/mode/BaseMode.java
@@ -0,0 +1,352 @@
+/* BaseMode.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * <p>A basic abstract class to facilitate implementing block cipher modes of
+ * operations.</p>
+ */
+public abstract class BaseMode implements IMode
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of this mode. */
+ protected String name;
+
+ /** The state indicator of this instance. */
+ protected int state;
+
+ /** The underlying block cipher implementation. */
+ protected IBlockCipher cipher;
+
+ /** The block size, in bytes, to operate the underlying block cipher in. */
+ protected int cipherBlockSize;
+
+ /** The block size, in bytes, in which to operate the mode instance. */
+ protected int modeBlockSize;
+
+ /** The initialisation vector value. */
+ protected byte[] iv;
+
+ /** The instance lock. */
+ protected Object lock = new Object();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name prefix of this mode.
+ * @param underlyingCipher the implementation of the underlying cipher.
+ * @param cipherBlockSize the block size, in bytes, in which to operate the
+ * underlying cipher.
+ */
+ protected BaseMode(String name, IBlockCipher underlyingCipher,
+ int cipherBlockSize)
+ {
+ super();
+
+ this.name = name;
+ this.cipher = underlyingCipher;
+ this.cipherBlockSize = cipherBlockSize;
+ state = -1;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IMode interface implementation ------------------------------------------
+
+ public void update(byte[] in, int inOffset, byte[] out, int outOffset)
+ throws IllegalStateException
+ {
+ synchronized (lock)
+ {
+ switch (state)
+ {
+ case ENCRYPTION:
+ encryptBlock(in, inOffset, out, outOffset);
+ break;
+ case DECRYPTION:
+ decryptBlock(in, inOffset, out, outOffset);
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ // IBlockCipher interface implementation -----------------------------------
+
+ public String name()
+ {
+ return new StringBuffer().append(name).append('(').append(cipher.name()).append(
+ ')').toString();
+ }
+
+ /**
+ * <p>Returns the default value, in bytes, of the mode's block size. This
+ * value is part of the construction arguments passed to the Factory methods
+ * in {@link ModeFactory}. Unless changed by an invocation of any of the
+ * <code>init()</code> methods, a <i>Mode</i> instance would operate with
+ * the same block size as its underlying block cipher. As mentioned earlier,
+ * the block size of the underlying block cipher itself is specified in one
+ * of the method(s) available in the factory class.</p>
+ *
+ * @return the default value, in bytes, of the mode's block size.
+ * @see gnu.crypto.mode.ModeFactory
+ */
+ public int defaultBlockSize()
+ {
+ return cipherBlockSize;
+ }
+
+ /**
+ * <p>Returns the default value, in bytes, of the underlying block cipher
+ * key size.</p>
+ *
+ * @return the default value, in bytes, of the underlying cipher's key size.
+ */
+ public int defaultKeySize()
+ {
+ return cipher.defaultKeySize();
+ }
+
+ /**
+ * <p>Returns an {@link Iterator} over the supported block sizes. Each
+ * element returned by this object is an {@link Integer}.</p>
+ *
+ * <p>The default behaviour is to return an iterator with just one value,
+ * which is that currently configured for the underlying block cipher.
+ * Concrete implementations may override this behaviour to signal their
+ * ability to support other values.</p>
+ *
+ * @return an {@link Iterator} over the supported block sizes.
+ */
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(cipherBlockSize));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ /**
+ * <p>Returns an {@link Iterator} over the supported underlying block cipher
+ * key sizes. Each element returned by this object is an instance of
+ * {@link Integer}.</p>
+ *
+ * @return an {@link Iterator} over the supported key sizes.
+ */
+ public Iterator keySizes()
+ {
+ return cipher.keySizes();
+ }
+
+ public void init(Map attributes) throws InvalidKeyException,
+ IllegalStateException
+ {
+ synchronized (lock)
+ {
+ if (state != -1)
+ {
+ throw new IllegalStateException();
+ }
+
+ Integer want = (Integer) attributes.get(STATE);
+ if (want != null)
+ {
+ switch (want.intValue())
+ {
+ case ENCRYPTION:
+ state = ENCRYPTION;
+ break;
+ case DECRYPTION:
+ state = DECRYPTION;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ Integer bs = (Integer) attributes.get(MODE_BLOCK_SIZE);
+ modeBlockSize = (bs == null ? cipherBlockSize : bs.intValue());
+
+ byte[] iv = (byte[]) attributes.get(IV);
+ if (iv != null)
+ {
+ this.iv = (byte[]) iv.clone();
+ }
+ else
+ {
+ this.iv = new byte[modeBlockSize];
+ }
+
+ cipher.init(attributes);
+ setup();
+ }
+ }
+
+ public int currentBlockSize()
+ {
+ if (state == -1)
+ {
+ throw new IllegalStateException();
+ }
+ return modeBlockSize;
+ }
+
+ public void reset()
+ {
+ synchronized (lock)
+ {
+ state = -1;
+ iv = null;
+ cipher.reset();
+
+ teardown();
+ }
+ }
+
+ public boolean selfTest()
+ {
+ int ks;
+ Iterator bit;
+ for (Iterator kit = keySizes(); kit.hasNext();)
+ {
+ ks = ((Integer) kit.next()).intValue();
+ for (bit = blockSizes(); bit.hasNext();)
+ {
+ if (!testSymmetry(ks, ((Integer) bit.next()).intValue()))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // methods to be implemented by concrete subclasses ------------------------
+
+ public abstract Object clone();
+
+ /** The initialisation phase of the concrete mode implementation. */
+ public abstract void setup();
+
+ /** The termination phase of the concrete mode implementation. */
+ public abstract void teardown();
+
+ public abstract void encryptBlock(byte[] in, int i, byte[] out, int o);
+
+ public abstract void decryptBlock(byte[] in, int i, byte[] out, int o);
+
+ // own methods -------------------------------------------------------------
+
+ private boolean testSymmetry(int ks, int bs)
+ {
+ try
+ {
+ IMode mode = (IMode) this.clone();
+ byte[] iv = new byte[cipherBlockSize]; // all zeroes
+ byte[] k = new byte[ks];
+ int i;
+ for (i = 0; i < ks; i++)
+ {
+ k[i] = (byte) i;
+ }
+
+ int blockCount = 5;
+ int limit = blockCount * bs;
+ byte[] pt = new byte[limit];
+ for (i = 0; i < limit; i++)
+ {
+ pt[i] = (byte) i;
+ }
+ byte[] ct = new byte[limit];
+ byte[] cpt = new byte[limit];
+
+ Map map = new HashMap();
+ map.put(KEY_MATERIAL, k);
+ map.put(CIPHER_BLOCK_SIZE, new Integer(cipherBlockSize));
+ map.put(STATE, new Integer(ENCRYPTION));
+ map.put(IV, iv);
+ map.put(MODE_BLOCK_SIZE, new Integer(bs));
+
+ mode.reset();
+ mode.init(map);
+ for (i = 0; i < blockCount; i++)
+ {
+ mode.update(pt, i * bs, ct, i * bs);
+ }
+
+ mode.reset();
+ map.put(STATE, new Integer(DECRYPTION));
+ mode.init(map);
+ for (i = 0; i < blockCount; i++)
+ {
+ mode.update(ct, i * bs, cpt, i * bs);
+ }
+
+ return Arrays.equals(pt, cpt);
+
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace(System.err);
+ return false;
+ }
+ }
+} \ No newline at end of file