summaryrefslogtreecommitdiff
path: root/libjava/classpath/gnu/javax/crypto/assembly
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/javax/crypto/assembly')
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Assembly.java272
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Cascade.java348
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/CascadeStage.java93
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/CascadeTransformer.java123
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/DeflateTransformer.java177
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Direction.java78
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/LoopbackTransformer.java100
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/ModeStage.java112
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Operation.java73
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/PaddingTransformer.java164
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Stage.java202
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Transformer.java421
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/TransformerException.java140
13 files changed, 2303 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/Assembly.java b/libjava/classpath/gnu/javax/crypto/assembly/Assembly.java
new file mode 100644
index 000000000..f570d2012
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/Assembly.java
@@ -0,0 +1,272 @@
+/* Assembly.java --
+ Copyright (C) 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.assembly;
+
+import java.util.Map;
+
+/**
+ * An <code>Assembly</code> is a construction consisting of a chain of
+ * {@link Transformer} elements; each wired in pre- or post- transformation
+ * mode. This chain is terminated by one <code>LoopbackTransformer</code>
+ * element.
+ * <p>
+ * Once constructed, and correctly initialised, the bulk of the methods
+ * available on the <code>Assembly</code> are delegated to the <i>head</i> of
+ * the {@link Transformer} chain of the <code>Assembly</code>.
+ *
+ * @see Transformer
+ */
+public class Assembly
+{
+ public static final String DIRECTION = "gnu.crypto.assembly.assembly.direction";
+
+ /** Flag that tells if the instance is initialised or not; and if yes how. */
+ private Direction wired;
+
+ /** The first Transformer in the chain. */
+ private Transformer head;
+
+ /**
+ * Trivial constructor that sets the <i>chain</i> to a
+ * <code>LoopbackTransformer</code>.
+ */
+ public Assembly()
+ {
+ super();
+
+ wired = null;
+ head = new LoopbackTransformer();
+ }
+
+ /**
+ * Adds the designated {@link Transformer} and signals that it should operate
+ * in pre-processing mode; i.e. it should apply its internal transformation
+ * algorithm on the input data stream, <b>before</b> it passes that stream to
+ * the next element in the <i>chain</i>.
+ *
+ * @param t the {@link Transformer} to add at the head of the current chain.
+ * @throws IllegalArgumentException if the designated {@link Transformer} has
+ * a non-null tail; i.e. it is already an element of a chain.
+ */
+ public void addPreTransformer(Transformer t)
+ {
+ wireTransformer(t, Operation.PRE_PROCESSING);
+ }
+
+ /**
+ * Adds the designated {@link Transformer} and signals that it should operate
+ * in post-processing mode; i.e. it should apply its internal transformation
+ * algorithm on the input data stream, <b>after</b> it passes that stream to
+ * the next element in the <i>chain</i>.
+ *
+ * @param t the {@link Transformer} to add at the head of the current chain.
+ * @throws IllegalArgumentException if the designated {@link Transformer} has
+ * a non-null tail; i.e. it is already an element of a chain.
+ */
+ public void addPostTransformer(Transformer t)
+ {
+ wireTransformer(t, Operation.POST_PROCESSING);
+ }
+
+ /**
+ * Initialises the <code>Assembly</code> for operation with specific
+ * characteristics.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalStateException if the instance is already initialised.
+ */
+ public void init(Map attributes) throws TransformerException
+ {
+ if (wired != null)
+ throw new IllegalStateException();
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == null)
+ flow = Direction.FORWARD;
+ attributes.put(Transformer.DIRECTION, flow);
+ head.init(attributes);
+ wired = flow;
+ }
+
+ /**
+ * Resets the <code>Assembly</code> for re-initialisation and use with other
+ * characteristics. This method always succeeds.
+ */
+ public void reset()
+ {
+ head.reset();
+ wired = null;
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments, using a byte array of length <code>1</code> whose contents are
+ * the designated byte.
+ *
+ * @param b the byte to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #update(byte[], int, int)
+ */
+ public byte[] update(byte b) throws TransformerException
+ {
+ return update(new byte[] { b }, 0, 1);
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments. All bytes in <code>in</code>, starting from index position
+ * <code>0</code> are considered.
+ *
+ * @param in the input data bytes.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #update(byte[], int, int)
+ */
+ public byte[] update(byte[] in) throws TransformerException
+ {
+ return update(in, 0, in.length);
+ }
+
+ /**
+ * Processes a designated number of bytes from a given byte array.
+ *
+ * @param in the input data bytes.
+ * @param offset index of <code>in</code> from which to start considering
+ * data.
+ * @param length the count of bytes to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ */
+ public byte[] update(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ if (wired == null)
+ throw new IllegalStateException();
+ return head.update(in, offset, length);
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three arguments
+ * using a 0-long byte array.
+ *
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate() throws TransformerException
+ {
+ return lastUpdate(new byte[0], 0, 0);
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments, using a byte array of length <code>1</code> whose contents are
+ * the designated byte.
+ *
+ * @param b the byte to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate(byte b) throws TransformerException
+ {
+ return lastUpdate(new byte[] { b }, 0, 1);
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments. All bytes in <code>in</code>, starting from index position
+ * <code>0</code> are considered.
+ *
+ * @param in the input data bytes.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate(byte[] in) throws TransformerException
+ {
+ return lastUpdate(in, 0, in.length);
+ }
+
+ /**
+ * Processes a designated number of bytes from a given byte array and signals,
+ * at the same time, that this is the last <i>push</i> operation for this
+ * <code>Assembly</code>.
+ *
+ * @param in the input data bytes.
+ * @param offset index of <code>in</code> from which to start considering
+ * data.
+ * @param length the count of bytes to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ */
+ public byte[] lastUpdate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ if (wired == null)
+ throw new IllegalStateException();
+ byte[] result = head.lastUpdate(in, offset, length);
+ reset();
+ return result;
+ }
+
+ private void wireTransformer(Transformer t, Operation mode)
+ {
+ if (t.tail != null)
+ throw new IllegalArgumentException();
+ t.setMode(mode);
+ t.tail = head;
+ head = t;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/Cascade.java b/libjava/classpath/gnu/javax/crypto/assembly/Cascade.java
new file mode 100644
index 000000000..685cef5b2
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/Cascade.java
@@ -0,0 +1,348 @@
+/* Cascade.java --
+ Copyright (C) 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.assembly;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A <i>Cascade</i> Cipher is the concatenation of two or more block ciphers
+ * each with independent keys. Plaintext is input to the first stage; the output
+ * of stage <code>i</code> is input to stage <code>i + 1</code>; and the
+ * output of the last stage is the <i>Cascade</i>'s ciphertext output.
+ * <p>
+ * In the simplest case, all stages in a <code>Cascade</code> have <i>k</i>-bit
+ * keys, and the stage inputs and outputs are all n-bit quantities. The stage
+ * ciphers may differ (general cascade of ciphers), or all be identical (cascade
+ * of identical ciphers).
+ * <p>
+ * The term "block ciphers" used above refers to implementations of
+ * {@link gnu.javax.crypto.mode.IMode}, including the
+ * {@link gnu.javax.crypto.mode.ECB} mode which basically exposes a
+ * symmetric-key block cipher algorithm as a <i>Mode</i> of Operations.
+ * <p>
+ * References:
+ * <ol>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
+ * Applied Cryptography.<br>
+ * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
+ * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
+ * </ol>
+ */
+public class Cascade
+{
+ public static final String DIRECTION = "gnu.crypto.assembly.cascade.direction";
+
+ /** The map of Stages chained in this cascade. */
+ protected HashMap stages;
+
+ /** The ordered list of Stage UIDs to their attribute maps. */
+ protected LinkedList stageKeys;
+
+ /** The current operational direction of this instance. */
+ protected Direction wired;
+
+ /** The curently set block-size for this instance. */
+ protected int blockSize;
+
+ public Cascade()
+ {
+ super();
+
+ stages = new HashMap(3);
+ stageKeys = new LinkedList();
+ wired = null;
+ blockSize = 0;
+ }
+
+ /**
+ * Returns the Least Common Multiple of two integers.
+ *
+ * @param a the first integer.
+ * @param b the second integer.
+ * @return the LCM of <code>abs(a)</code> and <code>abs(b)</code>.
+ */
+ private static final int lcm(int a, int b)
+ {
+ BigInteger A = BigInteger.valueOf(a * 1L);
+ BigInteger B = BigInteger.valueOf(b * 1L);
+ return A.multiply(B).divide(A.gcd(B)).abs().intValue();
+ }
+
+ /**
+ * Adds to the end of the current chain, a designated {@link Stage}.
+ *
+ * @param stage the {@link Stage} to append to the chain.
+ * @return a unique identifier for this stage, within this cascade.
+ * @throws IllegalStateException if the instance is already initialised.
+ * @throws IllegalArgumentException if the designated stage is already in the
+ * chain, or it has incompatible characteristics with the current
+ * elements already in the chain.
+ */
+ public Object append(Stage stage) throws IllegalArgumentException
+ {
+ return insert(size(), stage);
+ }
+
+ /**
+ * Adds to the begining of the current chain, a designated {@link Stage}.
+ *
+ * @param stage the {@link Stage} to prepend to the chain.
+ * @return a unique identifier for this stage, within this cascade.
+ * @throws IllegalStateException if the instance is already initialised.
+ * @throws IllegalArgumentException if the designated stage is already in the
+ * chain, or it has incompatible characteristics with the current
+ * elements already in the chain.
+ */
+ public Object prepend(Stage stage) throws IllegalArgumentException
+ {
+ return insert(0, stage);
+ }
+
+ /**
+ * Inserts a {@link Stage} into the current chain, at the specified index
+ * (zero-based) position.
+ *
+ * @param stage the {@link Stage} to insert into the chain.
+ * @return a unique identifier for this stage, within this cascade.
+ * @throws IllegalArgumentException if the designated stage is already in the
+ * chain, or it has incompatible characteristics with the current
+ * elements already in the chain.
+ * @throws IllegalStateException if the instance is already initialised.
+ * @throws IndexOutOfBoundsException if <code>index</code> is less than
+ * <code>0</code> or greater than the current size of this
+ * cascade.
+ */
+ public Object insert(int index, Stage stage) throws IllegalArgumentException,
+ IndexOutOfBoundsException
+ {
+ if (stages.containsValue(stage))
+ throw new IllegalArgumentException();
+ if (wired != null || stage == null)
+ throw new IllegalStateException();
+ if (index < 0 || index > size())
+ throw new IndexOutOfBoundsException();
+ // check that there is a non-empty set of common block-sizes
+ Set set = stage.blockSizes();
+ if (stages.isEmpty())
+ {
+ if (set.isEmpty())
+ throw new IllegalArgumentException("1st stage with no block sizes");
+ }
+ else
+ {
+ Set common = this.blockSizes();
+ common.retainAll(set);
+ if (common.isEmpty())
+ throw new IllegalArgumentException("no common block sizes found");
+ }
+ Object result = new Object();
+ stageKeys.add(index, result);
+ stages.put(result, stage);
+ return result;
+ }
+
+ /**
+ * Returns the current number of stages in this chain.
+ *
+ * @return the current count of stages in this chain.
+ */
+ public int size()
+ {
+ return stages.size();
+ }
+
+ /**
+ * Returns an {@link Iterator} over the stages contained in this instance.
+ * Each element of this iterator is a concrete implementation of a {@link
+ * Stage}.
+ *
+ * @return an {@link Iterator} over the stages contained in this instance.
+ * Each element of the returned iterator is a concrete instance of a
+ * {@link Stage}.
+ */
+ public Iterator stages()
+ {
+ LinkedList result = new LinkedList();
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ result.addLast(stages.get(it.next()));
+ return result.listIterator();
+ }
+
+ /**
+ * Returns the {@link Set} of supported block sizes for this
+ * <code>Cascade</code> that are common to all of its chained stages. Each
+ * element in the returned {@link Set} is an instance of {@link Integer}.
+ *
+ * @return a {@link Set} of supported block sizes common to all the stages of
+ * the chain.
+ */
+ public Set blockSizes()
+ {
+ HashSet result = null;
+ for (Iterator it = stages.values().iterator(); it.hasNext();)
+ {
+ Stage aStage = (Stage) it.next();
+ if (result == null) // first time
+ result = new HashSet(aStage.blockSizes());
+ else
+ result.retainAll(aStage.blockSizes());
+ }
+ return result == null ? Collections.EMPTY_SET : result;
+ }
+
+ /**
+ * Initialises the chain for operation with specific characteristics.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalStateException if the chain, or any of its stages, is
+ * already initialised.
+ * @throws InvalidKeyException if the intialisation data provided with the
+ * stage is incorrect or causes an invalid key to be generated.
+ * @see Direction#FORWARD
+ * @see Direction#REVERSED
+ */
+ public void init(Map attributes) throws InvalidKeyException
+ {
+ if (wired != null)
+ throw new IllegalStateException();
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == null)
+ flow = Direction.FORWARD;
+ int optimalSize = 0;
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ {
+ Object id = it.next();
+ Map attr = (Map) attributes.get(id);
+ attr.put(Stage.DIRECTION, flow);
+ Stage stage = (Stage) stages.get(id);
+ stage.init(attr);
+ optimalSize = optimalSize == 0 ? stage.currentBlockSize()
+ : lcm(optimalSize,
+ stage.currentBlockSize());
+ }
+ if (flow == Direction.REVERSED) // reverse order
+ Collections.reverse(stageKeys);
+ wired = flow;
+ blockSize = optimalSize;
+ }
+
+ /**
+ * Returns the currently set block size for the chain.
+ *
+ * @return the current block size for the chain.
+ * @throws IllegalStateException if the instance is not initialised.
+ */
+ public int currentBlockSize()
+ {
+ if (wired == null)
+ throw new IllegalStateException();
+ return blockSize;
+ }
+
+ /**
+ * Resets the chain for re-initialisation and use with other characteristics.
+ * This method always succeeds.
+ */
+ public void reset()
+ {
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ ((Stage) stages.get(it.next())).reset();
+ if (wired == Direction.REVERSED) // reverse it back
+ Collections.reverse(stageKeys);
+ wired = null;
+ blockSize = 0;
+ }
+
+ /**
+ * Processes exactly one block of <i>plaintext</i> (if initialised in the
+ * {@link Direction#FORWARD} state) or <i>ciphertext</i> (if initialised in
+ * the {@link Direction#REVERSED} state).
+ *
+ * @param in the plaintext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the ciphertext.
+ * @param outOffset index of <code>out</code> from which to store result.
+ * @throws IllegalStateException if the instance is not initialised.
+ */
+ public void update(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ if (wired == null)
+ throw new IllegalStateException();
+ int stageBlockSize, j, i = stages.size();
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ {
+ Stage stage = (Stage) stages.get(it.next());
+ stageBlockSize = stage.currentBlockSize();
+ for (j = 0; j < blockSize; j += stageBlockSize)
+ stage.update(in, inOffset + j, out, outOffset + j);
+ i--;
+ if (i > 0)
+ System.arraycopy(out, outOffset, in, inOffset, blockSize);
+ }
+ }
+
+ /**
+ * Conducts a simple <i>correctness</i> test that consists of basic symmetric
+ * encryption / decryption test(s) for all supported block and key sizes of
+ * underlying block cipher(s) wrapped by Mode leafs. The test also includes
+ * one (1) variable key Known Answer Test (KAT) for each block cipher.
+ *
+ * @return <code>true</code> if the implementation passes simple
+ * <i>correctness</i> tests. Returns <code>false</code> otherwise.
+ */
+ public boolean selfTest()
+ {
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ {
+ if (! ((Stage) stages.get(it.next())).selfTest())
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/CascadeStage.java b/libjava/classpath/gnu/javax/crypto/assembly/CascadeStage.java
new file mode 100644
index 000000000..196edafdf
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/CascadeStage.java
@@ -0,0 +1,93 @@
+/* CascadeStage.java --
+ Copyright (C) 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.assembly;
+
+import java.security.InvalidKeyException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A Cascade <i>Stage</i> in a Cascade Cipher.
+ */
+class CascadeStage
+ extends Stage
+{
+ private Cascade delegate;
+
+ CascadeStage(Cascade cascade, Direction forwardDirection)
+ {
+ super(forwardDirection);
+
+ this.delegate = cascade;
+ }
+
+ public Set blockSizes()
+ {
+ return Collections.unmodifiableSet(delegate.blockSizes());
+ }
+
+ void initDelegate(Map attributes) throws InvalidKeyException
+ {
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ attributes.put(DIRECTION, flow.equals(forward) ? forward
+ : Direction.reverse(forward));
+ delegate.init(attributes);
+ }
+
+ public int currentBlockSize() throws IllegalStateException
+ {
+ return delegate.currentBlockSize();
+ }
+
+ void resetDelegate()
+ {
+ delegate.reset();
+ }
+
+ void updateDelegate(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ delegate.update(in, inOffset, out, outOffset);
+ }
+
+ public boolean selfTest()
+ {
+ return delegate.selfTest();
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/CascadeTransformer.java b/libjava/classpath/gnu/javax/crypto/assembly/CascadeTransformer.java
new file mode 100644
index 000000000..8e3a9a5a1
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/CascadeTransformer.java
@@ -0,0 +1,123 @@
+/* CascadeTransformer.java --
+ Copyright (C) 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.assembly;
+
+import java.security.InvalidKeyException;
+import java.util.Map;
+
+/**
+ * An Adapter to use any {@link Cascade} as a {@link Transformer} in an
+ * {@link Assembly}.
+ */
+class CascadeTransformer
+ extends Transformer
+{
+ private Cascade delegate;
+
+ private int blockSize;
+
+ CascadeTransformer(Cascade delegate)
+ {
+ super();
+
+ this.delegate = delegate;
+ }
+
+ void initDelegate(Map attributes) throws TransformerException
+ {
+ attributes.put(Cascade.DIRECTION, wired);
+ try
+ {
+ delegate.init(attributes);
+ }
+ catch (InvalidKeyException x)
+ {
+ throw new TransformerException("initDelegate()", x);
+ }
+ blockSize = delegate.currentBlockSize();
+ }
+
+ int delegateBlockSize()
+ {
+ return blockSize;
+ }
+
+ void resetDelegate()
+ {
+ delegate.reset();
+ blockSize = 0;
+ }
+
+ byte[] updateDelegate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ byte[] result = updateInternal(in, offset, length);
+ return result;
+ }
+
+ byte[] lastUpdateDelegate() throws TransformerException
+ {
+ if (inBuffer.size() != 0)
+ {
+ IllegalStateException cause = new IllegalStateException(
+ "Cascade transformer, after last update, must be empty but isn't");
+ throw new TransformerException("lastUpdateDelegate()", cause);
+ }
+ return new byte[0];
+ }
+
+ private byte[] updateInternal(byte[] in, int offset, int length)
+ {
+ byte[] result;
+ for (int i = 0; i < length; i++)
+ {
+ inBuffer.write(in[offset++] & 0xFF);
+ if (inBuffer.size() >= blockSize)
+ {
+ result = inBuffer.toByteArray();
+ inBuffer.reset();
+ delegate.update(result, 0, result, 0);
+ outBuffer.write(result, 0, blockSize);
+ }
+ }
+ result = outBuffer.toByteArray();
+ outBuffer.reset();
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/DeflateTransformer.java b/libjava/classpath/gnu/javax/crypto/assembly/DeflateTransformer.java
new file mode 100644
index 000000000..97f9f0365
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/DeflateTransformer.java
@@ -0,0 +1,177 @@
+/* DeflateTransformer.java --
+ Copyright (C) 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.assembly;
+
+import java.util.Map;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+/**
+ * A {@link Transformer} Adapter allowing inclusion of a DEFLATE compression
+ * algorithm in an {@link Assembly} chain. The {@link Direction#FORWARD}
+ * transformation is a compression (deflate) of input data, while the
+ * {@link Direction#REVERSED} one is a decompression (inflate) that restores the
+ * original data.
+ * <p>
+ * This {@link Transformer} uses a {@link Deflater} instance to carry on the
+ * compression, and an {@link Inflater} to do the decompression.
+ * <p>
+ * When using such a {@link Transformer}, in an {@link Assembly}, there must
+ * be at least one element behind this instance in the constructed chain;
+ * otherwise, a {@link TransformerException} is thrown at initialisation time.
+ */
+class DeflateTransformer
+ extends Transformer
+{
+ private Deflater compressor;
+
+ private Inflater decompressor;
+
+ private int outputBlockSize = 512; // default zlib buffer size
+
+ private byte[] zlibBuffer;
+
+ DeflateTransformer()
+ {
+ super();
+
+ }
+
+ void initDelegate(Map attributes) throws TransformerException
+ {
+ if (tail == null)
+ {
+ IllegalStateException cause = new IllegalStateException(
+ "Compression transformer missing its tail!");
+ throw new TransformerException("initDelegate()", cause);
+ }
+ outputBlockSize = tail.currentBlockSize();
+ zlibBuffer = new byte[outputBlockSize];
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == Direction.FORWARD)
+ compressor = new Deflater();
+ else
+ decompressor = new Inflater();
+ }
+
+ int delegateBlockSize()
+ {
+ return 1;
+ }
+
+ void resetDelegate()
+ {
+ compressor = null;
+ decompressor = null;
+ outputBlockSize = 1;
+ zlibBuffer = null;
+ }
+
+ byte[] updateDelegate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ byte[] result;
+ if (wired == Direction.FORWARD)
+ {
+ compressor.setInput(in, offset, length);
+ while (! compressor.needsInput())
+ compress();
+ }
+ else // decompression: inflate first and then update tail
+ decompress(in, offset, length);
+ result = inBuffer.toByteArray();
+ inBuffer.reset();
+ return result;
+ }
+
+ byte[] lastUpdateDelegate() throws TransformerException
+ {
+ // process multiples of blocksize as much as possible
+ if (wired == Direction.FORWARD) // compressing
+ {
+ if (! compressor.finished())
+ {
+ compressor.finish();
+ while (! compressor.finished())
+ compress();
+ }
+ }
+ else // decompressing
+ {
+ if (! decompressor.finished())
+ {
+ IllegalStateException cause = new IllegalStateException(
+ "Compression transformer, after last update, must be finished "
+ + "but isn't");
+ throw new TransformerException("lastUpdateDelegate()", cause);
+ }
+ }
+ byte[] result = inBuffer.toByteArray();
+ inBuffer.reset();
+ return result;
+ }
+
+ private void compress()
+ {
+ int len = compressor.deflate(zlibBuffer);
+ if (len > 0)
+ inBuffer.write(zlibBuffer, 0, len);
+ }
+
+ private void decompress(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ decompressor.setInput(in, offset, length);
+ int len = 1;
+ while (len > 0)
+ {
+ try
+ {
+ len = decompressor.inflate(zlibBuffer);
+ }
+ catch (DataFormatException x)
+ {
+ throw new TransformerException("decompress()", x);
+ }
+ if (len > 0)
+ inBuffer.write(zlibBuffer, 0, len);
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/Direction.java b/libjava/classpath/gnu/javax/crypto/assembly/Direction.java
new file mode 100644
index 000000000..40ddfc429
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/Direction.java
@@ -0,0 +1,78 @@
+/* Direction.java --
+ Copyright (C) 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.assembly;
+
+/**
+ * An enumeration type for wiring {@link Stage} instances into {@link Cascade}
+ * Cipher chains, as well as for operating a {@link Cascade} in a given
+ * direction.
+ * <p>
+ * The possible values for this type are two:
+ * <ol>
+ * <li>FORWARD: equivalent to {@link gnu.javax.crypto.mode.IMode#ENCRYPTION},
+ * and its inverse value</li>
+ * <li>REVERSED: equivalent to {@link gnu.javax.crypto.mode.IMode#DECRYPTION}.
+ * </li>
+ * </ol>
+ */
+public final class Direction
+{
+ public static final Direction FORWARD = new Direction(1);
+
+ public static final Direction REVERSED = new Direction(2);
+
+ private int value;
+
+ private Direction(int value)
+ {
+ super();
+
+ this.value = value;
+ }
+
+ public static final Direction reverse(Direction d)
+ {
+ return (d.equals(FORWARD) ? REVERSED : FORWARD);
+ }
+
+ public String toString()
+ {
+ return (this == FORWARD ? "forward" : "reversed");
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/LoopbackTransformer.java b/libjava/classpath/gnu/javax/crypto/assembly/LoopbackTransformer.java
new file mode 100644
index 000000000..5bcfe5ffc
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/LoopbackTransformer.java
@@ -0,0 +1,100 @@
+/* LoopbackTransformer.java --
+ Copyright (C) 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.assembly;
+
+import java.util.Map;
+
+/**
+ * A trivial {@link Transformer} to allow closing a chain in an {@link Assembly}.
+ * This class is not visible outside this package.
+ */
+final class LoopbackTransformer
+ extends Transformer
+{
+ /** Trivial package-private constructor. */
+ LoopbackTransformer()
+ {
+ super();
+ }
+
+ public void init(Map attributes) throws TransformerException
+ {
+ }
+
+ public void reset()
+ {
+ }
+
+ public byte[] update(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ return updateDelegate(in, offset, length);
+ }
+
+ public byte[] lastUpdate() throws TransformerException
+ {
+ return lastUpdateDelegate();
+ }
+
+ void initDelegate(Map attributes) throws TransformerException
+ {
+ }
+
+ int delegateBlockSize()
+ {
+ return 1;
+ }
+
+ void resetDelegate()
+ {
+ }
+
+ byte[] updateDelegate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ byte[] result = new byte[length];
+ System.arraycopy(in, offset, result, 0, length);
+ return result;
+ }
+
+ byte[] lastUpdateDelegate() throws TransformerException
+ {
+ return new byte[0];
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/ModeStage.java b/libjava/classpath/gnu/javax/crypto/assembly/ModeStage.java
new file mode 100644
index 000000000..8bdbef7c4
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/ModeStage.java
@@ -0,0 +1,112 @@
+/* ModeStage.java --
+ Copyright (C) 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.assembly;
+
+import gnu.javax.crypto.mode.IMode;
+
+import java.security.InvalidKeyException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An {@link IMode} {@link Stage} in a {@link Cascade} Cipher chain.
+ * <p>
+ * Such a stage wraps an implementation of a Block Cipher Mode of Operation
+ * ({@link IMode}) to allow inclusion of such an instance in a cascade of block
+ * ciphers.
+ */
+class ModeStage
+ extends Stage
+{
+ private IMode delegate;
+
+ private transient Set cachedBlockSizes;
+
+ ModeStage(IMode mode, Direction forwardDirection)
+ {
+ super(forwardDirection);
+
+ delegate = mode;
+ cachedBlockSizes = null;
+ }
+
+ public Set blockSizes()
+ {
+ if (cachedBlockSizes == null)
+ {
+ HashSet result = new HashSet();
+ for (Iterator it = delegate.blockSizes(); it.hasNext();)
+ result.add(it.next());
+ cachedBlockSizes = Collections.unmodifiableSet(result);
+ }
+ return cachedBlockSizes;
+ }
+
+ void initDelegate(Map attributes) throws InvalidKeyException
+ {
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ attributes.put(IMode.STATE,
+ Integer.valueOf(flow.equals(forward) ? IMode.ENCRYPTION
+ : IMode.DECRYPTION));
+ delegate.init(attributes);
+ }
+
+ public int currentBlockSize() throws IllegalStateException
+ {
+ return delegate.currentBlockSize();
+ }
+
+ void resetDelegate()
+ {
+ delegate.reset();
+ }
+
+ void updateDelegate(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ delegate.update(in, inOffset, out, outOffset);
+ }
+
+ public boolean selfTest()
+ {
+ return delegate.selfTest();
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/Operation.java b/libjava/classpath/gnu/javax/crypto/assembly/Operation.java
new file mode 100644
index 000000000..6861a1377
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/Operation.java
@@ -0,0 +1,73 @@
+/* Operation.java --
+ Copyright (C) 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.assembly;
+
+/**
+ * An enumeration type for specifying the operation type of a
+ * {@link Transformer}.
+ * <p>
+ * The possible values for this type are two:
+ * <ol>
+ * <li>PRE_PROCESSING: where the input data is first processed by the current
+ * {@link Transformer} before being passed to the rest of the chain; and</li>
+ * <li>POST_PROCESSING: where the input data is first passed to the rest of the
+ * chain, and the resulting bytes are then processed by the current
+ * {@link Transformer}.</li>
+ * </ol>
+ */
+public final class Operation
+{
+ public static final Operation PRE_PROCESSING = new Operation(1);
+
+ public static final Operation POST_PROCESSING = new Operation(2);
+
+ private int value;
+
+ private Operation(int value)
+ {
+ super();
+
+ this.value = value;
+ }
+
+ public String toString()
+ {
+ return (this == PRE_PROCESSING ? "pre-processing" : "post-processing");
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/PaddingTransformer.java b/libjava/classpath/gnu/javax/crypto/assembly/PaddingTransformer.java
new file mode 100644
index 000000000..494ca34ca
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/PaddingTransformer.java
@@ -0,0 +1,164 @@
+/* PaddingTransformer.java --
+ Copyright (C) 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.assembly;
+
+import gnu.javax.crypto.pad.IPad;
+import gnu.javax.crypto.pad.WrongPaddingException;
+
+import java.util.Map;
+
+/**
+ * An Adapter to use any {@link IPad} as a {@link Transformer} in an
+ * {@link Assembly}.
+ * <p>
+ * When using such a {@link Transformer}, in an {@link Assembly}, there must
+ * be at least one element behind this instance in the constructed chain;
+ * otherwise, a {@link TransformerException} is thrown at initialisation time.
+ */
+class PaddingTransformer
+ extends Transformer
+{
+ private IPad delegate;
+
+ private int outputBlockSize = 1;
+
+ PaddingTransformer(IPad padding)
+ {
+ super();
+
+ this.delegate = padding;
+ }
+
+ void initDelegate(Map attributes) throws TransformerException
+ {
+ if (tail == null)
+ {
+ IllegalStateException cause = new IllegalStateException(
+ "Padding transformer missing its tail!");
+ throw new TransformerException("initDelegate()", cause);
+ }
+ outputBlockSize = tail.currentBlockSize();
+ delegate.init(outputBlockSize);
+ }
+
+ int delegateBlockSize()
+ {
+ return outputBlockSize;
+ }
+
+ void resetDelegate()
+ {
+ delegate.reset();
+ outputBlockSize = 1;
+ }
+
+ byte[] updateDelegate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ inBuffer.write(in, offset, length);
+ byte[] tmp = inBuffer.toByteArray();
+ inBuffer.reset();
+ byte[] result;
+ if (wired == Direction.FORWARD) // padding
+ {
+ // buffers remaining bytes from (inBuffer + in) that are less than 1
+ // block
+ if (tmp.length < outputBlockSize)
+ {
+ inBuffer.write(tmp, 0, tmp.length);
+ result = new byte[0];
+ }
+ else
+ {
+ int newlen = outputBlockSize * (tmp.length / outputBlockSize);
+ inBuffer.write(tmp, newlen, tmp.length - newlen);
+ result = new byte[newlen];
+ System.arraycopy(tmp, 0, result, 0, newlen);
+ }
+ }
+ else // unpadding
+ {
+ // always keep in own buffer a max of 1 block to cater for lastUpdate
+ if (tmp.length < outputBlockSize)
+ {
+ inBuffer.write(tmp, 0, tmp.length);
+ result = new byte[0];
+ }
+ else
+ {
+ result = new byte[tmp.length - outputBlockSize];
+ System.arraycopy(tmp, 0, result, 0, result.length);
+ inBuffer.write(tmp, result.length, outputBlockSize);
+ }
+ }
+ return result;
+ }
+
+ byte[] lastUpdateDelegate() throws TransformerException
+ {
+ byte[] result;
+ // process multiples of blocksize as much as possible
+ // catenate result from processing inBuffer with last-update( tail )
+ if (wired == Direction.FORWARD) // padding
+ {
+ result = inBuffer.toByteArray();
+ byte[] padding = delegate.pad(result, 0, result.length);
+ inBuffer.write(padding, 0, padding.length);
+ }
+ else // unpadding
+ {
+ byte[] tmp = inBuffer.toByteArray();
+ inBuffer.reset();
+ int realLength;
+ try
+ {
+ realLength = tmp.length; // should be outputBlockSize
+ realLength -= delegate.unpad(tmp, 0, tmp.length);
+ }
+ catch (WrongPaddingException x)
+ {
+ throw new TransformerException("lastUpdateDelegate()", x);
+ }
+ inBuffer.write(tmp, 0, realLength);
+ }
+ result = inBuffer.toByteArray();
+ inBuffer.reset();
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/Stage.java b/libjava/classpath/gnu/javax/crypto/assembly/Stage.java
new file mode 100644
index 000000000..5d0ab5353
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/Stage.java
@@ -0,0 +1,202 @@
+/* Stage.java --
+ Copyright (C) 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.assembly;
+
+import gnu.javax.crypto.mode.IMode;
+
+import java.security.InvalidKeyException;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A <i>Stage</i> in a Cascade Cipher.
+ * <p>
+ * Each stage may be either an implementation of a Block Cipher Mode of
+ * Operation ({@link IMode}) or another Cascade Cipher ({@link Cascade}).
+ * Each stage has also a <i>natural</i> operational direction when constructed
+ * for inclusion within a {@link Cascade}. This <i>natural</i> direction
+ * dictates how data flows from one stage into another when stages are chained
+ * together in a cascade. One can think of a stage and its natural direction as
+ * the specification of how to wire the stage into the chain. The following
+ * diagrams may help understand the paradigme. The first shows two stages
+ * chained each with a {@link Direction#FORWARD} direction.
+ *
+ * <pre>
+ * FORWARD FORWARD
+ * +------+ +-------+
+ * | | | |
+ * | +--in --+ | +--in --+
+ * ---+ | Stage | | | Stage | +---
+ * +--out--+ | +--out--+ |
+ * | | | |
+ * +-------+ +------+
+ * </pre>
+ *
+ * <p>
+ * The second diagram shows two stages, one in a {@link Direction#FORWARD}
+ * direction, while the other is wired in a {@link Direction#REVERSED}
+ * direction.
+ *
+ * <pre>
+ * FORWARD REVERSED
+ * +------+ +------+
+ * | | | |
+ * | +--in --+ +--in --+ |
+ * ---+ | Stage | | Stage | +---
+ * +--out--+ +--out--+
+ * | |
+ * +---------------+
+ * </pre>
+ *
+ * @see ModeStage
+ * @see CascadeStage
+ */
+public abstract class Stage
+{
+ public static final String DIRECTION = "gnu.crypto.assembly.stage.direction";
+
+ protected Direction forward;
+
+ protected Direction wired;
+
+ protected Stage(Direction forwardDirection)
+ {
+ super();
+
+ this.forward = forwardDirection;
+ this.wired = null;
+ }
+
+ public static final Stage getInstance(IMode mode, Direction forwardDirection)
+ {
+ return new ModeStage(mode, forwardDirection);
+ }
+
+ public static final Stage getInstance(Cascade cascade,
+ Direction forwardDirection)
+ {
+ return new CascadeStage(cascade, forwardDirection);
+ }
+
+ /**
+ * Returns the {@link Set} of supported block sizes for this
+ * <code>Stage</code>. Each element in the returned {@link Set} is an
+ * instance of {@link Integer}.
+ *
+ * @return a {@link Set} of supported block sizes.
+ */
+ public abstract Set blockSizes();
+
+ /**
+ * Initialises the stage for operation with specific characteristics.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalStateException if the instance is already initialised.
+ * @throws InvalidKeyException if the key data is invalid.
+ */
+ public void init(Map attributes) throws InvalidKeyException
+ {
+ if (wired != null)
+ throw new IllegalStateException();
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == null)
+ {
+ flow = Direction.FORWARD;
+ attributes.put(DIRECTION, flow);
+ }
+ initDelegate(attributes);
+ wired = flow;
+ }
+
+ /**
+ * Returns the currently set block size for the stage.
+ *
+ * @return the current block size for this stage.
+ * @throws IllegalStateException if the instance is not initialised.
+ */
+ public abstract int currentBlockSize() throws IllegalStateException;
+
+ /**
+ * Resets the stage for re-initialisation and use with other characteristics.
+ * This method always succeeds.
+ */
+ public void reset()
+ {
+ resetDelegate();
+ wired = null;
+ }
+
+ /**
+ * Processes exactly one block of <i>plaintext</i> (if initialised in the
+ * {@link Direction#FORWARD} state) or <i>ciphertext</i> (if initialised in
+ * the {@link Direction#REVERSED} state).
+ *
+ * @param in the plaintext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the ciphertext.
+ * @param outOffset index of <code>out</code> from which to store result.
+ * @throws IllegalStateException if the instance is not initialised.
+ */
+ public void update(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ if (wired == null)
+ throw new IllegalStateException();
+ updateDelegate(in, inOffset, out, outOffset);
+ }
+
+ /**
+ * Conducts a simple <i>correctness</i> test that consists of basic symmetric
+ * encryption / decryption test(s) for all supported block and key sizes of
+ * underlying block cipher(s) wrapped by Mode leafs. The test also includes
+ * one (1) variable key Known Answer Test (KAT) for each block cipher.
+ *
+ * @return <code>true</code> if the implementation passes simple
+ * <i>correctness</i> tests. Returns <code>false</code> otherwise.
+ */
+ public abstract boolean selfTest();
+
+ abstract void initDelegate(Map attributes) throws InvalidKeyException;
+
+ abstract void resetDelegate();
+
+ abstract void updateDelegate(byte[] in, int inOffset, byte[] out,
+ int outOffset);
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/Transformer.java b/libjava/classpath/gnu/javax/crypto/assembly/Transformer.java
new file mode 100644
index 000000000..1937f9950
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/Transformer.java
@@ -0,0 +1,421 @@
+/* Transformer.java --
+ Copyright (C) 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.assembly;
+
+import gnu.javax.crypto.pad.IPad;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Map;
+
+/**
+ * A <code>Transformer</code> is an abstract representation of a two-way
+ * <i>transformation</i> that can be chained together with other instances of
+ * this type. Examples of such transformations in this library are:
+ * {@link Cascade} cipher, {@link gnu.javax.crypto.pad.IPad} algorithm, and a
+ * ZLib-based deflater/inflater algorithm. A special implementation of a
+ * <code>Transformer</code> to close a chain is also provided.
+ * <p>
+ * A <code>Transformer</code> is characterised by the followings:
+ * <ul>
+ * <li>It can be chained to other instances, to form an {@link Assembly}.</li>
+ * <li>When configured in an {@link Assembly}, it can be set to apply its
+ * internal transformation on the input data stream before (pre-processing) or
+ * after (post-processing) passing the input data to the next element in the
+ * chain. Note that the same type <code>Transformer</code> can be used as
+ * either in pre-processing or a post-processing modes.</li>
+ * <li>A special transformer --<code>LoopbackTransformer</code>-- is used
+ * to close the chain.</li>
+ * <li>A useful type of <code>Transformer</code> --one we're interested in--
+ * has internal buffers. The distinction between a casual push (update)
+ * operation and the last one allows to correctly flush any intermediate bytes
+ * that may exist in those buffers.</li>
+ * </ul>
+ * <p>
+ * To allow wiring <code>Transformer</code> instances together, a
+ * <i>minimal-output-size</i> in bytes is necessary. The trivial case of a
+ * value of <code>1</code> for such attribute practically means that no output
+ * buffering, from the previous element, is needed --which is independant of
+ * buffering the input if the <code>Transformer</code> implementation itself
+ * is block-based.
+ *
+ * @see CascadeTransformer
+ * @see PaddingTransformer
+ * @see DeflateTransformer
+ */
+public abstract class Transformer
+{
+ public static final String DIRECTION = "gnu.crypto.assembly.transformer.direction";
+
+ protected Direction wired;
+
+ protected Operation mode;
+
+ protected Transformer tail = null;
+
+ protected ByteArrayOutputStream inBuffer = new ByteArrayOutputStream(2048);
+
+ protected ByteArrayOutputStream outBuffer = new ByteArrayOutputStream(2048);
+
+ /** Trivial protected constructor. */
+ protected Transformer()
+ {
+ super();
+
+ this.wired = null;
+ }
+
+ public static final Transformer getCascadeTransformer(Cascade cascade)
+ {
+ return new CascadeTransformer(cascade);
+ }
+
+ public static final Transformer getPaddingTransformer(IPad padding)
+ {
+ return new PaddingTransformer(padding);
+ }
+
+ public static final Transformer getDeflateTransformer()
+ {
+ return new DeflateTransformer();
+ }
+
+ /**
+ * Sets the operational mode of this <code>Transformer</code>.
+ *
+ * @param mode the processing mode this <code>Transformer</code> is required
+ * to operate in.
+ * @throws IllegalStateException if this instance has already been assigned an
+ * operational mode.
+ */
+ public void setMode(final Operation mode)
+ {
+ if (this.mode != null)
+ throw new IllegalStateException();
+ this.mode = mode;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Transformer</code> was wired in
+ * pre-processing mode; <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this <code>Transformer</code> has been
+ * wired in pre-processing mode; <code>false</code> otherwise.
+ * @throws IllegalStateException if this instance has not yet been assigned an
+ * operational <i>type</i>.
+ */
+ public boolean isPreProcessing()
+ {
+ if (mode == null)
+ throw new IllegalStateException();
+ return (mode == Operation.PRE_PROCESSING);
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Transformer</code> was wired in
+ * post-processing mode; <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this <code>Transformer</code> has been
+ * wired in post-processing mode; <code>false</code> otherwise.
+ * @throws IllegalStateException if this instance has not yet been assigned an
+ * operational <i>type</i>.
+ */
+ public boolean isPostProcessing()
+ {
+ return ! isPreProcessing();
+ }
+
+ /**
+ * Initialises the <code>Transformer</code> for operation with specific
+ * characteristics.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalStateException if the instance is already initialised.
+ */
+ public void init(Map attributes) throws TransformerException
+ {
+ if (wired != null)
+ throw new IllegalStateException();
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == null)
+ flow = Direction.FORWARD;
+ wired = flow;
+ inBuffer.reset();
+ outBuffer.reset();
+ tail.init(attributes); // initialise tail first
+ initDelegate(attributes); // initialise this instance
+ }
+
+ /**
+ * Returns the block-size of this <code>Transformer</code>. A value of
+ * <code>1</code> indicates that this instance is block-agnostic.
+ *
+ * @return the current minimal required block size.
+ */
+ public int currentBlockSize()
+ {
+ if (wired == null)
+ throw new IllegalStateException();
+ return delegateBlockSize();
+ }
+
+ /**
+ * Resets the <code>Transformer</code> for re-initialisation and use with
+ * other characteristics. This method always succeeds.
+ */
+ public void reset()
+ {
+ resetDelegate();
+ wired = null;
+ inBuffer.reset();
+ outBuffer.reset();
+ tail.reset(); // reset tail last
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments, using a byte array of length <code>1</code> whose contents are
+ * the designated byte.
+ *
+ * @param b the byte to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #update(byte[], int, int)
+ */
+ public byte[] update(byte b) throws TransformerException
+ {
+ return update(new byte[] { b }, 0, 1);
+ }
+
+ /**
+ * Convenience method that calls the same method with three arguments. All
+ * bytes in <code>in</code>, starting from index position <code>0</code>
+ * are considered.
+ *
+ * @param in the input data bytes.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #update(byte[], int, int)
+ */
+ public byte[] update(byte[] in) throws TransformerException
+ {
+ return update(in, 0, in.length);
+ }
+
+ /**
+ * Processes a designated number of bytes from a given byte array.
+ *
+ * @param in the input data bytes.
+ * @param offset index of <code>in</code> from which to start considering
+ * data.
+ * @param length the count of bytes to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ */
+ public byte[] update(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ if (wired == null)
+ throw new IllegalStateException();
+ byte[] result = (wired == Direction.FORWARD ? forwardUpdate(in, offset, length)
+ : inverseUpdate(in, offset, length));
+ return result;
+ }
+
+ /**
+ * Convenience method that calls the same method with three arguments. A
+ * zero-long byte array is used.
+ *
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate() throws TransformerException
+ {
+ byte[] result = (wired == Direction.FORWARD ? lastForwardUpdate()
+ : lastInverseUpdate());
+ if (inBuffer.size() != 0) // we still have some buffered bytes
+ throw new TransformerException("lastUpdate(): input buffer not empty");
+ return result;
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments, using a byte array of length <code>1</code> whose contents are
+ * the designated byte.
+ *
+ * @param b the byte to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate(byte b) throws TransformerException
+ {
+ return lastUpdate(new byte[] { b }, 0, 1);
+ }
+
+ /**
+ * Convenience method that calls the same method with three arguments. All
+ * bytes in <code>in</code>, starting from index position <code>0</code>
+ * are considered.
+ *
+ * @param in the input data bytes.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate(byte[] in) throws TransformerException
+ {
+ return lastUpdate(in, 0, in.length);
+ }
+
+ /**
+ * Processes a designated number of bytes from a given byte array and signals,
+ * at the same time, that this is the last <i>push</i> operation on this
+ * <code>Transformer</code>.
+ *
+ * @param in the input data bytes.
+ * @param offset index of <code>in</code> from which to start considering
+ * data.
+ * @param length the count of bytes to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ */
+ public byte[] lastUpdate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ byte[] result = update(in, offset, length);
+ byte[] rest = lastUpdate();
+ if (rest.length > 0)
+ {
+ byte[] newResult = new byte[result.length + rest.length];
+ System.arraycopy(result, 0, newResult, 0, result.length);
+ System.arraycopy(rest, 0, newResult, result.length, rest.length);
+ result = newResult;
+ }
+ return result;
+ }
+
+ private byte[] forwardUpdate(byte[] in, int off, int len)
+ throws TransformerException
+ {
+ return (isPreProcessing() ? preTransform(in, off, len)
+ : postTransform(in, off, len));
+ }
+
+ private byte[] inverseUpdate(byte[] in, int off, int len)
+ throws TransformerException
+ {
+ return (isPreProcessing() ? postTransform(in, off, len)
+ : preTransform(in, off, len));
+ }
+
+ private byte[] preTransform(byte[] in, int off, int len)
+ throws TransformerException
+ {
+ byte[] result = updateDelegate(in, off, len);
+ result = tail.update(result);
+ return result;
+ }
+
+ private byte[] postTransform(byte[] in, int off, int len)
+ throws TransformerException
+ {
+ byte[] result = tail.update(in, off, len);
+ result = updateDelegate(result, 0, result.length);
+ return result;
+ }
+
+ private byte[] lastForwardUpdate() throws TransformerException
+ {
+ return (isPreProcessing() ? preLastTransform() : postLastTransform());
+ }
+
+ private byte[] lastInverseUpdate() throws TransformerException
+ {
+ return (isPreProcessing() ? postLastTransform() : preLastTransform());
+ }
+
+ private byte[] preLastTransform() throws TransformerException
+ {
+ byte[] result = lastUpdateDelegate();
+ result = tail.lastUpdate(result);
+ return result;
+ }
+
+ private byte[] postLastTransform() throws TransformerException
+ {
+ byte[] result = tail.lastUpdate();
+ result = updateDelegate(result, 0, result.length);
+ byte[] rest = lastUpdateDelegate();
+ if (rest.length > 0)
+ {
+ byte[] newResult = new byte[result.length + rest.length];
+ System.arraycopy(result, 0, newResult, 0, result.length);
+ System.arraycopy(rest, 0, newResult, result.length, rest.length);
+ result = newResult;
+ }
+ return result;
+ }
+
+ abstract void initDelegate(Map attributes) throws TransformerException;
+
+ abstract int delegateBlockSize();
+
+ abstract void resetDelegate();
+
+ abstract byte[] updateDelegate(byte[] in, int off, int len)
+ throws TransformerException;
+
+ abstract byte[] lastUpdateDelegate() throws TransformerException;
+}
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/TransformerException.java b/libjava/classpath/gnu/javax/crypto/assembly/TransformerException.java
new file mode 100644
index 000000000..295fded7b
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/assembly/TransformerException.java
@@ -0,0 +1,140 @@
+/* TransformerException.java --
+ Copyright (C) 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.assembly;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ */
+public class TransformerException
+ extends Exception
+{
+ private Throwable _exception = null;
+
+ public TransformerException()
+ {
+ super();
+ }
+
+ public TransformerException(String details)
+ {
+ super(details);
+ }
+
+ public TransformerException(Throwable cause)
+ {
+ super();
+
+ this._exception = cause;
+ }
+
+ public TransformerException(String details, Throwable cause)
+ {
+ super(details);
+
+ this._exception = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return _exception;
+ }
+
+ /**
+ * Prints this exception's stack trace to <code>System.err</code>. If this
+ * exception has a root exception; the stack trace of the root exception is
+ * also printed to <code>System.err</code>.
+ */
+ public void printStackTrace()
+ {
+ super.printStackTrace();
+ if (_exception != null)
+ _exception.printStackTrace();
+ }
+
+ /**
+ * Prints this exception's stack trace to a print stream. If this exception
+ * has a root exception; the stack trace of the root exception is also printed
+ * to the print stream.
+ *
+ * @param ps the non-null print stream to which to print.
+ */
+ public void printStackTrace(PrintStream ps)
+ {
+ super.printStackTrace(ps);
+ if (_exception != null)
+ _exception.printStackTrace(ps);
+ }
+
+ /**
+ * Prints this exception's stack trace to a print writer. If this exception
+ * has a root exception; the stack trace of the root exception is also printed
+ * to the print writer.
+ *
+ * @param pw the non-null print writer to use for output.
+ */
+ public void printStackTrace(PrintWriter pw)
+ {
+ super.printStackTrace(pw);
+ if (_exception != null)
+ _exception.printStackTrace(pw);
+ }
+
+ /**
+ * Returns the string representation of this exception. The string
+ * representation contains this exception's class name, its detailed messsage,
+ * and if it has a root exception, the string representation of the root
+ * exception. This string representation is meant for debugging and not meant
+ * to be interpreted programmatically.
+ *
+ * @return the non-null string representation of this exception.
+ * @see Throwable#getMessage()
+ */
+ public String toString()
+ {
+ CPStringBuilder sb = new CPStringBuilder(this.getClass().getName())
+ .append(": ").append(super.toString());
+ if (_exception != null)
+ sb.append("; caused by: ").append(_exception.toString());
+ return sb.toString();
+ }
+}