From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- .../classpath/gnu/javax/crypto/mode/BaseMode.java | 295 +++++++++++++++++++++ libjava/classpath/gnu/javax/crypto/mode/CBC.java | 123 +++++++++ libjava/classpath/gnu/javax/crypto/mode/CFB.java | 155 +++++++++++ libjava/classpath/gnu/javax/crypto/mode/CTR.java | 168 ++++++++++++ libjava/classpath/gnu/javax/crypto/mode/EAX.java | 289 ++++++++++++++++++++ libjava/classpath/gnu/javax/crypto/mode/ECB.java | 121 +++++++++ .../gnu/javax/crypto/mode/IAuthenticatedMode.java | 56 ++++ libjava/classpath/gnu/javax/crypto/mode/ICM.java | 181 +++++++++++++ libjava/classpath/gnu/javax/crypto/mode/IMode.java | 123 +++++++++ .../gnu/javax/crypto/mode/ModeFactory.java | 151 +++++++++++ libjava/classpath/gnu/javax/crypto/mode/OFB.java | 174 ++++++++++++ 11 files changed, 1836 insertions(+) create mode 100644 libjava/classpath/gnu/javax/crypto/mode/BaseMode.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/CBC.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/CFB.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/CTR.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/EAX.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/ECB.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/IAuthenticatedMode.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/ICM.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/IMode.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/ModeFactory.java create mode 100644 libjava/classpath/gnu/javax/crypto/mode/OFB.java (limited to 'libjava/classpath/gnu/javax/crypto/mode') diff --git a/libjava/classpath/gnu/javax/crypto/mode/BaseMode.java b/libjava/classpath/gnu/javax/crypto/mode/BaseMode.java new file mode 100644 index 000000000..831dd9664 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/BaseMode.java @@ -0,0 +1,295 @@ +/* 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.java.lang.CPStringBuilder; + +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; + +/** + * A basic abstract class to facilitate implementing block cipher modes of + * operations. + */ +public abstract class BaseMode + implements IMode +{ + /** 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(); + + /** + * Trivial constructor for use by concrete subclasses. + * + * @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; + } + + 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(); + } + } + } + + public String name() + { + return new CPStringBuilder(name).append('(').append(cipher.name()).append(')') + .toString(); + } + + /** + * 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 + * init() methods, a Mode 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. + * + * @return the default value, in bytes, of the mode's block size. + * @see ModeFactory + */ + public int defaultBlockSize() + { + return cipherBlockSize; + } + + /** + * Returns the default value, in bytes, of the underlying block cipher key + * size. + * + * @return the default value, in bytes, of the underlying cipher's key size. + */ + public int defaultKeySize() + { + return cipher.defaultKeySize(); + } + + /** + * Returns an {@link Iterator} over the supported block sizes. Each element + * returned by this object is an {@link Integer}. + *

+ * 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. + * + * @return an {@link Iterator} over the supported block sizes. + */ + public Iterator blockSizes() + { + ArrayList al = new ArrayList(); + al.add(Integer.valueOf(cipherBlockSize)); + return Collections.unmodifiableList(al).iterator(); + } + + /** + * Returns an {@link Iterator} over the supported underlying block cipher key + * sizes. Each element returned by this object is an instance of + * {@link Integer}. + * + * @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; + } + + 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); + + 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, Integer.valueOf(cipherBlockSize)); + map.put(STATE, Integer.valueOf(ENCRYPTION)); + map.put(IV, iv); + map.put(MODE_BLOCK_SIZE, Integer.valueOf(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, Integer.valueOf(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; + } + } +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/CBC.java b/libjava/classpath/gnu/javax/crypto/mode/CBC.java new file mode 100644 index 000000000..31c445f4e --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/CBC.java @@ -0,0 +1,123 @@ +/* CBC.java -- + Copyright (C) 2002, 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.java.security.Registry; +import gnu.javax.crypto.cipher.IBlockCipher; + +/** + * The Cipher Block Chaining mode. This mode introduces feedback into the cipher + * by XORing the previous ciphertext block with the plaintext block before + * encipherment. That is, encrypting looks like this: + * + *

+ *  Ci = EK(Piˆ Ci-1)
+ * 
+ *

+ * Similarly, decrypting is: + *

+ *  Pi = Ci-1 ˆ DK(Ci)
+ * 
+ */ +public class CBC + extends BaseMode + implements Cloneable +{ + /** The last (de|en)crypted block */ + private byte[] lastBlock; + /** An intermediate buffer. */ + private byte[] scratch; + + /** + * Package-private constructor for the factory class. + * + * @param underlyingCipher The cipher implementation. + * @param cipherBlockSize The cipher's block size. + */ + CBC(IBlockCipher underlyingCipher, int cipherBlockSize) + { + super(Registry.CBC_MODE, underlyingCipher, cipherBlockSize); + } + + /** Our constructor for cloning. */ + private CBC(CBC that) + { + this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize); + } + + public Object clone() + { + return new CBC(this); + } + + public void setup() + { + if (modeBlockSize != cipherBlockSize) + throw new IllegalArgumentException(); + scratch = new byte[cipherBlockSize]; + lastBlock = new byte[cipherBlockSize]; + // lastBlock gets initialized to the initialization vector. + for (int i = 0; i < lastBlock.length && i < iv.length; i++) + lastBlock[i] = iv[i]; + } + + public void teardown() + { + lastBlock = null; + scratch = null; + } + + public void encryptBlock(byte[] in, int i, byte[] out, int o) + { + for (int k = 0; k < scratch.length; k++) + scratch[k] = (byte)(lastBlock[k] ^ in[k + i]); + cipher.encryptBlock(scratch, 0, out, o); + System.arraycopy(out, o, lastBlock, 0, cipherBlockSize); + } + + public void decryptBlock(byte[] in, int i, byte[] out, int o) + { + byte[] buf = new byte[cipherBlockSize]; + System.arraycopy(in, i, buf, 0, cipherBlockSize); + cipher.decryptBlock(in, i, scratch, 0); + for (int k = 0; k < scratch.length; k++) + out[o + k] = (byte)(lastBlock[k] ^ scratch[k]); + System.arraycopy(buf, 0, lastBlock, 0, cipherBlockSize); + } +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/CFB.java b/libjava/classpath/gnu/javax/crypto/mode/CFB.java new file mode 100644 index 000000000..c5f06e11c --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/CFB.java @@ -0,0 +1,155 @@ +/* CFB.java -- + Copyright (C) 2002, 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.java.security.Registry; +import gnu.javax.crypto.cipher.IBlockCipher; + +/** + * The cipher feedback mode. CFB mode is a stream mode that operates on s + * bit blocks, where 1 <= s <= b, if b is the + * underlying cipher's block size. Encryption is: + *
+ *  I[1] = IV
+ *  I[j] = LSB(b-s, I[j-1]) | C[j-1]   for j = 2...n
+ *  O[j] = CIPH(K, I[j])               for j = 1,2...n
+ *  C[j] = P[j] ˆ MSB(s, O[j])         for j = 1,2...n
+ * 
+ *

+ * And decryption is: + *

+ *  I[1] = IV
+ *  I[j] = LSB(b-s, I[j-1]) | C[j-1]   for j = 2...n
+ *  O[j] = CIPH(K, I[j])               for j = 1,2...n
+ *  P[j] = C[j] ˆ MSB(s, O[j])         for j = 1,2...n
+ * 
+ *

+ * CFB mode requires an initialization vector, which need not be kept secret. + *

+ * References: + *

    + *
  1. Bruce Schneier, Applied Cryptography: Protocols, Algorithms, and + * Source Code in C, Second Edition. (1996 John Wiley and Sons) ISBN + * 0-471-11709-9.
  2. + *
  3. + * Recommendation for Block Cipher Modes of Operation Methods and Techniques, + * Morris Dworkin.
  4. + *
+ */ +public class CFB + extends BaseMode +{ + /** The shift register, the input block to the block cipher. */ + private byte[] shiftRegister; + /** The output block from the block cipher. */ + private byte[] scratch; + + /** + * Package-private constructor for the factory class. + * + * @param underlyingCipher The cipher implementation. + * @param cipherBlockSize The cipher's block size. + */ + CFB(IBlockCipher underlyingCipher, int cipherBlockSize) + { + super(Registry.CFB_MODE, underlyingCipher, cipherBlockSize); + } + + /** + * Cloneing constructor. + * + * @param that The instance being cloned. + */ + private CFB(CFB that) + { + this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize); + } + + public Object clone() + { + return new CFB(this); + } + + public void setup() + { + if (modeBlockSize > cipherBlockSize) + throw new IllegalArgumentException( + "CFB block size cannot be larger than the cipher block size"); + shiftRegister = new byte[cipherBlockSize]; + scratch = new byte[cipherBlockSize]; + System.arraycopy(iv, 0, + shiftRegister, 0, + Math.min(iv.length, cipherBlockSize)); + } + + public void teardown() + { + if (shiftRegister != null) + for (int i = 0; i < shiftRegister.length; i++) + shiftRegister[i] = 0; + shiftRegister = null; + } + + public void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) + { + cipher.encryptBlock(shiftRegister, 0, scratch, 0); + for (int i = 0; i < modeBlockSize; i++) + out[outOffset + i] = (byte)(in[inOffset + i] ^ scratch[i]); + System.arraycopy(shiftRegister, modeBlockSize, + shiftRegister, 0, + cipherBlockSize - modeBlockSize); + System.arraycopy(out, outOffset, + shiftRegister, cipherBlockSize - modeBlockSize, + modeBlockSize); + } + + public void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) + { + cipher.encryptBlock(shiftRegister, 0, scratch, 0); + for (int i = 0; i < modeBlockSize; i++) + out[outOffset + i] = (byte)(in[inOffset + i] ^ scratch[i]); + System.arraycopy(shiftRegister, modeBlockSize, + shiftRegister, 0, + cipherBlockSize - modeBlockSize); + System.arraycopy(in, inOffset, + shiftRegister, cipherBlockSize - modeBlockSize, + modeBlockSize); + } +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/CTR.java b/libjava/classpath/gnu/javax/crypto/mode/CTR.java new file mode 100644 index 000000000..56ea58c25 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/CTR.java @@ -0,0 +1,168 @@ +/* CTR.java -- + Copyright (C) 2001, 2002, 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.java.security.Registry; +import gnu.java.security.util.Sequence; +import gnu.javax.crypto.cipher.IBlockCipher; + +import java.util.Arrays; +import java.util.Iterator; + +/** + * The implementation of the Counter Mode. + *

+ * The algorithm steps are formally described as follows: + * + *

+ *     CTR Encryption: O[j] = E(K)(T[j]); for j = 1, 2...n;
+ *                     C[j] = P[j] ˆ O[j]; for j = 1, 2...n.
+ *     CTR Decryption: O[j] = E(K)(T[j]); for j = 1, 2...n;
+ *                     P[j] = C[j] ˆ O[j]; for j = 1, 2...n.
+ * 
+ * + *

+ * where P is the plaintext, C is the ciphertext, + * E(K) is the underlying block cipher encryption function + * parametrised with the session key K, and T is + * the Counter. + *

+ * This implementation, uses a standard incrementing function with a step of 1, + * and an initial value similar to that described in the NIST document. + *

+ * References: + *

    + *
  1. + * Recommendation for Block Cipher Modes of Operation Methods and Techniques, + * Morris Dworkin.
  2. + *
+ */ +public class CTR + extends BaseMode + implements Cloneable +{ + private int off; + private byte[] counter, enc; + + /** + * Trivial package-private constructor for use by the Factory class. + * + * @param underlyingCipher the underlying cipher implementation. + * @param cipherBlockSize the underlying cipher block size to use. + */ + CTR(IBlockCipher underlyingCipher, int cipherBlockSize) + { + super(Registry.CTR_MODE, underlyingCipher, cipherBlockSize); + } + + /** + * Private constructor for cloning purposes. + * + * @param that the instance to clone. + */ + private CTR(CTR that) + { + this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize); + } + + public Object clone() + { + return new CTR(this); + } + + public void setup() + { + if (modeBlockSize > cipherBlockSize) + throw new IllegalArgumentException("mode size exceeds cipher block size"); + off = 0; + counter = new byte[cipherBlockSize]; + int i = cipherBlockSize - 1; + int j = iv.length - 1; + while (i >= 0 && j >= 0) + counter[i--] = iv[j--]; + enc = new byte[cipherBlockSize]; + cipher.encryptBlock(counter, 0, enc, 0); + } + + public void teardown() + { + if (counter != null) + Arrays.fill(counter, (byte) 0); + if (enc != null) + Arrays.fill(enc, (byte) 0); + } + + public void encryptBlock(byte[] in, int i, byte[] out, int o) + { + ctr(in, i, out, o); + } + + public void decryptBlock(byte[] in, int i, byte[] out, int o) + { + ctr(in, i, out, o); + } + + public Iterator blockSizes() + { + return new Sequence(1, cipherBlockSize).iterator(); + } + + private void ctr(byte[] in, int inOffset, byte[] out, int outOffset) + { + for (int i = 0; i < modeBlockSize; i++) + { + out[outOffset++] = (byte)(in[inOffset++] ^ enc[off++]); + if (off == cipherBlockSize) + { + int j; + for (j = cipherBlockSize - 1; j >= 0; j--) + { + counter[j]++; + if ((counter[j] & 0xFF) != 0) + break; + } + if (j == 0) + counter[cipherBlockSize - 1]++; + off = 0; + cipher.encryptBlock(counter, 0, enc, 0); + } + } + } +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/EAX.java b/libjava/classpath/gnu/javax/crypto/mode/EAX.java new file mode 100644 index 000000000..b3e4a6a4e --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/EAX.java @@ -0,0 +1,289 @@ +/* EAX.java -- + Copyright (C) 2004, 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.java.security.Registry; +import gnu.javax.crypto.cipher.IBlockCipher; +import gnu.javax.crypto.mac.IMac; +import gnu.javax.crypto.mac.MacFactory; + +import java.security.InvalidKeyException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * A conventional two-pass authenticated-encrypted mode, EAX. EAX is a + * Authenticated Encryption with Additional Data (AEAD) scheme, + * which provides protection and authentication for the message, and provides + * authentication of an (optional) header. EAX is composed of the counter mode + * (CTR) and the one-key CBC MAC (OMAC). + *

+ * This class makes full use of the {@link IAuthenticatedMode} interface, that + * is, all methods of both {@link IMode} and {@link IMac} can be used as + * specified in the {@link IAuthenticatedMode} interface. + *

+ * References: + *

    + *
  1. M. Bellare, P. Rogaway, and D. Wagner; A + * Conventional Authenticated-Encryption Mode.
  2. + *
+ */ +public class EAX + implements IAuthenticatedMode +{ + /** The tag size, in bytes. */ + private int tagSize; + /** The nonce OMAC instance. */ + private IMac nonceOmac; + /** The header OMAC instance. */ + private IMac headerOmac; + /** The message OMAC instance. */ + private IMac msgOmac; + /** The CTR instance. */ + private IMode ctr; + /** The direction state (encrypting or decrypting). */ + private int state; + /** Whether we're initialized or not. */ + private boolean init; + /** The cipher block size. */ + private int cipherBlockSize; + /** The cipher. */ + private IBlockCipher cipher; + /** The [t]_n array. */ + private byte[] t_n; + private static boolean valid = false; + + public EAX(IBlockCipher cipher, int cipherBlockSize) + { + this.cipher = cipher; + this.cipherBlockSize = cipherBlockSize; + String name = cipher.name(); + int i = name.indexOf('-'); + if (i >= 0) + name = name.substring(0, i); + String omacname = Registry.OMAC_PREFIX + name; + nonceOmac = MacFactory.getInstance(omacname); + headerOmac = MacFactory.getInstance(omacname); + msgOmac = MacFactory.getInstance(omacname); + ctr = ModeFactory.getInstance(Registry.CTR_MODE, cipher, cipherBlockSize); + t_n = new byte[cipherBlockSize]; + init = false; + } + + public Object clone() + { + return new EAX((IBlockCipher) cipher.clone(), cipherBlockSize); + } + + public String name() + { + return Registry.EAX_MODE + "(" + cipher.name() + ")"; + } + + public int defaultBlockSize() + { + return ctr.defaultBlockSize(); + } + + public int defaultKeySize() + { + return ctr.defaultKeySize(); + } + + public Iterator blockSizes() + { + return ctr.blockSizes(); + } + + public Iterator keySizes() + { + return ctr.keySizes(); + } + + public void init(Map attrib) throws InvalidKeyException + { + byte[] nonce = (byte[]) attrib.get(IV); + if (nonce == null) + throw new IllegalArgumentException("no nonce provided"); + byte[] key = (byte[]) attrib.get(KEY_MATERIAL); + if (key == null) + throw new IllegalArgumentException("no key provided"); + + Arrays.fill(t_n, (byte) 0); + nonceOmac.reset(); + nonceOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key)); + nonceOmac.update(t_n, 0, t_n.length); + nonceOmac.update(nonce, 0, nonce.length); + byte[] N = nonceOmac.digest(); + nonceOmac.reset(); + nonceOmac.update(t_n, 0, t_n.length); + nonceOmac.update(nonce, 0, nonce.length); + t_n[t_n.length - 1] = 1; + headerOmac.reset(); + headerOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key)); + headerOmac.update(t_n, 0, t_n.length); + t_n[t_n.length - 1] = 2; + msgOmac.reset(); + msgOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key)); + msgOmac.update(t_n, 0, t_n.length); + Integer modeSize = (Integer) attrib.get(MODE_BLOCK_SIZE); + if (modeSize == null) + modeSize = Integer.valueOf(cipherBlockSize); + HashMap ctrAttr = new HashMap(); + ctrAttr.put(KEY_MATERIAL, key); + ctrAttr.put(IV, N); + ctrAttr.put(STATE, Integer.valueOf(ENCRYPTION)); + ctrAttr.put(MODE_BLOCK_SIZE, modeSize); + ctr.reset(); + ctr.init(ctrAttr); + Integer st = (Integer) attrib.get(STATE); + if (st != null) + { + state = st.intValue(); + if (state != ENCRYPTION && state != DECRYPTION) + throw new IllegalArgumentException("invalid state"); + } + else + state = ENCRYPTION; + + Integer ts = (Integer) attrib.get(TRUNCATED_SIZE); + if (ts != null) + tagSize = ts.intValue(); + else + tagSize = cipherBlockSize; + if (tagSize < 0 || tagSize > cipherBlockSize) + throw new IllegalArgumentException("tag size out of range"); + init = true; + } + + public int currentBlockSize() + { + return ctr.currentBlockSize(); + } + + public void encryptBlock(byte[] in, int inOff, byte[] out, int outOff) + { + if (! init) + throw new IllegalStateException("not initialized"); + if (state != ENCRYPTION) + throw new IllegalStateException("not encrypting"); + ctr.update(in, inOff, out, outOff); + msgOmac.update(out, outOff, ctr.currentBlockSize()); + } + + public void decryptBlock(byte[] in, int inOff, byte[] out, int outOff) + { + if (! init) + throw new IllegalStateException("not initialized"); + if (state != DECRYPTION) + throw new IllegalStateException("not decrypting"); + msgOmac.update(in, inOff, ctr.currentBlockSize()); + ctr.update(in, inOff, out, outOff); + } + + public void update(byte[] in, int inOff, byte[] out, int outOff) + { + switch (state) + { + case ENCRYPTION: + encryptBlock(in, inOff, out, outOff); + break; + case DECRYPTION: + decryptBlock(in, inOff, out, outOff); + break; + default: + throw new IllegalStateException("impossible state " + state); + } + } + + public void reset() + { + nonceOmac.reset(); + headerOmac.reset(); + msgOmac.reset(); + ctr.reset(); + } + + public boolean selfTest() + { + return true; // XXX + } + + public int macSize() + { + return tagSize; + } + + public byte[] digest() + { + byte[] tag = new byte[tagSize]; + digest(tag, 0); + return tag; + } + + public void digest(byte[] out, int outOffset) + { + if (outOffset < 0 || outOffset + tagSize > out.length) + throw new IndexOutOfBoundsException(); + byte[] N = nonceOmac.digest(); + byte[] H = headerOmac.digest(); + byte[] M = msgOmac.digest(); + for (int i = 0; i < tagSize; i++) + out[outOffset + i] = (byte)(N[i] ^ H[i] ^ M[i]); + reset(); + } + + public void update(byte b) + { + if (! init) + throw new IllegalStateException("not initialized"); + headerOmac.update(b); + } + + public void update(byte[] buf, int off, int len) + { + if (! init) + throw new IllegalStateException("not initialized"); + headerOmac.update(buf, off, len); + } +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/ECB.java b/libjava/classpath/gnu/javax/crypto/mode/ECB.java new file mode 100644 index 000000000..7e02b0187 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/ECB.java @@ -0,0 +1,121 @@ +/* ECB.java -- + Copyright (C) 2001, 2002, 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.java.security.Registry; +import gnu.javax.crypto.cipher.IBlockCipher; + +/** + * The implementation of the Electronic Codebook mode. + *

+ * The Electronic Codebook (ECB) mode is a confidentiality mode that is defined + * as follows: + *

+ *

+ * In ECB encryption, the forward cipher function is applied directly, and + * independently, to each block of the plaintext. The resulting sequence of + * output blocks is the ciphertext. + *

+ * In ECB decryption, the inverse cipher function is applied directly, and + * independently, to each block of the ciphertext. The resulting sequence of + * output blocks is the plaintext. + *

+ * References: + *

    + *
  1. + * Recommendation for Block Cipher Modes of Operation Methods and Techniques, + * Morris Dworkin.
  2. + *
+ */ +public class ECB + extends BaseMode + implements Cloneable +{ + /** + * Trivial package-private constructor for use by the Factory class. + * + * @param underlyingCipher the underlying cipher implementation. + * @param cipherBlockSize the underlying cipher block size to use. + */ + ECB(IBlockCipher underlyingCipher, int cipherBlockSize) + { + super(Registry.ECB_MODE, underlyingCipher, cipherBlockSize); + } + + /** + * Private constructor for cloning purposes. + * + * @param that the mode to clone. + */ + private ECB(ECB that) + { + this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize); + } + + public Object clone() + { + return new ECB(this); + } + + public void setup() + { + if (modeBlockSize != cipherBlockSize) + throw new IllegalArgumentException(IMode.MODE_BLOCK_SIZE); + } + + public void teardown() + { + } + + public void encryptBlock(byte[] in, int i, byte[] out, int o) + { + cipher.encryptBlock(in, i, out, o); + } + + public void decryptBlock(byte[] in, int i, byte[] out, int o) + { + cipher.decryptBlock(in, i, out, o); + } +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/IAuthenticatedMode.java b/libjava/classpath/gnu/javax/crypto/mode/IAuthenticatedMode.java new file mode 100644 index 000000000..51a5547f2 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/IAuthenticatedMode.java @@ -0,0 +1,56 @@ +/* IAuthenticatedMode.java -- + Copyright (C) 2004, 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.mac.IMac; + +/** + * The interface for encryption modes that also produce a message authentication + * tag. + *

+ * This interface is merely the conjuction of the {@link IMode} and {@link IMac} + * interfaces. Encryption and decryption is done via the + * {@link IMode#update(byte[],int,byte[],int)} method, tag generation is done + * via the {@link IMac#digest()} method, and header updating (if supported by + * the mode) is done via the {@link IMac#update(byte[],int,int)} method. + */ +public interface IAuthenticatedMode + extends IMode, IMac +{ +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/ICM.java b/libjava/classpath/gnu/javax/crypto/mode/ICM.java new file mode 100644 index 000000000..a4737bcdf --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/ICM.java @@ -0,0 +1,181 @@ +/* ICM.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.java.security.Registry; +import gnu.javax.crypto.cipher.IBlockCipher; + +import java.math.BigInteger; + +/** + * An implementation of David McGrew Integer Counter Mode (ICM) as an + * {@link IMode}. + *

+ * ICM is a way to define a pseudorandom keystream generator using a block + * cipher. The keystream can be used for additive encryption, key derivation, or + * any other application requiring pseudorandom data. In the case of this class, + * it is used as additive encryption, XOR-ing the keystream with the input text + * --for both encryption and decryption. + *

+ * In ICM, the keystream is logically broken into segments. Each segment is + * identified with a segment index, and the segments have equal lengths. This + * segmentation makes ICM especially appropriate for securing packet-based + * protocols. ICM also allows a variety of configurations based, among other + * things, on two parameters: the block index length and the segment + * index length. A constraint on those two values exists: The sum of + * segment index length and block index length must not + * half the block size of the underlying cipher. This requirement + * protects the ICM keystream generator from potentially failing to be + * pseudorandom. + *

+ * For simplicity, this implementation, fixes these two values to the following: + *

+ *

+ * For a 128-bit block cipher, the above values imply a maximum keystream length + * of 295,147,905,179,352,825,856 octets, since in ICM, each segment must not + * exceed the value + * (256 ^ block index length) * block length + * octets. + *

+ * Finally, for this implementation of the ICM, the IV placeholder will be used + * to pass the value of the Offset in the keystream segment. + *

+ * References: + *

    + *
  1. + * Integer Counter Mode, David A. McGrew.
  2. + *
+ */ +public class ICM + extends BaseMode + implements Cloneable +{ + /** The integer value 256 as a BigInteger. */ + private static final BigInteger TWO_FIFTY_SIX = new BigInteger("256"); + /** Maximum number of blocks per segment. */ + private BigInteger maxBlocksPerSegment; + /** A work constant. */ + private BigInteger counterRange; + /** The initial counter for a given keystream segment. */ + private BigInteger C0; + /** The index of the next block for a given keystream segment. */ + private BigInteger blockNdx; + + /** + * Trivial package-private constructor for use by the Factory class. + * + * @param underlyingCipher the underlying cipher implementation. + * @param cipherBlockSize the underlying cipher block size to use. + */ + ICM(IBlockCipher underlyingCipher, int cipherBlockSize) + { + super(Registry.ICM_MODE, underlyingCipher, cipherBlockSize); + } + + /** + * Private constructor for cloning purposes. + * + * @param that the instance to clone. + */ + private ICM(ICM that) + { + this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize); + } + + public Object clone() + { + return new ICM(this); + } + + public void setup() + { + if (modeBlockSize != cipherBlockSize) + throw new IllegalArgumentException(); + counterRange = TWO_FIFTY_SIX.pow(cipherBlockSize); + maxBlocksPerSegment = TWO_FIFTY_SIX.pow(cipherBlockSize / 2); + BigInteger r = new BigInteger(1, iv); + C0 = maxBlocksPerSegment.add(r).modPow(BigInteger.ONE, counterRange); + blockNdx = BigInteger.ZERO; + } + + public void teardown() + { + counterRange = null; + maxBlocksPerSegment = null; + C0 = null; + blockNdx = null; + } + + public void encryptBlock(byte[] in, int i, byte[] out, int o) + { + icm(in, i, out, o); + } + + public void decryptBlock(byte[] in, int i, byte[] out, int o) + { + icm(in, i, out, o); + } + + private void icm(byte[] in, int inOffset, byte[] out, int outOffset) + { + if (blockNdx.compareTo(maxBlocksPerSegment) >= 0) + throw new RuntimeException("Maximum blocks for segment reached"); + BigInteger Ci = C0.add(blockNdx).modPow(BigInteger.ONE, counterRange); + byte[] result = Ci.toByteArray(); + int limit = result.length; + int ndx = 0; + if (limit < cipherBlockSize) + { + byte[] data = new byte[cipherBlockSize]; + System.arraycopy(result, 0, data, cipherBlockSize - limit, limit); + result = data; + } + else if (limit > cipherBlockSize) + ndx = limit - cipherBlockSize; + + cipher.encryptBlock(result, ndx, result, ndx); + blockNdx = blockNdx.add(BigInteger.ONE); // increment blockNdx + for (int i = 0; i < modeBlockSize; i++) // xor result with input block + out[outOffset++] = (byte)(in[inOffset++] ^ result[ndx++]); + } +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/IMode.java b/libjava/classpath/gnu/javax/crypto/mode/IMode.java new file mode 100644 index 000000000..72c99ba73 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/IMode.java @@ -0,0 +1,123 @@ +/* IMode.java -- + Copyright (C) 2001, 2002, 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; + +/** + * The basic visible methods of any block cipher mode. + *

+ * Block ciphers encrypt plaintext in fixed size n-bit blocks. For messages + * larger than n bits, the simplest approach is to segment the message into + * n-bit blocks and process (encrypt and/or decrypt) each one separately + * (Electronic Codebook or ECB mode). But this approach has disadvantages in + * most applications. The block cipher modes of operations are one way of + * working around those disadvantages. + *

+ * A Mode always employs an underlying block cipher for processing its + * input. For all intents and purposes, a Mode appears to behave as any + * other block cipher with the following differences: + *

+ *

+ * Possible additional initialisation values for an instance of that type are: + *

+ */ +public interface IMode + extends IBlockCipher +{ + /** + * Property name of the state in which to operate this mode. The value + * associated to this property name is taken to be an {@link Integer} which + * value is either ENCRYPTION or DECRYPTION. + */ + String STATE = "gnu.crypto.mode.state"; + /** + * Property name of the block size in which to operate this mode. The value + * associated with this property name is taken to be an {@link Integer}. If + * it is not specified, the value of the block size of the underlying block + * cipher, used to construct the mode instance, shall be used. + */ + String MODE_BLOCK_SIZE = "gnu.crypto.mode.block.size"; + /** + * Property name of the initialisation vector to use, if required, with this + * instance. The value associated with this property name is taken to be a + * byte array. If the concrete instance needs such a parameter, and it has not + * been specified as part of the initialissation parameters, an all-zero byte + * array of the appropriate size shall be used. + */ + String IV = "gnu.crypto.mode.iv"; + /** Constant indicating the instance is being used for encryption. */ + int ENCRYPTION = 1; + /** Constant indicating the instance is being used for decryption. */ + int DECRYPTION = 2; + + /** + * A convenience method. Effectively invokes the encryptBlock() + * or decryptBlock() method depending on the operational state + * of the instance. + * + * @param in the plaintext. + * @param inOffset index of in from which to start considering + * data. + * @param out the ciphertext. + * @param outOffset index of out from which to store result. + * @exception IllegalStateException if the instance is not initialised. + */ + void update(byte[] in, int inOffset, byte[] out, int outOffset) + throws IllegalStateException; +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/ModeFactory.java b/libjava/classpath/gnu/javax/crypto/mode/ModeFactory.java new file mode 100644 index 000000000..c1108ea11 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/ModeFactory.java @@ -0,0 +1,151 @@ +/* ModeFactory.java -- + Copyright (C) 2001, 2002, 2004, 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.java.security.Registry; + +import gnu.javax.crypto.cipher.CipherFactory; +import gnu.javax.crypto.cipher.IBlockCipher; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * A Factory to instantiate block cipher modes of operations. + */ +public class ModeFactory + implements Registry +{ + private static Set names; + + /** Trivial constructor to enforce Singleton pattern. */ + private ModeFactory() + { + super(); + } + + /** + * Returns an instance of a block cipher mode of operations given its name and + * characteristics of the underlying block cipher. + * + * @param mode the case-insensitive name of the mode of operations. + * @param cipher the case-insensitive name of the block cipher. + * @param cipherBlockSize the block size, in bytes, of the underlying cipher. + * @return an instance of the block cipher algorithm, operating in a given + * mode of operations, or null if none found. + * @exception InternalError if either the mode or the underlying block cipher + * implementation does not pass its self-test. + */ + public static IMode getInstance(String mode, String cipher, + int cipherBlockSize) + { + if (mode == null || cipher == null) + return null; + + mode = mode.trim(); + cipher = cipher.trim(); + IBlockCipher cipherImpl = CipherFactory.getInstance(cipher); + if (cipherImpl == null) + return null; + + return getInstance(mode, cipherImpl, cipherBlockSize); + } + + public static IMode getInstance(String mode, IBlockCipher cipher, + int cipherBlockSize) + { + // ensure that cipherBlockSize is valid for the chosen underlying cipher + boolean ok = false; + for (Iterator it = cipher.blockSizes(); it.hasNext();) + { + ok = (cipherBlockSize == ((Integer) it.next()).intValue()); + if (ok) + break; + } + if (! ok) + throw new IllegalArgumentException("cipherBlockSize"); + IMode result = null; + if (mode.equalsIgnoreCase(ECB_MODE)) + result = new ECB(cipher, cipherBlockSize); + else if (mode.equalsIgnoreCase(CTR_MODE)) + result = new CTR(cipher, cipherBlockSize); + else if (mode.equalsIgnoreCase(ICM_MODE)) + result = new ICM(cipher, cipherBlockSize); + else if (mode.equalsIgnoreCase(OFB_MODE)) + result = new OFB(cipher, cipherBlockSize); + else if (mode.equalsIgnoreCase(CBC_MODE)) + result = new CBC(cipher, cipherBlockSize); + else if (mode.equalsIgnoreCase(CFB_MODE)) + result = new CFB(cipher, cipherBlockSize); + else if (mode.equalsIgnoreCase(EAX_MODE)) + result = new EAX(cipher, cipherBlockSize); + + if (result != null && ! result.selfTest()) + throw new InternalError(result.name()); + + return result; + } + + /** + * Returns a {@link Set} of names of mode supported by this Factory. + * + * @return a {@link Set} of mode names (Strings). + */ + public static final Set getNames() + { + synchronized (ModeFactory.class) + { + if (names == null) + { + HashSet hs = new HashSet(); + hs.add(ECB_MODE); + hs.add(CTR_MODE); + hs.add(ICM_MODE); + hs.add(OFB_MODE); + hs.add(CBC_MODE); + hs.add(CFB_MODE); + hs.add(EAX_MODE); + names = Collections.unmodifiableSet(hs); + } + } + return names; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/mode/OFB.java b/libjava/classpath/gnu/javax/crypto/mode/OFB.java new file mode 100644 index 000000000..087f99132 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mode/OFB.java @@ -0,0 +1,174 @@ +/* OFB.java -- + Copyright (C) 2001, 2002, 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.java.security.Registry; +import gnu.javax.crypto.cipher.IBlockCipher; + +/** + * The Output Feedback (OFB) mode is a confidentiality mode that requires a + * unique IV for every message that is ever encrypted under the + * given key. The OFB mode is defined as follows: + * + *

+ * In OFB encryption, the IV is transformed by the forward cipher + * function to produce the first output block. The first output block is + * exclusive-ORed with the first plaintext block to produce the first ciphertext + * block. The first output block is then transformed by the forward cipher + * function to produce the second output block. The second output block is + * exclusive-ORed with the second plaintext block to produce the second + * ciphertext block, and the second output block is transformed by the forward + * cipher function to produce the third output block. Thus, the successive + * output blocks are produced from enciphering the previous output blocks, and + * the output blocks are exclusive-ORed with the corresponding plaintext blocks + * to produce the ciphertext blocks. + *

+ * In OFB decryption, the IV is transformed by the forward cipher + * function to produce the first output block. The first output block is + * exclusive-ORed with the first ciphertext block to recover the first plaintext + * block. The first output block is then transformed by the forward cipher + * function to produce the second output block. The second output block is + * exclusive-ORed with the second ciphertext block to produce the second + * plaintext block, and the second output block is also transformed by the + * forward cipher function to produce the third output block. Thus, the + * successive output blocks are produced from enciphering the previous output + * blocks, and the output blocks are exclusive-ORed with the corresponding + * ciphertext blocks to recover the plaintext blocks. + *

+ * In both OFB encryption and OFB decryption, each forward cipher function + * (except the first) depends on the results of the previous forward cipher + * function; therefore, multiple forward cipher functions cannot be performed in + * parallel. However, if the IV is known, the output blocks can + * be generated prior to the availability of the plaintext or ciphertext data. + *

+ * The OFB mode requires a unique IV for every message that is + * ever encrypted under the given key. If, contrary to this requirement, the + * same IV is used for the encryption of more than one message, + * then the confidentiality of those messages may be compromised. In particular, + * if a plaintext block of any of these messages is known, say, the jth + * plaintext block, then the jth output of the forward cipher + * function can be determined easily from the jth ciphertext block + * of the message. This information allows the jth plaintext block + * of any other message that is encrypted using the same IV to be + * easily recovered from the jth ciphertext block of that message. + *

+ * Confidentiality may similarly be compromised if any of the input blocks to + * the forward cipher function for the encryption of a message is used as the + * IV for the encryption of another message under the given key. + *

+ * References: + *

    + *
  1. + * Recommendation for Block Cipher Modes of Operation Methods and Techniques, + * Morris Dworkin.
  2. + *
+ */ +public class OFB + extends BaseMode + implements Cloneable +{ + private byte[] outputBlock; + + /** + * Trivial package-private constructor for use by the Factory class. + * + * @param underlyingCipher the underlying cipher implementation. + * @param cipherBlockSize the underlying cipher block size to use. + */ + OFB(IBlockCipher underlyingCipher, int cipherBlockSize) + { + super(Registry.OFB_MODE, underlyingCipher, cipherBlockSize); + } + + /** + * Private constructor for cloning purposes. + * + * @param that the mode to clone. + */ + private OFB(OFB that) + { + this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize); + } + + public Object clone() + { + return new OFB(this); + } + + public void setup() + { + if (modeBlockSize != cipherBlockSize) + throw new IllegalArgumentException(IMode.MODE_BLOCK_SIZE); + outputBlock = (byte[]) iv.clone(); + } + + public void teardown() + { + } + + public void encryptBlock(byte[] in, int i, byte[] out, int o) + { + cipher.encryptBlock(outputBlock, 0, outputBlock, 0); + for (int j = 0; j < cipherBlockSize;) + out[o++] = (byte)(in[i++] ^ outputBlock[j++]); + } + + public void decryptBlock(byte[] in, int i, byte[] out, int o) + { + this.encryptBlock(in, i, out, o); + } +} -- cgit v1.2.3