/* 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} <i>Adapter</i> class to wrap
 * GNU cipher instances.
 * <p>
 * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
 * the {@link Cipher} class, which provides the functionality of symmetric-key
 * block ciphers, such as the AES.
 * <p>
 * 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 <code>key</code> is invalid or the cipher
   *           needs extra parameters which can not be derived from
   *           <code>key</code>; 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;
  }
}
