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. --- .../gnu/javax/crypto/jce/cipher/CipherAdapter.java | 531 +++++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100644 libjava/classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java (limited to 'libjava/classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java') diff --git a/libjava/classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java new file mode 100644 index 000000000..0871c5402 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java @@ -0,0 +1,531 @@ +/* CipherAdapter.java -- + Copyright (C) 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.jce.cipher; + +import gnu.java.security.Registry; +import gnu.javax.crypto.cipher.CipherFactory; +import gnu.javax.crypto.cipher.IBlockCipher; +import gnu.javax.crypto.jce.spec.BlockCipherParameterSpec; +import gnu.javax.crypto.mode.IMode; +import gnu.javax.crypto.mode.ModeFactory; +import gnu.javax.crypto.pad.IPad; +import gnu.javax.crypto.pad.PadFactory; +import gnu.javax.crypto.pad.WrongPaddingException; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.CipherSpi; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.IvParameterSpec; + +/** + * The implementation of a generic {@link Cipher} Adapter class to wrap + * GNU cipher instances. + *

+ * This class defines the Service Provider Interface (SPI) for + * the {@link Cipher} class, which provides the functionality of symmetric-key + * block ciphers, such as the AES. + *

+ * This base class defines all of the abstract methods in {@link CipherSpi}, + * but does not define the (non-abstract) key wrapping functions that extended + * the base cipher SPI, and these methods thus immediately throw an + * {@link UnsupportedOperationException}. If a cipher implementation provides + * this functionality, or if it in fact accepts parameters other than the key + * and the initialization vector, the subclass should override those methods. + * Otherwise a subclass need only call the {@link #CipherAdapter(String)} + * constructor with the name of the cipher. + */ +class CipherAdapter + extends CipherSpi +{ + /** Our cipher instance. */ + protected IBlockCipher cipher; + /** Our mode instance. */ + protected IMode mode; + /** Our padding instance. */ + protected IPad pad; + /** The current key size. */ + protected int keyLen; + /** Our attributes map. */ + protected Map attributes; + /** An incomplete block. */ + protected byte[] partBlock; + /** The number of bytes in {@link #partBlock}. */ + protected int partLen; + /** The length of blocks we are processing. */ + protected int blockLen; + + /** + * Protected constructor to be called by subclasses. The cipher name argument + * should be the appropriate one listed in {@link Registry}. The basic cipher + * instance is created, along with an instance of the + * {@link gnu.javax.crypto.mode.ECB} mode and no padding. + * + * @param cipherName The cipher to instantiate. + * @param blockLen The block length to use. + */ + protected CipherAdapter(String cipherName, int blockLen) + { + cipher = CipherFactory.getInstance(cipherName); + attributes = new HashMap(); + this.blockLen = blockLen; + mode = ModeFactory.getInstance("ECB", cipher, blockLen); + attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen)); + } + + /** + * Creates a new cipher adapter with the default block size. + * + * @param cipherName The cipher to instantiate. + */ + protected CipherAdapter(String cipherName) + { + cipher = CipherFactory.getInstance(cipherName); + blockLen = cipher.defaultBlockSize(); + attributes = new HashMap(); + mode = ModeFactory.getInstance("ECB", cipher, blockLen); + attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen)); + } + + protected void engineSetMode(String modeName) throws NoSuchAlgorithmException + { + if (modeName.length() >= 3 + && modeName.substring(0, 3).equalsIgnoreCase("CFB")) + { + if (modeName.length() > 3) + { + try + { + int bs = Integer.parseInt(modeName.substring(3)); + attributes.put(IMode.MODE_BLOCK_SIZE, Integer.valueOf(bs / 8)); + } + catch (NumberFormatException nfe) + { + throw new NoSuchAlgorithmException(modeName); + } + modeName = "CFB"; + } + } + else + attributes.remove(IMode.MODE_BLOCK_SIZE); + mode = ModeFactory.getInstance(modeName, cipher, blockLen); + if (mode == null) + throw new NoSuchAlgorithmException(modeName); + } + + protected void engineSetPadding(String padName) throws NoSuchPaddingException + { + if (padName.equalsIgnoreCase("NoPadding")) + { + pad = null; + return; + } + pad = PadFactory.getInstance(padName); + if (pad == null) + throw new NoSuchPaddingException(padName); + } + + protected int engineGetBlockSize() + { + if (cipher != null) + return blockLen; + return 0; + } + + protected int engineGetOutputSize(int inputLen) + { + final int blockSize = mode.currentBlockSize(); + return ((inputLen + partLen) / blockSize) * blockSize; + } + + protected byte[] engineGetIV() + { + byte[] iv = (byte[]) attributes.get(IMode.IV); + if (iv == null) + return null; + return (byte[]) iv.clone(); + } + + protected AlgorithmParameters engineGetParameters() + { + byte[] iv = (byte[]) attributes.get(IMode.IV); + int cipherBlockSize = cipher.currentBlockSize(); + BlockCipherParameterSpec spec = new BlockCipherParameterSpec(iv, + cipherBlockSize, + keyLen); + AlgorithmParameters params; + try + { + params = AlgorithmParameters.getInstance("BlockCipherParameters"); + params.init(spec); + } + catch (NoSuchAlgorithmException nsae) + { + return null; + } + catch (InvalidParameterSpecException ipse) + { + return null; + } + return params; + } + + protected void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException + { + try + { + engineInit(opmode, key, (AlgorithmParameterSpec) null, random); + } + catch (InvalidAlgorithmParameterException e) + { + throw new InvalidKeyException(e.getMessage(), e); + } + } + + /** + * Executes initialization logic after all parameters have been handled by the + * engineInit()s. + * + * @param opmode the desired mode of operation for this instance. + * @param key the key material to use for initialization. + * @param random a source of randmoness to use if/when needed. + * @throws InvalidKeyException if key is invalid or the cipher + * needs extra parameters which can not be derived from + * key; e.g. an IV. + */ + private void engineInitHandler(int opmode, Key key, SecureRandom random) + throws InvalidKeyException + { + switch (opmode) + { + case Cipher.ENCRYPT_MODE: + attributes.put(IMode.STATE, Integer.valueOf(IMode.ENCRYPTION)); + break; + case Cipher.DECRYPT_MODE: + attributes.put(IMode.STATE, Integer.valueOf(IMode.DECRYPTION)); + break; + } + if (! key.getFormat().equalsIgnoreCase("RAW")) + throw new InvalidKeyException("bad key format " + key.getFormat()); + byte[] kb = key.getEncoded(); + int kbLength = kb.length; + if (keyLen == 0) + { + // no key-size given; instead key-material is provided in kb --which + // can be more than what we need. if we don't cull this down to what + // the cipher likes/wants we may get an InvalidKeyException. + // + // try to find the largest key-size value that is less than or equal + // to kbLength + for (Iterator it = cipher.keySizes(); it.hasNext();) + { + int aKeySize = ((Integer) it.next()).intValue(); + if (aKeySize == kbLength) + { + keyLen = aKeySize; + break; + } + else if (aKeySize < kbLength) + keyLen = aKeySize; + else // all remaining key-sizes are longer than kb.length + break; + } + } + if (keyLen == 0) + { + // we were unable to find a key-size, among those advertised by the + // cipher, that is less than or equal to the length of the kb array. + // set keyLen to kbLength. either the cipher implementation will throw + // an InvalidKeyException, or it is implemented in a way which can deal + // with an unsupported key-size. + keyLen = kbLength; + } + if (keyLen < kbLength) + { + byte[] kbb = kb; + kb = new byte[keyLen]; + System.arraycopy(kbb, 0, kb, 0, keyLen); + } + attributes.put(IBlockCipher.KEY_MATERIAL, kb); + reset(); + } + + protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, + SecureRandom random) throws InvalidKeyException, + InvalidAlgorithmParameterException + { + if (params == null) + { + // All cipher modes require parameters (like an IV) except ECB. When + // these cant be derived from the given key then it must be generated + // randomly if in ENCRYPT or WRAP mode. Parameters that have defaults + // for our cipher must be set to these defaults. + if (! mode.name().toLowerCase().startsWith(Registry.ECB_MODE + "(")) + { + switch (opmode) + { + case Cipher.ENCRYPT_MODE: + case Cipher.WRAP_MODE: + byte[] iv = new byte[blockLen]; + random.nextBytes(iv); + attributes.put(IMode.IV, iv); + break; + default: + throw new InvalidAlgorithmParameterException( + "Required algorithm parameters are missing for mode: " + + mode.name()); + } + } + // Add default for block length etc. + blockLen = cipher.defaultBlockSize(); + attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, + Integer.valueOf(blockLen)); + keyLen = 0; + } + else if (params instanceof BlockCipherParameterSpec) + { + BlockCipherParameterSpec bcps = (BlockCipherParameterSpec) params; + blockLen = bcps.getBlockSize(); + attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen)); + attributes.put(IMode.IV, bcps.getIV()); + keyLen = bcps.getKeySize(); + } + else if (params instanceof IvParameterSpec) + { + // The size of the IV must match the block size + if (((IvParameterSpec) params).getIV().length != cipher.defaultBlockSize()) + { + throw new InvalidAlgorithmParameterException(); + } + + attributes.put(IMode.IV, ((IvParameterSpec) params).getIV()); + blockLen = cipher.defaultBlockSize(); + attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen)); + keyLen = 0; + } + engineInitHandler(opmode, key, random); + } + + protected void engineInit(int opmode, Key key, AlgorithmParameters params, + SecureRandom random) throws InvalidKeyException, + InvalidAlgorithmParameterException + { + AlgorithmParameterSpec spec = null; + try + { + if (params != null) + spec = params.getParameterSpec(BlockCipherParameterSpec.class); + } + catch (InvalidParameterSpecException ignored) + { + } + engineInit(opmode, key, spec, random); + } + + protected byte[] engineUpdate(byte[] input, int inOff, int inLen) + { + if (inLen == 0) // nothing to process + return new byte[0]; + final int blockSize = mode.currentBlockSize(); + int blockCount = (partLen + inLen) / blockSize; + + // always keep data for unpadding in padded decryption mode; + // might even be a complete block + if (pad != null + && ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION + && (partLen + inLen) % blockSize == 0) + blockCount--; + + final byte[] out = new byte[blockCount * blockSize]; + try + { + engineUpdate(input, inOff, inLen, out, 0); + } + catch (ShortBufferException x) // should not happen + { + x.printStackTrace(System.err); + } + return out; + } + + protected int engineUpdate(byte[] in, int inOff, int inLen, byte[] out, + int outOff) throws ShortBufferException + { + if (inLen == 0) // nothing to process + return 0; + final int blockSize = mode.currentBlockSize(); + int blockCount = (partLen + inLen) / blockSize; + + // always keep data for unpadding in padded decryption mode; + // might even be a complete block + if (pad != null + && ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION + && (partLen + inLen) % blockSize == 0) + blockCount--; + + final int result = blockCount * blockSize; + if (result > out.length - outOff) + throw new ShortBufferException(); + if (blockCount == 0) // not enough bytes for even 1 block + { + System.arraycopy(in, inOff, partBlock, partLen, inLen); + partLen += inLen; + return 0; + } + final byte[] buf; + // we have enough bytes for at least 1 block + if (partLen == 0) // if no cached bytes use input + buf = in; + else // prefix input with cached bytes + { + buf = new byte[partLen + inLen]; + System.arraycopy(partBlock, 0, buf, 0, partLen); + if (in != null && inLen > 0) + System.arraycopy(in, inOff, buf, partLen, inLen); + inOff = 0; + } + for (int i = 0; i < blockCount; i++) // update blockCount * blockSize + { + mode.update(buf, inOff, out, outOff); + inOff += blockSize; + outOff += blockSize; + } + partLen += inLen - result; + if (partLen > 0) // cache remaining bytes from buf + System.arraycopy(buf, inOff, partBlock, 0, partLen); + return result; + } + + protected byte[] engineDoFinal(byte[] input, int off, int len) + throws IllegalBlockSizeException, BadPaddingException + { + final byte[] result; + final byte[] buf = engineUpdate(input, off, len); + if (pad != null) + { + switch (((Integer) attributes.get(IMode.STATE)).intValue()) + { + case IMode.ENCRYPTION: + byte[] padding = pad.pad(partBlock, 0, partLen); + byte[] buf2 = engineUpdate(padding, 0, padding.length); + result = new byte[buf.length + buf2.length]; + System.arraycopy(buf, 0, result, 0, buf.length); + System.arraycopy(buf2, 0, result, buf.length, buf2.length); + break; + case IMode.DECRYPTION: + int padLen; + byte[] buf3 = new byte[buf.length + partLen]; + try + { + if (partLen != mode.currentBlockSize()) + throw new WrongPaddingException(); + System.arraycopy(buf, 0, buf3, 0, buf.length); + mode.update(partBlock, 0, buf3, buf.length); + padLen = pad.unpad(buf3, 0, buf3.length); + } + catch (WrongPaddingException wpe) + { + throw new BadPaddingException(wpe.getMessage()); + } + result = new byte[buf3.length - padLen]; + System.arraycopy(buf3, 0, result, 0, result.length); + break; + default: + throw new IllegalStateException(); + } + } + else + { + if (partLen > 0) + throw new IllegalBlockSizeException(partLen + " trailing bytes"); + result = buf; + } + + try + { + reset(); + } + catch (InvalidKeyException ike) + { + // Should not happen; if we initialized it with the current + // parameters before, we should be able to do it again. + throw new Error(ike); + } + return result; + } + + protected int engineDoFinal(byte[] in, int inOff, int inLen, byte[] out, + int outOff) throws BadPaddingException, + IllegalBlockSizeException, ShortBufferException + { + byte[] buf = engineDoFinal(in, inOff, inLen); + if (out.length + outOff < buf.length) + throw new ShortBufferException(); + System.arraycopy(buf, 0, out, outOff, buf.length); + return buf.length; + } + + private void reset() throws InvalidKeyException + { + mode.reset(); + mode.init(attributes); + if (pad != null) + { + pad.reset(); + pad.init(blockLen); + } + partBlock = new byte[blockLen]; + partLen = 0; + } +} -- cgit v1.2.3