/*
 * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.crypto;

import java.util.StringTokenizer;
import java.util.NoSuchElementException;
import java.security.AlgorithmParameters;
import java.security.Provider;
import java.security.Key;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.ProviderException;
import java.security.spec.AlgorithmParameterSpec;

import java.nio.ByteBuffer;

/**
 * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
 * for the <code>Cipher</code> class.
 * All the abstract methods in this class must be implemented by each
 * cryptographic service provider who wishes to supply the implementation
 * of a particular cipher algorithm.
 *
 * <p>In order to create an instance of <code>Cipher</code>, which
 * encapsulates an instance of this <code>CipherSpi</code> class, an
 * application calls one of the
 * {@link Cipher#getInstance(java.lang.String) getInstance}
 * factory methods of the
 * {@link Cipher Cipher} engine class and specifies the requested
 * <i>transformation</i>.
 * Optionally, the application may also specify the name of a provider.
 *
 * <p>A <i>transformation</i> is a string that describes the operation (or
 * set of operations) to be performed on the given input, to produce some
 * output. A transformation always includes the name of a cryptographic
 * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
 * padding scheme.
 *
 * <p> A transformation is of the form:<p>
 *
 * <ul>
 * <li>"<i>algorithm/mode/padding</i>" or
 * <p>
 * <li>"<i>algorithm</i>"
 * </ul>
 *
 * <P> (in the latter case,
 * provider-specific default values for the mode and padding scheme are used).
 * For example, the following is a valid transformation:<p>
 *
 * <pre>
 *     Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
 * </pre>
 *
 * <p>A provider may supply a separate class for each combination
 * of <i>algorithm/mode/padding</i>, or may decide to provide more generic
 * classes representing sub-transformations corresponding to
 * <i>algorithm</i> or <i>algorithm/mode</i> or <i>algorithm//padding</i>
 * (note the double slashes),
 * in which case the requested mode and/or padding are set automatically by
 * the <code>getInstance</code> methods of <code>Cipher</code>, which invoke
 * the {@link #engineSetMode(java.lang.String) engineSetMode} and
 * {@link #engineSetPadding(java.lang.String) engineSetPadding}
 * methods of the provider's subclass of <code>CipherSpi</code>.
 *
 * <p>A <code>Cipher</code> property in a provider master class may have one of
 * the following formats:
 *
 * <ul>
 *
 * <li>
 * <pre>
 *     // provider's subclass of "CipherSpi" implements "algName" with
 *     // pluggable mode and padding
 *     <code>Cipher.</code><i>algName</i>
 * </pre>
 *
 * <li>
 * <pre>
 *     // provider's subclass of "CipherSpi" implements "algName" in the
 *     // specified "mode", with pluggable padding
 *     <code>Cipher.</code><i>algName/mode</i>
 * </pre>
 *
 * <li>
 * <pre>
 *     // provider's subclass of "CipherSpi" implements "algName" with the
 *     // specified "padding", with pluggable mode
 *     <code>Cipher.</code><i>algName//padding</i>
 * </pre>
 *
 * <li>
 * <pre>
 *     // provider's subclass of "CipherSpi" implements "algName" with the
 *     // specified "mode" and "padding"
 *     <code>Cipher.</code><i>algName/mode/padding</i>
 * </pre>
 *
 * </ul>
 *
 * <p>For example, a provider may supply a subclass of <code>CipherSpi</code>
 * that implements <i>DES/ECB/PKCS5Padding</i>, one that implements
 * <i>DES/CBC/PKCS5Padding</i>, one that implements
 * <i>DES/CFB/PKCS5Padding</i>, and yet another one that implements
 * <i>DES/OFB/PKCS5Padding</i>. That provider would have the following
 * <code>Cipher</code> properties in its master class:<p>
 *
 * <ul>
 *
 * <li>
 * <pre>
 *     <code>Cipher.</code><i>DES/ECB/PKCS5Padding</i>
 * </pre>
 *
 * <li>
 * <pre>
 *     <code>Cipher.</code><i>DES/CBC/PKCS5Padding</i>
 * </pre>
 *
 * <li>
 * <pre>
 *     <code>Cipher.</code><i>DES/CFB/PKCS5Padding</i>
 * </pre>
 *
 * <li>
 * <pre>
 *     <code>Cipher.</code><i>DES/OFB/PKCS5Padding</i>
 * </pre>
 *
 * </ul>
 *
 * <p>Another provider may implement a class for each of the above modes
 * (i.e., one class for <i>ECB</i>, one for <i>CBC</i>, one for <i>CFB</i>,
 * and one for <i>OFB</i>), one class for <i>PKCS5Padding</i>,
 * and a generic <i>DES</i> class that subclasses from <code>CipherSpi</code>.
 * That provider would have the following
 * <code>Cipher</code> properties in its master class:<p>
 *
 * <ul>
 *
 * <li>
 * <pre>
 *     <code>Cipher.</code><i>DES</i>
 * </pre>
 *
 * </ul>
 *
 * <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
 * engine class follows these rules in order to instantiate a provider's
 * implementation of <code>CipherSpi</code> for a
 * transformation of the form "<i>algorithm</i>":
 *
 * <ol>
 * <li>
 * Check if the provider has registered a subclass of <code>CipherSpi</code>
 * for the specified "<i>algorithm</i>".
 * <p>If the answer is YES, instantiate this
 * class, for whose mode and padding scheme default values (as supplied by
 * the provider) are used.
 * <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
 * exception.
 * </ol>
 *
 * <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
 * engine class follows these rules in order to instantiate a provider's
 * implementation of <code>CipherSpi</code> for a
 * transformation of the form "<i>algorithm/mode/padding</i>":
 *
 * <ol>
 * <li>
 * Check if the provider has registered a subclass of <code>CipherSpi</code>
 * for the specified "<i>algorithm/mode/padding</i>" transformation.
 * <p>If the answer is YES, instantiate it.
 * <p>If the answer is NO, go to the next step.<p>
 * <li>
 * Check if the provider has registered a subclass of <code>CipherSpi</code>
 * for the sub-transformation "<i>algorithm/mode</i>".
 * <p>If the answer is YES, instantiate it, and call
 * <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
 * <p>If the answer is NO, go to the next step.<p>
 * <li>
 * Check if the provider has registered a subclass of <code>CipherSpi</code>
 * for the sub-transformation "<i>algorithm//padding</i>" (note the double
 * slashes).
 * <p>If the answer is YES, instantiate it, and call
 * <code>engineSetMode(<i>mode</i>)</code> on the new instance.
 * <p>If the answer is NO, go to the next step.<p>
 * <li>
 * Check if the provider has registered a subclass of <code>CipherSpi</code>
 * for the sub-transformation "<i>algorithm</i>".
 * <p>If the answer is YES, instantiate it, and call
 * <code>engineSetMode(<i>mode</i>)</code> and
 * <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
 * <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
 * exception.
 * </ol>
 *
 * @author Jan Luehe
 * @see KeyGenerator
 * @see SecretKey
 * @since 1.4
 */

public abstract class CipherSpi {

    /**
     * Sets the mode of this cipher.
     *
     * @param mode the cipher mode
     *
     * @exception NoSuchAlgorithmException if the requested cipher mode does
     * not exist
     */
    protected abstract void engineSetMode(String mode)
        throws NoSuchAlgorithmException;

    /**
     * Sets the padding mechanism of this cipher.
     *
     * @param padding the padding mechanism
     *
     * @exception NoSuchPaddingException if the requested padding mechanism
     * does not exist
     */
    protected abstract void engineSetPadding(String padding)
        throws NoSuchPaddingException;

    /**
     * Returns the block size (in bytes).
     *
     * @return the block size (in bytes), or 0 if the underlying algorithm is
     * not a block cipher
     */
    protected abstract int engineGetBlockSize();

    /**
     * Returns the length in bytes that an output buffer would
     * need to be in order to hold the result of the next <code>update</code>
     * or <code>doFinal</code> operation, given the input length
     * <code>inputLen</code> (in bytes).
     *
     * <p>This call takes into account any unprocessed (buffered) data from a
     * previous <code>update</code> call, and padding.
     *
     * <p>The actual output length of the next <code>update</code> or
     * <code>doFinal</code> call may be smaller than the length returned by
     * this method.
     *
     * @param inputLen the input length (in bytes)
     *
     * @return the required output buffer size (in bytes)
     */
    protected abstract int engineGetOutputSize(int inputLen);

    /**
     * Returns the initialization vector (IV) in a new buffer.
     *
     * <p> This is useful in the context of password-based encryption or
     * decryption, where the IV is derived from a user-provided passphrase.
     *
     * @return the initialization vector in a new buffer, or null if the
     * underlying algorithm does not use an IV, or if the IV has not yet
     * been set.
     */
    protected abstract byte[] engineGetIV();

    /**
     * Returns the parameters used with this cipher.
     *
     * <p>The returned parameters may be the same that were used to initialize
     * this cipher, or may contain a combination of default and random
     * parameter values used by the underlying cipher implementation if this
     * cipher requires algorithm parameters but was not initialized with any.
     *
     * @return the parameters used with this cipher, or null if this cipher
     * does not use any parameters.
     */
    protected abstract AlgorithmParameters engineGetParameters();

    /**
     * Initializes this cipher with a key and a source
     * of randomness.
     *
     * <p>The cipher is initialized for one of the following four operations:
     * encryption, decryption, key wrapping or key unwrapping, depending on
     * the value of <code>opmode</code>.
     *
     * <p>If this cipher requires any algorithm parameters that cannot be
     * derived from the given <code>key</code>, the underlying cipher
     * implementation is supposed to generate the required parameters itself
     * (using provider-specific default or random values) if it is being
     * initialized for encryption or key wrapping, and raise an
     * <code>InvalidKeyException</code> if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #engineGetParameters() engineGetParameters} or
     * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
     *
     * <p>If this cipher (including its underlying feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them from <code>random</code>.
     *
     * <p>Note that when a Cipher object is initialized, it loses all
     * previously-acquired state. In other words, initializing a Cipher is
     * equivalent to creating a new instance of that Cipher and initializing
     * it.
     *
     * @param opmode the operation mode of this cipher (this is one of
     * the following:
     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
     * @param key the encryption key
     * @param random the source of randomness
     *
     * @exception InvalidKeyException if the given key is inappropriate for
     * initializing this cipher, or if this cipher is being initialized for
     * decryption and requires algorithm parameters that cannot be
     * determined from the given key.
     */
    protected abstract void engineInit(int opmode, Key key,
                                       SecureRandom random)
        throws InvalidKeyException;

    /**
     * Initializes this cipher with a key, a set of
     * algorithm parameters, and a source of randomness.
     *
     * <p>The cipher is initialized for one of the following four operations:
     * encryption, decryption, key wrapping or key unwrapping, depending on
     * the value of <code>opmode</code>.
     *
     * <p>If this cipher requires any algorithm parameters and
     * <code>params</code> is null, the underlying cipher implementation is
     * supposed to generate the required parameters itself (using
     * provider-specific default or random values) if it is being
     * initialized for encryption or key wrapping, and raise an
     * <code>InvalidAlgorithmParameterException</code> if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #engineGetParameters() engineGetParameters} or
     * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
     *
     * <p>If this cipher (including its underlying feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them from <code>random</code>.
     *
     * <p>Note that when a Cipher object is initialized, it loses all
     * previously-acquired state. In other words, initializing a Cipher is
     * equivalent to creating a new instance of that Cipher and initializing
     * it.
     *
     * @param opmode the operation mode of this cipher (this is one of
     * the following:
     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
     * @param key the encryption key
     * @param params the algorithm parameters
     * @param random the source of randomness
     *
     * @exception InvalidKeyException if the given key is inappropriate for
     * initializing this cipher
     * @exception InvalidAlgorithmParameterException if the given algorithm
     * parameters are inappropriate for this cipher,
     * or if this cipher is being initialized for decryption and requires
     * algorithm parameters and <code>params</code> is null.
     */
    protected abstract void engineInit(int opmode, Key key,
                                       AlgorithmParameterSpec params,
                                       SecureRandom random)
        throws InvalidKeyException, InvalidAlgorithmParameterException;

    /**
     * Initializes this cipher with a key, a set of
     * algorithm parameters, and a source of randomness.
     *
     * <p>The cipher is initialized for one of the following four operations:
     * encryption, decryption, key wrapping or key unwrapping, depending on
     * the value of <code>opmode</code>.
     *
     * <p>If this cipher requires any algorithm parameters and
     * <code>params</code> is null, the underlying cipher implementation is
     * supposed to generate the required parameters itself (using
     * provider-specific default or random values) if it is being
     * initialized for encryption or key wrapping, and raise an
     * <code>InvalidAlgorithmParameterException</code> if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #engineGetParameters() engineGetParameters} or
     * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
     *
     * <p>If this cipher (including its underlying feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them from <code>random</code>.
     *
     * <p>Note that when a Cipher object is initialized, it loses all
     * previously-acquired state. In other words, initializing a Cipher is
     * equivalent to creating a new instance of that Cipher and initializing
     * it.
     *
     * @param opmode the operation mode of this cipher (this is one of
     * the following:
     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
     * @param key the encryption key
     * @param params the algorithm parameters
     * @param random the source of randomness
     *
     * @exception InvalidKeyException if the given key is inappropriate for
     * initializing this cipher
     * @exception InvalidAlgorithmParameterException if the given algorithm
     * parameters are inappropriate for this cipher,
     * or if this cipher is being initialized for decryption and requires
     * algorithm parameters and <code>params</code> is null.
     */
    protected abstract void engineInit(int opmode, Key key,
                                       AlgorithmParameters params,
                                       SecureRandom random)
        throws InvalidKeyException, InvalidAlgorithmParameterException;

    /**
     * Continues a multiple-part encryption or decryption operation
     * (depending on how this cipher was initialized), processing another data
     * part.
     *
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
     * buffer, starting at <code>inputOffset</code> inclusive, are processed,
     * and the result is stored in a new buffer.
     *
     * @param input the input buffer
     * @param inputOffset the offset in <code>input</code> where the input
     * starts
     * @param inputLen the input length
     *
     * @return the new buffer with the result, or null if the underlying
     * cipher is a block cipher and the input data is too short to result in a
     * new block.
     */
    protected abstract byte[] engineUpdate(byte[] input, int inputOffset,
                                           int inputLen);

    /**
     * Continues a multiple-part encryption or decryption operation
     * (depending on how this cipher was initialized), processing another data
     * part.
     *
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
     * buffer, starting at <code>inputOffset</code> inclusive, are processed,
     * and the result is stored in the <code>output</code> buffer, starting at
     * <code>outputOffset</code> inclusive.
     *
     * <p>If the <code>output</code> buffer is too small to hold the result,
     * a <code>ShortBufferException</code> is thrown.
     *
     * @param input the input buffer
     * @param inputOffset the offset in <code>input</code> where the input
     * starts
     * @param inputLen the input length
     * @param output the buffer for the result
     * @param outputOffset the offset in <code>output</code> where the result
     * is stored
     *
     * @return the number of bytes stored in <code>output</code>
     *
     * @exception ShortBufferException if the given output buffer is too small
     * to hold the result
     */
    protected abstract int engineUpdate(byte[] input, int inputOffset,
                                        int inputLen, byte[] output,
                                        int outputOffset)
        throws ShortBufferException;

    /**
     * Continues a multiple-part encryption or decryption operation
     * (depending on how this cipher was initialized), processing another data
     * part.
     *
     * <p>All <code>input.remaining()</code> bytes starting at
     * <code>input.position()</code> are processed. The result is stored
     * in the output buffer.
     * Upon return, the input buffer's position will be equal
     * to its limit; its limit will not have changed. The output buffer's
     * position will have advanced by n, where n is the value returned
     * by this method; the output buffer's limit will not have changed.
     *
     * <p>If <code>output.remaining()</code> bytes are insufficient to
     * hold the result, a <code>ShortBufferException</code> is thrown.
     *
     * <p>Subclasses should consider overriding this method if they can
     * process ByteBuffers more efficiently than byte arrays.
     *
     * @param input the input ByteBuffer
     * @param output the output ByteByffer
     *
     * @return the number of bytes stored in <code>output</code>
     *
     * @exception ShortBufferException if there is insufficient space in the
     * output buffer
     *
     * @throws NullPointerException if either parameter is <CODE>null</CODE>
     * @since 1.5
     */
    protected int engineUpdate(ByteBuffer input, ByteBuffer output)
            throws ShortBufferException {
        try {
            return bufferCrypt(input, output, true);
        } catch (IllegalBlockSizeException e) {
            // never thrown for engineUpdate()
            throw new ProviderException("Internal error in update()");
        } catch (BadPaddingException e) {
            // never thrown for engineUpdate()
            throw new ProviderException("Internal error in update()");
        }
    }

    /**
     * Encrypts or decrypts data in a single-part operation,
     * or finishes a multiple-part operation.
     * The data is encrypted or decrypted, depending on how this cipher was
     * initialized.
     *
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
     * buffer, starting at <code>inputOffset</code> inclusive, and any input
     * bytes that may have been buffered during a previous <code>update</code>
     * operation, are processed, with padding (if requested) being applied.
     * The result is stored in a new buffer.
     *
     * <p>Upon finishing, this method resets this cipher object to the state
     * it was in when previously initialized via a call to
     * <code>engineInit</code>.
     * That is, the object is reset and available to encrypt or decrypt
     * (depending on the operation mode that was specified in the call to
     * <code>engineInit</code>) more data.
     *
     * <p>Note: if any exception is thrown, this cipher object may need to
     * be reset before it can be used again.
     *
     * @param input the input buffer
     * @param inputOffset the offset in <code>input</code> where the input
     * starts
     * @param inputLen the input length
     *
     * @return the new buffer with the result
     *
     * @exception IllegalBlockSizeException if this cipher is a block cipher,
     * no padding has been requested (only in encryption mode), and the total
     * input length of the data processed by this cipher is not a multiple of
     * block size; or if this encryption algorithm is unable to
     * process the input data provided.
     * @exception BadPaddingException if this cipher is in decryption mode,
     * and (un)padding has been requested, but the decrypted data is not
     * bounded by the appropriate padding bytes
     */
    protected abstract byte[] engineDoFinal(byte[] input, int inputOffset,
                                            int inputLen)
        throws IllegalBlockSizeException, BadPaddingException;

    /**
     * Encrypts or decrypts data in a single-part operation,
     * or finishes a multiple-part operation.
     * The data is encrypted or decrypted, depending on how this cipher was
     * initialized.
     *
     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
     * buffer, starting at <code>inputOffset</code> inclusive, and any input
     * bytes that may have been buffered during a previous <code>update</code>
     * operation, are processed, with padding (if requested) being applied.
     * The result is stored in the <code>output</code> buffer, starting at
     * <code>outputOffset</code> inclusive.
     *
     * <p>If the <code>output</code> buffer is too small to hold the result,
     * a <code>ShortBufferException</code> is thrown.
     *
     * <p>Upon finishing, this method resets this cipher object to the state
     * it was in when previously initialized via a call to
     * <code>engineInit</code>.
     * That is, the object is reset and available to encrypt or decrypt
     * (depending on the operation mode that was specified in the call to
     * <code>engineInit</code>) more data.
     *
     * <p>Note: if any exception is thrown, this cipher object may need to
     * be reset before it can be used again.
     *
     * @param input the input buffer
     * @param inputOffset the offset in <code>input</code> where the input
     * starts
     * @param inputLen the input length
     * @param output the buffer for the result
     * @param outputOffset the offset in <code>output</code> where the result
     * is stored
     *
     * @return the number of bytes stored in <code>output</code>
     *
     * @exception IllegalBlockSizeException if this cipher is a block cipher,
     * no padding has been requested (only in encryption mode), and the total
     * input length of the data processed by this cipher is not a multiple of
     * block size; or if this encryption algorithm is unable to
     * process the input data provided.
     * @exception ShortBufferException if the given output buffer is too small
     * to hold the result
     * @exception BadPaddingException if this cipher is in decryption mode,
     * and (un)padding has been requested, but the decrypted data is not
     * bounded by the appropriate padding bytes
     */
    protected abstract int engineDoFinal(byte[] input, int inputOffset,
                                         int inputLen, byte[] output,
                                         int outputOffset)
        throws ShortBufferException, IllegalBlockSizeException,
               BadPaddingException;

    /**
     * Encrypts or decrypts data in a single-part operation,
     * or finishes a multiple-part operation.
     * The data is encrypted or decrypted, depending on how this cipher was
     * initialized.
     *
     * <p>All <code>input.remaining()</code> bytes starting at
     * <code>input.position()</code> are processed. The result is stored
     * in the output buffer.
     * Upon return, the input buffer's position will be equal
     * to its limit; its limit will not have changed. The output buffer's
     * position will have advanced by n, where n is the value returned
     * by this method; the output buffer's limit will not have changed.
     *
     * <p>If <code>output.remaining()</code> bytes are insufficient to
     * hold the result, a <code>ShortBufferException</code> is thrown.
     *
     * <p>Upon finishing, this method resets this cipher object to the state
     * it was in when previously initialized via a call to
     * <code>engineInit</code>.
     * That is, the object is reset and available to encrypt or decrypt
     * (depending on the operation mode that was specified in the call to
     * <code>engineInit</code>) more data.
     *
     * <p>Note: if any exception is thrown, this cipher object may need to
     * be reset before it can be used again.
     *
     * <p>Subclasses should consider overriding this method if they can
     * process ByteBuffers more efficiently than byte arrays.
     *
     * @param input the input ByteBuffer
     * @param output the output ByteByffer
     *
     * @return the number of bytes stored in <code>output</code>
     *
     * @exception IllegalBlockSizeException if this cipher is a block cipher,
     * no padding has been requested (only in encryption mode), and the total
     * input length of the data processed by this cipher is not a multiple of
     * block size; or if this encryption algorithm is unable to
     * process the input data provided.
     * @exception ShortBufferException if there is insufficient space in the
     * output buffer
     * @exception BadPaddingException if this cipher is in decryption mode,
     * and (un)padding has been requested, but the decrypted data is not
     * bounded by the appropriate padding bytes
     *
     * @throws NullPointerException if either parameter is <CODE>null</CODE>
     * @since 1.5
     */
    protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
            throws ShortBufferException, IllegalBlockSizeException,
            BadPaddingException {
        return bufferCrypt(input, output, false);
    }

    // copied from sun.security.jca.JCAUtil
    // will be changed to reference that method once that code has been
    // integrated and promoted
    static int getTempArraySize(int totalSize) {
        return Math.min(4096, totalSize);
    }

    /**
     * Implementation for encryption using ByteBuffers. Used for both
     * engineUpdate() and engineDoFinal().
     */
    private int bufferCrypt(ByteBuffer input, ByteBuffer output,
            boolean isUpdate) throws ShortBufferException,
            IllegalBlockSizeException, BadPaddingException {
        if ((input == null) || (output == null)) {
            throw new NullPointerException
                ("Input and output buffers must not be null");
        }
        int inPos = input.position();
        int inLimit = input.limit();
        int inLen = inLimit - inPos;
        if (isUpdate && (inLen == 0)) {
            return 0;
        }
        int outLenNeeded = engineGetOutputSize(inLen);
        if (output.remaining() < outLenNeeded) {
            throw new ShortBufferException("Need at least " + outLenNeeded
                + " bytes of space in output buffer");
        }

        boolean a1 = input.hasArray();
        boolean a2 = output.hasArray();

        if (a1 && a2) {
            byte[] inArray = input.array();
            int inOfs = input.arrayOffset() + inPos;
            byte[] outArray = output.array();
            int outPos = output.position();
            int outOfs = output.arrayOffset() + outPos;
            int n;
            if (isUpdate) {
                n = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
            } else {
                n = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
            }
            input.position(inLimit);
            output.position(outPos + n);
            return n;
        } else if (!a1 && a2) {
            int outPos = output.position();
            byte[] outArray = output.array();
            int outOfs = output.arrayOffset() + outPos;
            byte[] inArray = new byte[getTempArraySize(inLen)];
            int total = 0;
            while (inLen > 0) {
                int chunk = Math.min(inLen, inArray.length);
                input.get(inArray, 0, chunk);
                int n;
                if (isUpdate || (inLen != chunk)) {
                    n = engineUpdate(inArray, 0, chunk, outArray, outOfs);
                } else {
                    n = engineDoFinal(inArray, 0, chunk, outArray, outOfs);
                }
                total += n;
                outOfs += n;
                inLen -= chunk;
            }
            output.position(outPos + total);
            return total;
        } else { // output is not backed by an accessible byte[]
            byte[] inArray;
            int inOfs;
            if (a1) {
                inArray = input.array();
                inOfs = input.arrayOffset() + inPos;
            } else {
                inArray = new byte[getTempArraySize(inLen)];
                inOfs = 0;
            }
            byte[] outArray = new byte[getTempArraySize(outLenNeeded)];
            int outSize = outArray.length;
            int total = 0;
            boolean resized = false;
            while (inLen > 0) {
                int chunk = Math.min(inLen, outSize);
                if ((a1 == false) && (resized == false)) {
                    input.get(inArray, 0, chunk);
                    inOfs = 0;
                }
                try {
                    int n;
                    if (isUpdate || (inLen != chunk)) {
                        n = engineUpdate(inArray, inOfs, chunk, outArray, 0);
                    } else {
                        n = engineDoFinal(inArray, inOfs, chunk, outArray, 0);
                    }
                    resized = false;
                    inOfs += chunk;
                    inLen -= chunk;
                    output.put(outArray, 0, n);
                    total += n;
                } catch (ShortBufferException e) {
                    if (resized) {
                        // we just resized the output buffer, but it still
                        // did not work. Bug in the provider, abort
                        throw (ProviderException)new ProviderException
                            ("Could not determine buffer size").initCause(e);
                    }
                    // output buffer is too small, realloc and try again
                    resized = true;
                    int newOut = engineGetOutputSize(chunk);
                    outArray = new byte[newOut];
                }
            }
            input.position(inLimit);
            return total;
        }
    }

    /**
     * Wrap a key.
     *
     * <p>This concrete method has been added to this previously-defined
     * abstract class. (For backwards compatibility, it cannot be abstract.)
     * It may be overridden by a provider to wrap a key.
     * Such an override is expected to throw an IllegalBlockSizeException or
     * InvalidKeyException (under the specified circumstances),
     * if the given key cannot be wrapped.
     * If this method is not overridden, it always throws an
     * UnsupportedOperationException.
     *
     * @param key the key to be wrapped.
     *
     * @return the wrapped key.
     *
     * @exception IllegalBlockSizeException if this cipher is a block cipher,
     * no padding has been requested, and the length of the encoding of the
     * key to be wrapped is not a multiple of the block size.
     *
     * @exception InvalidKeyException if it is impossible or unsafe to
     * wrap the key with this cipher (e.g., a hardware protected key is
     * being passed to a software-only cipher).
     */
    protected byte[] engineWrap(Key key)
        throws IllegalBlockSizeException, InvalidKeyException
    {
        throw new UnsupportedOperationException();
    }

    /**
     * Unwrap a previously wrapped key.
     *
     * <p>This concrete method has been added to this previously-defined
     * abstract class. (For backwards compatibility, it cannot be abstract.)
     * It may be overridden by a provider to unwrap a previously wrapped key.
     * Such an override is expected to throw an InvalidKeyException if
     * the given wrapped key cannot be unwrapped.
     * If this method is not overridden, it always throws an
     * UnsupportedOperationException.
     *
     * @param wrappedKey the key to be unwrapped.
     *
     * @param wrappedKeyAlgorithm the algorithm associated with the wrapped
     * key.
     *
     * @param wrappedKeyType the type of the wrapped key. This is one of
     * <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or
     * <code>PUBLIC_KEY</code>.
     *
     * @return the unwrapped key.
     *
     * @exception NoSuchAlgorithmException if no installed providers
     * can create keys of type <code>wrappedKeyType</code> for the
     * <code>wrappedKeyAlgorithm</code>.
     *
     * @exception InvalidKeyException if <code>wrappedKey</code> does not
     * represent a wrapped key of type <code>wrappedKeyType</code> for
     * the <code>wrappedKeyAlgorithm</code>.
     */
    protected Key engineUnwrap(byte[] wrappedKey,
                               String wrappedKeyAlgorithm,
                               int wrappedKeyType)
        throws InvalidKeyException, NoSuchAlgorithmException
    {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the key size of the given key object in bits.
     * <p>This concrete method has been added to this previously-defined
     * abstract class. It throws an <code>UnsupportedOperationException</code>
     * if it is not overridden by the provider.
     *
     * @param key the key object.
     *
     * @return the key size of the given key object.
     *
     * @exception InvalidKeyException if <code>key</code> is invalid.
     */
    protected int engineGetKeySize(Key key)
        throws InvalidKeyException
    {
        throw new UnsupportedOperationException();
    }
}
