/*
 * Copyright (c) 1997, 2025, 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.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.*;


import java.security.*;
import java.security.Provider.Service;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

import javax.crypto.spec.*;

import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;

import sun.security.util.Debug;
import sun.security.jca.*;
import sun.security.util.KnownOIDs;

/**
 * This class provides the functionality of a cryptographic cipher for
 * encryption and decryption. It forms the core of the Java Cryptographic
 * Extension (JCE) framework.
 *
 * <p>In order to create a {@code Cipher} object, the application calls the
 * cipher's {@code getInstance} method, and passes the name of the
 * requested <i>transformation</i> to it. Optionally, the name of a provider
 * may be specified.
 *
 * <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>AES</i>), and may be followed by a feedback mode and
 * padding scheme.
 *
 * <p> A transformation is of the form:
 *
 * <ul>
 * <li>"<i>algorithm/mode/padding</i>" or
 *
 * <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:
 *
 * <pre>
 *     Cipher c = Cipher.getInstance("<i>AES/CBC/PKCS5Padding</i>");
 * </pre>
 *
 * Using modes such as {@code CFB} and {@code OFB}, block
 * ciphers can encrypt data in units smaller than the cipher's actual
 * block size.  When requesting such a mode, you may optionally specify
 * the number of bits to be processed at a time by appending this number
 * to the mode name as shown in the "{@code AES/CFB8/NoPadding}" and
 * "{@code AES/OFB32/PKCS5Padding}" transformations. If no such
 * number is specified, a provider-specific default is used.
 * (See the
 * {@extLink security_guide_jdk_providers JDK Providers Documentation}
 * for the JDK Providers default values.)
 * Thus, block ciphers can be turned into byte-oriented stream ciphers by
 * using an 8 bit mode such as CFB8 or OFB8.
 * <p>
 * Modes such as Authenticated Encryption with Associated Data (AEAD)
 * provide authenticity assurances for both confidential data and
 * Additional Associated Data (AAD) that is not encrypted.  (Please see
 * <a href="http://www.ietf.org/rfc/rfc5116.txt"> RFC 5116 </a> for more
 * information on AEAD and AAD algorithms such as GCM/CCM.) Both
 * confidential and AAD data can be used when calculating the
 * authentication tag (similar to a {@link Mac}).  This tag is appended
 * to the ciphertext during encryption, and is verified on decryption.
 * <p>
 * AEAD modes such as GCM/CCM perform all AAD authenticity calculations
 * before starting the ciphertext authenticity calculations.  To avoid
 * implementations having to internally buffer ciphertext, all AAD data
 * must be supplied to GCM/CCM implementations (via the {@code updateAAD}
 * methods) <b>before</b> the ciphertext is processed (via
 * the {@code update} and {@code doFinal} methods).
 * <p>
 * Note that GCM mode has a uniqueness requirement on IVs used in
 * encryption with a given key. When IVs are repeated for GCM
 * encryption, such usages are subject to forgery attacks. Thus, after
 * each encryption operation using GCM mode, callers should re-initialize
 * the {@code Cipher} objects with GCM parameters which have a different IV
 * value.
 * <pre>
 *     GCMParameterSpec s = ...;
 *     cipher.init(..., s);
 *
 *     // If the GCM parameters were generated by the provider, it can
 *     // be retrieved by:
 *     // cipher.getParameters().getParameterSpec(GCMParameterSpec.class);
 *
 *     cipher.updateAAD(...);  // AAD
 *     cipher.update(...);     // Multi-part update
 *     cipher.doFinal(...);    // conclusion of operation
 *
 *     // Use a different IV value for every encryption
 *     byte[] newIv = ...;
 *     s = new GCMParameterSpec(s.getTLen(), newIv);
 *     cipher.init(..., s);
 *     ...
 *
 * </pre>
 * The ChaCha20 and ChaCha20-Poly1305 algorithms have a similar requirement
 * for unique nonces with a given key.  After each encryption or decryption
 * operation, callers should re-initialize their ChaCha20 or ChaCha20-Poly1305
 * ciphers with parameters that specify a different nonce value.  Please
 * see <a href="https://tools.ietf.org/html/rfc7539">RFC 7539</a> for more
 * information on the ChaCha20 and ChaCha20-Poly1305 algorithms.
 * <p>
 * Every implementation of the Java platform is required to support
 * the following standard {@code Cipher} object transformations with
 * the keysizes in parentheses:
 * <ul>
 * <li>{@code AES/CBC/NoPadding} (128)</li>
 * <li>{@code AES/CBC/PKCS5Padding} (128)</li>
 * <li>{@code AES/ECB/NoPadding} (128)</li>
 * <li>{@code AES/ECB/PKCS5Padding} (128)</li>
 * <li>{@code AES/GCM/NoPadding} (128, 256)</li>
 * <li>{@code ChaCha20-Poly1305}</li>
 * <li>{@code DESede/CBC/NoPadding} (168)</li>
 * <li>{@code DESede/CBC/PKCS5Padding} (168)</li>
 * <li>{@code DESede/ECB/NoPadding} (168)</li>
 * <li>{@code DESede/ECB/PKCS5Padding} (168)</li>
 * <li>{@code RSA/ECB/PKCS1Padding} (1024, 2048)</li>
 * <li>{@code RSA/ECB/OAEPWithSHA-1AndMGF1Padding} (1024, 2048)</li>
 * <li>{@code RSA/ECB/OAEPWithSHA-256AndMGF1Padding} (1024, 2048)</li>
 * </ul>
 * These transformations are described in the
 * <a href="{@docRoot}/../specs/security/standard-names.html#cipher-algorithms">
 * Cipher section</a> of the
 * Java Security Standard Algorithm Names Specification.
 * Consult the release documentation for your implementation to see if any
 * other transformations are supported.
 *
 * @spec https://www.rfc-editor.org/info/rfc5116
 *      RFC 5116: An Interface and Algorithms for Authenticated Encryption
 * @spec https://www.rfc-editor.org/info/rfc7539
 *      RFC 7539: ChaCha20 and Poly1305 for IETF Protocols
 * @spec security/standard-names.html Java Security Standard Algorithm Names
 * @author Jan Luehe
 * @see KeyGenerator
 * @see SecretKey
 * @since 1.4
 */

public class Cipher {

    private static final Debug debug =
                        Debug.getInstance("jca", "Cipher");

    private static final Debug pdebug =
                        Debug.getInstance("provider", "Provider");
    private static final boolean skipDebug =
        Debug.isOn("engine=") && !Debug.isOn("cipher");

    /**
     * Constant used to initialize cipher to encryption mode.
     */
    public static final int ENCRYPT_MODE = 1;

    /**
     * Constant used to initialize cipher to decryption mode.
     */
    public static final int DECRYPT_MODE = 2;

    /**
     * Constant used to initialize cipher to key-wrapping mode.
     */
    public static final int WRAP_MODE = 3;

    /**
     * Constant used to initialize cipher to key-unwrapping mode.
     */
    public static final int UNWRAP_MODE = 4;

    /**
     * Constant used to indicate the to-be-unwrapped key is a "public key".
     */
    public static final int PUBLIC_KEY = 1;

    /**
     * Constant used to indicate the to-be-unwrapped key is a "private key".
     */
    public static final int PRIVATE_KEY = 2;

    /**
     * Constant used to indicate the to-be-unwrapped key is a "secret key".
     */
    public static final int SECRET_KEY = 3;

    // The provider
    private Provider provider;

    // The provider implementation (delegate)
    private CipherSpi spi;

    // The transformation
    private final String transformation;

    // Crypto permission representing the maximum allowable cryptographic
    // strength that this cipher can be used for. (The cryptographic
    // strength is a function of the keysize and algorithm parameters encoded
    // in the crypto permission.)
    private CryptoPermission cryptoPerm;

    // The exemption mechanism that needs to be enforced
    private ExemptionMechanism exmech;

    // Flag which indicates whether or not this cipher has been initialized
    private boolean initialized = false;

    // The operation mode - store the operation mode after the
    // cipher has been initialized.
    private int opmode = 0;

    // next SPI  to try in provider selection
    // null once provider is selected
    private CipherSpi firstSpi;

    // next service to try in provider selection
    // null once provider is selected
    private Service firstService;

    // remaining services to try in provider selection
    // null once provider is selected
    private Iterator<Service> serviceIterator;

    // list of transform Strings to lookup in the provider
    private List<Transform> transforms;

    private final Object lock;

    /**
     * Creates a {@code Cipher} object.
     *
     * @param cipherSpi the delegate
     * @param provider the provider
     * @param transformation the transformation
     * @throws NullPointerException if {@code provider} is {@code null}
     * @throws IllegalArgumentException if the supplied arguments
     *         are deemed invalid for constructing the {@code Cipher} object
     */
    protected Cipher(CipherSpi cipherSpi,
                     Provider provider,
                     String transformation) {
        // See bug 4341369 & 4334690 for more info.
        // If the caller is trusted, then okay.
        // Otherwise throw an IllegalArgumentException.
        if (!JceSecurityManager.INSTANCE.isCallerTrusted(
                JceSecurityManager.WALKER.getCallerClass(), provider)) {
            throw new IllegalArgumentException("Cannot construct cipher");
        }
        this.spi = cipherSpi;
        this.provider = provider;
        this.transformation = transformation;
        this.cryptoPerm = CryptoAllPermission.INSTANCE;
        this.lock = null;
    }

    /**
     * Creates a {code Cipher} object. Called internally by {code NullCipher}.
     *
     * @param cipherSpi the delegate
     * @param transformation the transformation
     */
    Cipher(CipherSpi cipherSpi, String transformation) {
        this.spi = cipherSpi;
        this.transformation = transformation;
        this.cryptoPerm = CryptoAllPermission.INSTANCE;
        this.lock = null;
    }

    private Cipher(CipherSpi firstSpi, Service firstService,
            Iterator<Service> serviceIterator, String transformation,
            List<Transform> transforms) {
        this.firstSpi = firstSpi;
        this.firstService = firstService;
        this.serviceIterator = serviceIterator;
        this.transforms = transforms;
        this.transformation = transformation;
        this.lock = new Object();
    }

    private static final String SHA512TRUNCATED = "SHA512/2";

    private static String[] tokenizeTransformation(String transformation)
            throws NoSuchAlgorithmException {
        if (transformation == null) {
            throw new NoSuchAlgorithmException("No transformation given");
        }
        /*
         * array containing the components of a cipher transformation:
         *
         * index 0: algorithm component (e.g., AES)
         * index 1: feedback component (e.g., CFB)
         * index 2: padding component (e.g., PKCS5Padding)
         */
        String[] parts = { "", "", "" };

        // check if the transformation contains algorithms with "/" in their
        // name which can cause the parsing logic to go wrong
        int sha512Idx = transformation.toUpperCase(Locale.ENGLISH)
                .indexOf(SHA512TRUNCATED);
        int startIdx = (sha512Idx == -1 ? 0 :
                sha512Idx + SHA512TRUNCATED.length());
        int endIdx = transformation.indexOf('/', startIdx);
        if (endIdx == -1) {
            // algorithm
            parts[0] = transformation.trim();
        } else {
            // algorithm/mode/padding
            parts[0] = transformation.substring(0, endIdx).trim();
            startIdx = endIdx+1;
            endIdx = transformation.indexOf('/', startIdx);
            if (endIdx == -1) {
                throw new NoSuchAlgorithmException("Invalid transformation"
                            + " format:" + transformation);
            }
            parts[1] = transformation.substring(startIdx, endIdx).trim();
            parts[2] = transformation.substring(endIdx+1).trim();
        }
        if (parts[0].isEmpty()) {
            throw new NoSuchAlgorithmException("Invalid transformation: " +
                                   "algorithm not specified-"
                                   + transformation);
        }
        return parts;
    }

    // Provider attribute name for supported chaining mode
    private static final String ATTR_MODE = "SupportedModes";
    // Provider attribute name for supported padding names
    private static final String ATTR_PAD  = "SupportedPaddings";

    // constants indicating whether the provider supports
    // a given mode or padding
    private static final int S_NO    = 0;       // does not support
    private static final int S_MAYBE = 1;       // unable to determine
    private static final int S_YES   = 2;       // does support

    /**
     * Nested class to deal with modes and paddings.
     */
    private static class Transform {
        // transform string to lookup in the provider
        final String transform;
        // the mode/padding suffix in upper case. for example, if the algorithm
        // to lookup is "AES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING"
        // if lookup is "AES", suffix is the empty string
        // needed because aliases prevent straight transform.equals()
        final String suffix;
        // value to pass to setMode() or null if no such call required
        final String mode;
        // value to pass to setPadding() or null if no such call required
        final String pad;
        Transform(String alg, String suffix, String mode, String pad) {
            this.transform = alg + suffix;
            this.suffix = suffix.toUpperCase(Locale.ENGLISH);
            this.mode = mode;
            this.pad = pad;
        }
        // set mode and padding for the given SPI
        void setModePadding(CipherSpi spi) throws NoSuchAlgorithmException,
                NoSuchPaddingException {
            if (mode != null) {
                spi.engineSetMode(mode);
            }
            if (pad != null) {
                spi.engineSetPadding(pad);
            }
        }
        // check whether the given services supports the mode and
        // padding described by this Transform
        int supportsModePadding(Service s) {
            int smode = supportsMode(s);
            if (smode == S_NO) {
                return smode;
            }
            int spad = supportsPadding(s);
            // our constants are defined so that Math.min() is a tri-valued AND
            return Math.min(smode, spad);
        }

        // separate methods for mode and padding
        // called directly by cipher only to throw the correct exception
        int supportsMode(Service s) {
            return supports(s, ATTR_MODE, mode);
        }
        int supportsPadding(Service s) {
            return supports(s, ATTR_PAD, pad);
        }

        private static int supports(Service s, String attrName, String value) {
            if (value == null) {
                return S_YES;
            }
            String regexp = s.getAttribute(attrName);
            if (regexp == null) {
                return S_MAYBE;
            }
            return matches(regexp, value) ? S_YES : S_NO;
        }

        // ConcurrentMap<String,Pattern> for previously compiled patterns
        private static final ConcurrentMap<String, Pattern> patternCache =
            new ConcurrentHashMap<String, Pattern>();

        private static boolean matches(String regexp, String str) {
            Pattern pattern = patternCache.get(regexp);
            if (pattern == null) {
                pattern = Pattern.compile(regexp);
                patternCache.putIfAbsent(regexp, pattern);
            }
            return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches();
        }

    }

    private static List<Transform> getTransforms(String transformation)
            throws NoSuchAlgorithmException {
        String[] parts = tokenizeTransformation(transformation);

        String alg = parts[0];
        String mode = parts[1];
        String pad = parts[2];

        if ((mode.length() == 0) && (pad.length() == 0)) {
            // Algorithm only
            Transform tr = new Transform(alg, "", null, null);
            return Collections.singletonList(tr);
        } else {
            // Algorithm w/ at least mode or padding or both
            List<Transform> list = new ArrayList<>(4);
            list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
            list.add(new Transform(alg, "/" + mode, null, pad));
            list.add(new Transform(alg, "//" + pad, mode, null));
            list.add(new Transform(alg, "", mode, pad));
            return list;
        }
    }

    // get the transform matching the specified service
    private static Transform getTransform(Service s,
                                          List<Transform> transforms) {
        String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH);
        for (Transform tr : transforms) {
            if (alg.endsWith(tr.suffix)) {
                return tr;
            }
        }
        return null;
    }

    /**
     * Returns a {@code Cipher} object that implements the specified
     * transformation.
     *
     * <p> This method traverses the list of registered security providers,
     * starting with the most preferred provider.
     * A new {@code Cipher} object encapsulating the
     * {@code CipherSpi} implementation from the first
     * provider that supports the specified algorithm is returned.
     *
     * <p> Note that the list of registered providers may be retrieved via
     * the {@link Security#getProviders() Security.getProviders()} method.
     *
     * @apiNote
     * It is recommended to use a transformation that fully specifies the
     * algorithm, mode, and padding. By not doing so, the provider will
     * use a default for the mode and padding which may not meet the security
     * requirements of your application.
     *
     * @implNote
     * The JDK Reference Implementation additionally uses the
     * {@code jdk.security.provider.preferred}
     * {@link Security#getProperty(String) Security} property to determine
     * the preferred provider order for the specified algorithm. This
     * may be different than the order of providers returned by
     * {@link Security#getProviders() Security.getProviders()}.
     * See also the Cipher Transformations section of the {@extLink
     * security_guide_jdk_providers JDK Providers} document for information
     * on the transformation defaults used by JDK providers.
     *
     * @param transformation the name of the transformation, e.g.,
     * <i>AES/CBC/PKCS5Padding</i>.
     * See the Cipher section in the <a href=
     *   "{@docRoot}/../specs/security/standard-names.html#cipher-algorithms">
     * Java Security Standard Algorithm Names Specification</a>
     * for information about standard transformation names.
     *
     * @spec security/standard-names.html Java Security Standard Algorithm Names
     * @return a {@code Cipher} object that implements the requested
     * transformation
     *
     * @throws NoSuchAlgorithmException if {@code transformation}
     *         is {@code null}, empty, in an invalid format,
     *         or if no provider supports a {@code CipherSpi}
     *         implementation for the specified algorithm
     *
     * @throws NoSuchPaddingException if {@code transformation}
     *         contains a padding scheme that is not available
     *
     * @see java.security.Provider
     */
    public static final Cipher getInstance(String transformation)
            throws NoSuchAlgorithmException, NoSuchPaddingException
    {
        if ((transformation == null) || transformation.isEmpty()) {
            throw new NoSuchAlgorithmException("Null or empty transformation");
        }
        List<Transform> transforms = getTransforms(transformation);
        List<ServiceId> cipherServices = new ArrayList<>(transforms.size());
        for (Transform transform : transforms) {
            cipherServices.add(new ServiceId("Cipher", transform.transform));
        }
        // make sure there is at least one service from a signed provider
        // and that it can use the specified mode and padding
        Iterator<Service> t = GetInstance.getServices(cipherServices);
        Exception failure = null;
        while (t.hasNext()) {
            Service s = t.next();
            if (JceSecurity.canUseProvider(s.getProvider()) == false) {
                continue;
            }
            Transform tr = getTransform(s, transforms);
            if (tr == null) {
                // should never happen
                continue;
            }
            int canuse = tr.supportsModePadding(s);
            if (canuse == S_NO) {
                // does not support mode or padding we need, ignore
                continue;
            }
            // S_YES, S_MAYBE
            // even when mode and padding are both supported, they
            // may not be used together, try out and see if it works
            try {
                CipherSpi spi = (CipherSpi)s.newInstance(null);
                tr.setModePadding(spi);
                // specify null instead of spi for delayed provider selection
                return new Cipher(null, s, t, transformation, transforms);
            } catch (Exception e) {
                failure = e;
            }
        }
        throw new NoSuchAlgorithmException
            ("Cannot find any provider supporting " + transformation, failure);
    }

    /**
     * Returns a {@code Cipher} object that implements the specified
     * transformation.
     *
     * <p> A new {@code Cipher} object encapsulating the
     * {@code CipherSpi} implementation from the specified provider
     * is returned.  The specified provider must be registered
     * in the security provider list.
     *
     * <p> Note that the list of registered providers may be retrieved via
     * the {@link Security#getProviders() Security.getProviders()} method.
     *
     * @apiNote
     * It is recommended to use a transformation that fully specifies the
     * algorithm, mode, and padding. By not doing so, the provider will
     * use a default for the mode and padding which may not meet the security
     * requirements of your application.
     *
     * @implNote
     * See the Cipher Transformations section of the {@extLink
     * security_guide_jdk_providers JDK Providers} document for information
     * on the transformation defaults used by JDK providers.
     *
     * @param transformation the name of the transformation,
     * e.g., <i>AES/CBC/PKCS5Padding</i>.
     * See the Cipher section in the <a href=
     *   "{@docRoot}/../specs/security/standard-names.html#cipher-algorithms">
     * Java Security Standard Algorithm Names Specification</a>
     * for information about standard transformation names.
     *
     * @param provider the name of the provider
     *
     * @spec security/standard-names.html Java Security Standard Algorithm Names
     * @return a {@code Cipher} object that implements the requested
     * transformation
     *
     * @throws IllegalArgumentException if the {@code provider}
     *         is {@code null} or empty
     *
     * @throws NoSuchAlgorithmException if {@code transformation}
     *         is {@code null}, empty, in an invalid format,
     *         or if a {@code CipherSpi} implementation for the
     *         specified algorithm is not available from the specified
     *         provider
     *
     * @throws NoSuchPaddingException if {@code transformation}
     *         contains a padding scheme that is not available
     *
     * @throws NoSuchProviderException if the specified provider is not
     *         registered in the security provider list
     *
     * @see java.security.Provider
     */
    public static final Cipher getInstance(String transformation,
                                           String provider)
            throws NoSuchAlgorithmException, NoSuchProviderException,
            NoSuchPaddingException
    {
        if ((transformation == null) || transformation.isEmpty()) {
            throw new NoSuchAlgorithmException("Null or empty transformation");
        }
        if ((provider == null) || (provider.isEmpty())) {
            throw new IllegalArgumentException("Missing provider");
        }
        Provider p = Security.getProvider(provider);
        if (p == null) {
            throw new NoSuchProviderException("No such provider: " +
                                              provider);
        }
        return getInstance(transformation, p);
    }

    private String getProviderName() {
        return (provider == null)  ? "(no provider)" : provider.getName();
    }

    /**
     * Returns a {@code Cipher} object that implements the specified
     * transformation.
     *
     * <p> A new {@code Cipher} object encapsulating the
     * {@code CipherSpi} implementation from the specified {@code provider}
     * object is returned.  Note that the specified {@code provider} object
     * does not have to be registered in the provider list.
     *
     * @apiNote
     * It is recommended to use a transformation that fully specifies the
     * algorithm, mode, and padding. By not doing so, the provider will
     * use a default for the mode and padding which may not meet the security
     * requirements of your application.
     *
     * @implNote
     * See the Cipher Transformations section of the {@extLink
     * security_guide_jdk_providers JDK Providers} document for information
     * on the transformation defaults used by JDK providers.
     *
     * @param transformation the name of the transformation,
     * e.g., <i>AES/CBC/PKCS5Padding</i>.
     * See the Cipher section in the <a href=
     *   "{@docRoot}/../specs/security/standard-names.html#cipher-algorithms">
     * Java Security Standard Algorithm Names Specification</a>
     * for information about standard transformation names.
     *
     * @param provider the provider
     *
     * @spec security/standard-names.html Java Security Standard Algorithm Names
     * @return a {@code Cipher} object that implements the requested
     * transformation
     *
     * @throws IllegalArgumentException if the {@code provider}
     *         is {@code null}
     *
     * @throws NoSuchAlgorithmException if {@code transformation}
     *         is {@code null}, empty, in an invalid format,
     *         or if a {@code CipherSpi} implementation for the
     *         specified algorithm is not available from the specified
     *         {@code provider} object
     *
     * @throws NoSuchPaddingException if {@code transformation}
     *         contains a padding scheme that is not available
     *
     * @see java.security.Provider
     */
    public static final Cipher getInstance(String transformation,
                                           Provider provider)
            throws NoSuchAlgorithmException, NoSuchPaddingException
    {
        if ((transformation == null) || transformation.isEmpty()) {
            throw new NoSuchAlgorithmException("Null or empty transformation");
        }
        if (provider == null) {
            throw new IllegalArgumentException("Missing provider");
        }
        Exception failure = null;
        List<Transform> transforms = getTransforms(transformation);
        boolean providerChecked = false;
        String paddingError = null;
        for (Transform tr : transforms) {
            Service s = provider.getService("Cipher", tr.transform);
            if (s == null) {
                continue;
            }
            if (providerChecked == false) {
                // for compatibility, first do the lookup and then verify
                // the provider. this makes the difference between a NSAE
                // and a SecurityException if the
                // provider does not support the algorithm.
                Exception ve = JceSecurity.getVerificationResult(provider);
                if (ve != null) {
                    String msg = "JCE cannot authenticate the provider "
                        + provider.getName();
                    throw new SecurityException(msg, ve);
                }
                providerChecked = true;
            }
            if (tr.supportsMode(s) == S_NO) {
                continue;
            }
            if (tr.supportsPadding(s) == S_NO) {
                paddingError = tr.pad;
                continue;
            }
            try {
                CipherSpi spi = (CipherSpi)s.newInstance(null);
                tr.setModePadding(spi);
                Cipher cipher = new Cipher(spi, transformation);
                cipher.provider = s.getProvider();
                cipher.initCryptoPermission();
                return cipher;
            } catch (Exception e) {
                failure = e;
            }
        }

        // throw NoSuchPaddingException if the problem is with padding
        if (failure instanceof NoSuchPaddingException) {
            throw (NoSuchPaddingException)failure;
        }
        if (paddingError != null) {
            throw new NoSuchPaddingException
                ("Padding not supported: " + paddingError);
        }
        throw new NoSuchAlgorithmException
                ("No such algorithm: " + transformation, failure);
    }

    // If the requested crypto service is export-controlled,
    // determine the maximum allowable keysize.
    private void initCryptoPermission() throws NoSuchAlgorithmException {
        if (JceSecurity.isRestricted() == false) {
            cryptoPerm = CryptoAllPermission.INSTANCE;
            exmech = null;
            return;
        }
        cryptoPerm = getConfiguredPermission(transformation);
        // Instantiate the exemption mechanism (if required)
        String exmechName = cryptoPerm.getExemptionMechanism();
        if (exmechName != null) {
            exmech = ExemptionMechanism.getInstance(exmechName);
        }
    }

    // max number of debug warnings to print from chooseFirstProvider()
    private static int warnCount = 10;

    /**
     * Choose the Spi from the first provider available. Used if
     * delayed provider selection is not possible because init()
     * is not the first method called.
     */
    void chooseFirstProvider() {
        if (spi != null) {
            return;
        }
        synchronized (lock) {
            if (spi != null) {
                return;
            }
            if (debug != null) {
                int w = --warnCount;
                if (w >= 0) {
                    debug.println("Cipher.init() not first method "
                        + "called, disabling delayed provider selection");
                    if (w == 0) {
                        debug.println("Further warnings of this type will "
                            + "be suppressed");
                    }
                    new Exception("Call trace").printStackTrace();
                }
            }
            Exception lastException = null;
            while ((firstService != null) || serviceIterator.hasNext()) {
                Service s;
                CipherSpi thisSpi;
                if (firstService != null) {
                    s = firstService;
                    thisSpi = firstSpi;
                    firstService = null;
                    firstSpi = null;
                } else {
                    s = serviceIterator.next();
                    thisSpi = null;
                }
                if (JceSecurity.canUseProvider(s.getProvider()) == false) {
                    continue;
                }
                Transform tr = getTransform(s, transforms);
                if (tr == null) {
                    // should never happen
                    continue;
                }
                if (tr.supportsModePadding(s) == S_NO) {
                    continue;
                }
                try {
                    if (thisSpi == null) {
                        Object obj = s.newInstance(null);
                        if (obj instanceof CipherSpi == false) {
                            continue;
                        }
                        thisSpi = (CipherSpi)obj;
                    }
                    tr.setModePadding(thisSpi);
                    initCryptoPermission();
                    spi = thisSpi;
                    provider = s.getProvider();
                    // not needed any more
                    firstService = null;
                    serviceIterator = null;
                    transforms = null;
                    return;
                } catch (Exception e) {
                    lastException = e;
                }
            }
            ProviderException e = new ProviderException
                    ("Could not construct CipherSpi instance");
            if (lastException != null) {
                e.initCause(lastException);
            }
            throw e;
        }
    }

    private static final int I_KEY       = 1;
    private static final int I_PARAMSPEC = 2;
    private static final int I_PARAMS    = 3;
    private static final int I_CERT      = 4;

    private void implInit(CipherSpi thisSpi, int type, int opmode, Key key,
            AlgorithmParameterSpec paramSpec, AlgorithmParameters params,
            SecureRandom random) throws InvalidKeyException,
            InvalidAlgorithmParameterException {
        switch (type) {
        case I_KEY:
            checkCryptoPerm(thisSpi, key);
            thisSpi.engineInit(opmode, key, random);
            break;
        case I_PARAMSPEC:
            checkCryptoPerm(thisSpi, key, paramSpec);
            thisSpi.engineInit(opmode, key, paramSpec, random);
            break;
        case I_PARAMS:
            checkCryptoPerm(thisSpi, key, params);
            thisSpi.engineInit(opmode, key, params, random);
            break;
        case I_CERT:
            checkCryptoPerm(thisSpi, key);
            thisSpi.engineInit(opmode, key, random);
            break;
        default:
            throw new AssertionError("Internal Cipher error: " + type);
        }
    }

    private void chooseProvider(int initType, int opmode, Key key,
            AlgorithmParameterSpec paramSpec,
            AlgorithmParameters params, SecureRandom random)
            throws InvalidKeyException, InvalidAlgorithmParameterException {
        synchronized (lock) {
            if (spi != null) {
                implInit(spi, initType, opmode, key, paramSpec, params, random);
                return;
            }
            Exception lastException = null;
            while ((firstService != null) || serviceIterator.hasNext()) {
                Service s;
                CipherSpi thisSpi;
                if (firstService != null) {
                    s = firstService;
                    thisSpi = firstSpi;
                    firstService = null;
                    firstSpi = null;
                } else {
                    s = serviceIterator.next();
                    thisSpi = null;
                }
                // if provider says it does not support this key, ignore it
                if (s.supportsParameter(key) == false) {
                    continue;
                }
                if (JceSecurity.canUseProvider(s.getProvider()) == false) {
                    continue;
                }
                Transform tr = getTransform(s, transforms);
                if (tr == null) {
                    // should never happen
                    continue;
                }
                if (tr.supportsModePadding(s) == S_NO) {
                    continue;
                }
                try {
                    if (thisSpi == null) {
                        thisSpi = (CipherSpi)s.newInstance(null);
                    }
                    tr.setModePadding(thisSpi);
                    initCryptoPermission();
                    implInit(thisSpi, initType, opmode, key, paramSpec,
                                                        params, random);
                    provider = s.getProvider();
                    this.spi = thisSpi;
                    firstService = null;
                    serviceIterator = null;
                    transforms = null;
                    return;
                } catch (Exception e) {
                    // NoSuchAlgorithmException from newInstance()
                    // InvalidKeyException from init()
                    // RuntimeException (ProviderException) from init()
                    // SecurityException from crypto permission check
                    if (lastException == null) {
                        lastException = e;
                    }
                }
            }
            // no working provider found, fail
            if (lastException instanceof InvalidKeyException) {
                throw (InvalidKeyException)lastException;
            }
            if (lastException instanceof InvalidAlgorithmParameterException) {
                throw (InvalidAlgorithmParameterException)lastException;
            }
            if (lastException instanceof RuntimeException) {
                throw (RuntimeException)lastException;
            }
            String kName = (key != null) ? key.getClass().getName() : "(null)";
            throw new InvalidKeyException
                ("No installed provider supports this key: "
                + kName, lastException);
        }
    }

    /**
     * Returns the provider of this {@code Cipher} object.
     *
     * @return the provider of this {@code Cipher} object
     */
    public final Provider getProvider() {
        chooseFirstProvider();
        return this.provider;
    }

    /**
     * Returns the algorithm name of this {@code Cipher} object.
     *
     * <p>This is the same name that was specified in one of the
     * {@code getInstance} calls that created this {@code Cipher}
     * object.
     *
     * @return the algorithm name of this {@code Cipher} object
     */
    public final String getAlgorithm() {
        return this.transformation;
    }

    /**
     * Returns the block size (in bytes).
     *
     * @return the block size (in bytes), or 0 if this cipher is
     * not a block cipher
     */
    public final int getBlockSize() {
        chooseFirstProvider();
        return spi.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} or
     * {@code doFinal} operation, given the input length
     * {@code inputLen} (in bytes).
     *
     * <p>This call takes into account any unprocessed (buffered) data from a
     * previous {@code update} call, padding, and AEAD tagging.
     *
     * <p>The actual output length of the next {@code update} or
     * {@code doFinal} 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)
     *
     * @throws IllegalStateException if this {@code Cipher} object is in a
     * wrong state (e.g., has not yet been initialized)
     */
    public final int getOutputSize(int inputLen) {

        if (!initialized && !(this instanceof NullCipher)) {
            throw new IllegalStateException("Cipher not initialized");
        }
        if (inputLen < 0) {
            throw new IllegalArgumentException("Input size must be equal " +
                                               "to or greater than zero");
        }
        chooseFirstProvider();
        return spi.engineGetOutputSize(inputLen);
    }

    /**
     * Returns the initialization vector (IV) in a new buffer.
     *
     * <p>This is useful in the case where a random IV was created,
     * or in the context of password-based encryption or
     * decryption, where the IV is derived from a user-supplied password.
     *
     * @return the initialization vector in a new buffer, or {@code null} if
     * this cipher does not use an IV, or if the IV has not yet
     * been set.
     */
    public final byte[] getIV() {
        chooseFirstProvider();
        return spi.engineGetIV();
    }

    /**
     * Returns the parameters used with this {@code Cipher} object.
     *
     * <p>The returned parameters may be the same that were used to initialize
     * this cipher, or may contain additional default or random parameter
     * values used by the underlying cipher implementation. If the required
     * parameters were not supplied and can be generated by the cipher, the
     * generated parameters are returned. Otherwise, {@code null} is returned.
     *
     * @return the parameters used with this cipher, or {@code null}
     */
    public final AlgorithmParameters getParameters() {
        chooseFirstProvider();
        return spi.engineGetParameters();
    }

    /**
     * Returns the exemption mechanism object used with this {@code Cipher}
     * object.
     *
     * @return the exemption mechanism object used with this {@code Cipher}
     * object, or {@code null} if this {@code Cipher} object does not use any
     * exemption mechanism.
     */
    public final ExemptionMechanism getExemptionMechanism() {
        chooseFirstProvider();
        return exmech;
    }

    //
    // Crypto permission check code below
    //
    private void checkCryptoPerm(CipherSpi checkSpi, Key key)
            throws InvalidKeyException {
        if (cryptoPerm == CryptoAllPermission.INSTANCE) {
            return;
        }
        // Check if key size and default parameters are within legal limits
        AlgorithmParameterSpec params;
        try {
            params = getAlgorithmParameterSpec(checkSpi.engineGetParameters());
        } catch (InvalidParameterSpecException ipse) {
            throw new InvalidKeyException
                ("Unsupported default algorithm parameters");
        }
        if (!passCryptoPermCheck(checkSpi, key, params)) {
            throw new InvalidKeyException(
                "Illegal key size or default parameters");
        }
    }

    private void checkCryptoPerm(CipherSpi checkSpi, Key key,
            AlgorithmParameterSpec params) throws InvalidKeyException,
            InvalidAlgorithmParameterException {
        if (cryptoPerm == CryptoAllPermission.INSTANCE) {
            return;
        }
        // Determine keysize and check if it is within legal limits
        if (!passCryptoPermCheck(checkSpi, key, null)) {
            throw new InvalidKeyException("Illegal key size");
        }
        if ((params != null) && (!passCryptoPermCheck(checkSpi, key, params))) {
            throw new InvalidAlgorithmParameterException("Illegal parameters");
        }
    }

    private void checkCryptoPerm(CipherSpi checkSpi, Key key,
            AlgorithmParameters params)
            throws InvalidKeyException, InvalidAlgorithmParameterException {
        if (cryptoPerm == CryptoAllPermission.INSTANCE) {
            return;
        }
        // Convert the specified parameters into specs and then delegate.
        AlgorithmParameterSpec pSpec;
        try {
            pSpec = getAlgorithmParameterSpec(params);
        } catch (InvalidParameterSpecException ipse) {
            throw new InvalidAlgorithmParameterException
                ("Failed to retrieve algorithm parameter specification");
        }
        checkCryptoPerm(checkSpi, key, pSpec);
    }

    private boolean passCryptoPermCheck(CipherSpi checkSpi, Key key,
                                        AlgorithmParameterSpec params)
            throws InvalidKeyException {
        String em = cryptoPerm.getExemptionMechanism();
        int keySize = checkSpi.engineGetKeySize(key);
        // Use the "algorithm" component of the cipher
        // transformation so that the perm check would
        // work when the key has the "aliased" algo.
        String algComponent;
        int index = transformation.indexOf('/');
        if (index != -1) {
            algComponent = transformation.substring(0, index);
        } else {
            algComponent = transformation;
        }
        CryptoPermission checkPerm =
            new CryptoPermission(algComponent, keySize, params, em);

        if (!cryptoPerm.implies(checkPerm)) {
            if (debug != null) {
                debug.println("Crypto Permission check failed");
                debug.println("granted: " + cryptoPerm);
                debug.println("requesting: " + checkPerm);
            }
            return false;
        }
        if (exmech == null) {
            return true;
        }
        try {
            if (!exmech.isCryptoAllowed(key)) {
                if (debug != null) {
                    debug.println(exmech.getName() + " isn't enforced");
                }
                return false;
            }
        } catch (ExemptionMechanismException eme) {
            if (debug != null) {
                debug.println("Cannot determine whether "+
                              exmech.getName() + " has been enforced");
                eme.printStackTrace();
            }
            return false;
        }
        return true;
    }

    // check if opmode is one of the defined constants
    // throw InvalidParameterException if not
    private static void checkOpmode(int opmode) {
        if ((opmode < ENCRYPT_MODE) || (opmode > UNWRAP_MODE)) {
            throw new InvalidParameterException("Invalid operation mode");
        }
    }

    /**
     * Initializes this {@code Cipher} object with a key.
     *
     * <p>The {@code Cipher} object is initialized for one of the following four
     * operations:
     * encryption, decryption, key wrapping or key unwrapping, depending
     * on the value of {@code opmode}.
     *
     * <p>If this cipher requires any algorithm parameters that cannot be
     * derived from the given {@code key}, 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} if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #getParameters() getParameters} or
     * {@link #getIV() getIV} (if the parameter is an IV).
     *
     * <p>If this cipher requires algorithm parameters that cannot be
     * derived from the input parameters, and there are no reasonable
     * provider-specific default values, initialization will
     * necessarily fail.
     *
     * <p>If this cipher (including its feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them using the {@link java.security.SecureRandom}
     * implementation of the highest-priority
     * installed provider as the source of randomness.
     * (If none of the installed providers supply an implementation of
     * SecureRandom, a system-provided source of randomness will be used.)
     *
     * <p>Note that when a {@code Cipher} object is initialized, it loses all
     * previously-acquired state. In other words, initializing a {@code Cipher}
     * object is equivalent to creating a new instance of that {@code Cipher}
     * object and initializing it.
     *
     * @param opmode the operation mode of this {@code Cipher} object
     * (this is one of the following:
     * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},
     * {@code WRAP_MODE} or {@code UNWRAP_MODE})
     * @param key the key
     *
     * @throws InvalidKeyException if the given key is inappropriate for
     * initializing this cipher, or requires
     * algorithm parameters that cannot be
     * determined from the given key, or if the given key has a keysize that
     * exceeds the maximum allowable keysize (as determined from the
     * configured jurisdiction policy files)
     * @throws UnsupportedOperationException if {@code opmode} is
     * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
     * by the underlying {@code CipherSpi}
     * @throws InvalidParameterException if {@code opmode} is not one of the
     * recognized values
     */
    public final void init(int opmode, Key key) throws InvalidKeyException {
        init(opmode, key, JCAUtil.getDefSecureRandom());
    }

    /**
     * Initializes this {@code Cipher} object with a key and a
     * source of randomness.
     *
     * <p>The {@code Cipher} object is initialized for one of the following four
     * operations:
     * encryption, decryption, key wrapping or  key unwrapping, depending
     * on the value of {@code opmode}.
     *
     * <p>If this cipher requires any algorithm parameters that cannot be
     * derived from the given {@code key}, 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} if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #getParameters() getParameters} or
     * {@link #getIV() getIV} (if the parameter is an IV).
     *
     * <p>If this cipher requires algorithm parameters that cannot be
     * derived from the input parameters, and there are no reasonable
     * provider-specific default values, initialization will
     * necessarily fail.
     *
     * <p>If this cipher (including its feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them from {@code random}.
     *
     * <p>Note that when a {@code Cipher} object is initialized, it loses all
     * previously-acquired state. In other words, initializing a {@code Cipher}
     * object is equivalent to creating a new instance of that
     * {@code Cipher} object and initializing it.
     *
     * @param opmode the operation mode of this {@code Cipher} object
     * (this is one of the following:
     * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},
     * {@code WRAP_MODE} or {@code UNWRAP_MODE})
     * @param key the encryption key
     * @param random the source of randomness
     *
     * @throws InvalidKeyException if the given key is inappropriate for
     * initializing this cipher, or requires
     * algorithm parameters that cannot be
     * determined from the given key, or if the given key has a keysize that
     * exceeds the maximum allowable keysize (as determined from the
     * configured jurisdiction policy files)
     * @throws UnsupportedOperationException if {@code opmode} is
     * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
     * by the underlying {@code CipherSpi}
     * @throws InvalidParameterException if {@code opmode} is not one of the
     * recognized values
     */
    public final void init(int opmode, Key key, SecureRandom random)
            throws InvalidKeyException
    {
        initialized = false;
        checkOpmode(opmode);

        if (spi != null) {
            checkCryptoPerm(spi, key);
            spi.engineInit(opmode, key, random);
        } else {
            try {
                chooseProvider(I_KEY, opmode, key, null, null, random);
            } catch (InvalidAlgorithmParameterException e) {
                // should never occur
                throw new InvalidKeyException(e);
            }
        }

        initialized = true;
        this.opmode = opmode;

        if (!skipDebug && pdebug != null) {
            pdebug.println(this.toString());
        }
    }

    /**
     * Initializes this {@code Cipher} object with a key and a set of algorithm
     * parameters.
     *
     * <p>The {@code Cipher} object is initialized for one of the following four
     * operations:
     * encryption, decryption, key wrapping or  key unwrapping, depending
     * on the value of {@code opmode}.
     *
     * <p>If this cipher requires any algorithm parameters and
     * {@code params} is {@code 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} if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #getParameters() getParameters} or
     * {@link #getIV() getIV} (if the parameter is an IV).
     *
     * <p>If this cipher requires algorithm parameters that cannot be
     * derived from the input parameters, and there are no reasonable
     * provider-specific default values, initialization will
     * necessarily fail.
     *
     * <p>If this cipher (including its feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them using the {@link java.security.SecureRandom}
     * implementation of the highest-priority
     * installed provider as the source of randomness.
     * (If none of the installed providers supply an implementation of
     * SecureRandom, a system-provided source of randomness will be used.)
     *
     * <p>Note that when a {@code Cipher} object is initialized, it loses all
     * previously-acquired state. In other words, initializing a {@code Cipher}
     * object is equivalent to creating a new instance of that {@code Cipher}
     * object and initializing it.
     *
     * @param opmode the operation mode of this {@code Cipher} object
     * (this is one of the following:
     * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},
     * {@code WRAP_MODE} or {@code UNWRAP_MODE})
     * @param key the encryption key
     * @param params the algorithm parameters
     *
     * @throws InvalidKeyException if the given key is inappropriate for
     * initializing this cipher, or its keysize exceeds the maximum allowable
     * keysize (as determined from the configured jurisdiction policy files)
     * @throws InvalidAlgorithmParameterException if the given algorithm
     * parameters are inappropriate for this cipher,
     * or this cipher requires
     * algorithm parameters and {@code params} is {@code null}, or the given
     * algorithm parameters imply a cryptographic strength that would exceed
     * the legal limits (as determined from the configured jurisdiction
     * policy files)
     * @throws UnsupportedOperationException if {@code opmode} is
     * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
     * by the underlying {@code CipherSpi}
     * @throws InvalidParameterException if {@code opmode} is not one of the
     * recognized values
     *
     */
    public final void init(int opmode, Key key, AlgorithmParameterSpec params)
            throws InvalidKeyException, InvalidAlgorithmParameterException
    {
        init(opmode, key, params, JCAUtil.getDefSecureRandom());
    }

    /**
     * Initializes this {@code Cipher} object with a key, a set of algorithm
     * parameters, and a source of randomness.
     *
     * <p>The {@code Cipher} object is initialized for one of the following four
     * operations:
     * encryption, decryption, key wrapping or  key unwrapping, depending
     * on the value of {@code opmode}.
     *
     * <p>If this cipher requires any algorithm parameters and
     * {@code params} is {@code 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} if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #getParameters() getParameters} or
     * {@link #getIV() getIV} (if the parameter is an IV).
     *
     * <p>If this cipher requires algorithm parameters that cannot be
     * derived from the input parameters, and there are no reasonable
     * provider-specific default values, initialization will
     * necessarily fail.
     *
     * <p>If this cipher (including its feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them from {@code random}.
     *
     * <p>Note that when a {@code Cipher} object is initialized, it loses all
     * previously-acquired state. In other words, initializing a {@code Cipher}
     * object is equivalent to creating a new instance of that {@code Cipher}
     * object and initializing it.
     *
     * @param opmode the operation mode of this {@code Cipher} object
     * (this is one of the following:
     * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},
     * {@code WRAP_MODE} or {@code UNWRAP_MODE})
     * @param key the encryption key
     * @param params the algorithm parameters
     * @param random the source of randomness
     *
     * @throws InvalidKeyException if the given key is inappropriate for
     * initializing this cipher, or its keysize exceeds the maximum allowable
     * keysize (as determined from the configured jurisdiction policy files)
     * @throws InvalidAlgorithmParameterException if the given algorithm
     * parameters are inappropriate for this cipher,
     * or this cipher requires
     * algorithm parameters and {@code params} is {@code null}, or the given
     * algorithm parameters imply a cryptographic strength that would exceed
     * the legal limits (as determined from the configured jurisdiction
     * policy files)
     * @throws UnsupportedOperationException if {@code opmode} is
     * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
     * by the underlying {@code CipherSpi}
     * @throws InvalidParameterException if {@code opmode} is not one of the
     * recognized values
     *
     */
    public final void init(int opmode, Key key, AlgorithmParameterSpec params,
                           SecureRandom random)
            throws InvalidKeyException, InvalidAlgorithmParameterException
    {
        initialized = false;
        checkOpmode(opmode);

        if (spi != null) {
            checkCryptoPerm(spi, key, params);
            spi.engineInit(opmode, key, params, random);
        } else {
            chooseProvider(I_PARAMSPEC, opmode, key, params, null, random);
        }

        initialized = true;
        this.opmode = opmode;

        if (!skipDebug && pdebug != null) {
            pdebug.println(this.toString());
        }
    }

    /**
     * Initializes this {@code Cipher} object with a key and a set of algorithm
     * parameters.
     *
     * <p>The {@code Cipher} object is initialized for one of the following four
     * operations:
     * encryption, decryption, key wrapping or  key unwrapping, depending
     * on the value of {@code opmode}.
     *
     * <p>If this cipher requires any algorithm parameters and
     * {@code params} is {@code 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} if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #getParameters() getParameters} or
     * {@link #getIV() getIV} (if the parameter is an IV).
     *
     * <p>If this cipher requires algorithm parameters that cannot be
     * derived from the input parameters, and there are no reasonable
     * provider-specific default values, initialization will
     * necessarily fail.
     *
     * <p>If this cipher (including its feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them using the {@link java.security.SecureRandom}
     * implementation of the highest-priority
     * installed provider as the source of randomness.
     * (If none of the installed providers supply an implementation of
     * SecureRandom, a system-provided source of randomness will be used.)
     *
     * <p>Note that when a {@code Cipher} object is initialized, it loses all
     * previously-acquired state. In other words, initializing a {@code Cipher}
     * object is equivalent to creating a new instance of that {@code Cipher}
     * object and initializing it.
     *
     * @param opmode the operation mode of this {@code Cipher} object
     * this is one of the following: {@code ENCRYPT_MODE},
     * {@code DECRYPT_MODE}, {@code WRAP_MODE}
     * or {@code UNWRAP_MODE})
     * @param key the encryption key
     * @param params the algorithm parameters
     *
     * @throws InvalidKeyException if the given key is inappropriate for
     * initializing this cipher, or its keysize exceeds the maximum allowable
     * keysize (as determined from the configured jurisdiction policy files).
     * @throws InvalidAlgorithmParameterException if the given algorithm
     * parameters are inappropriate for this cipher,
     * or this cipher requires
     * algorithm parameters and {@code params} is {@code null}, or the given
     * algorithm parameters imply a cryptographic strength that would exceed
     * the legal limits (as determined from the configured jurisdiction
     * policy files)
     * @throws UnsupportedOperationException if {@code opmode} is
     * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
     * by the underlying {@code CipherSpi}
     * @throws InvalidParameterException if {@code opmode} is not one of the
     * recognized values
     */
    public final void init(int opmode, Key key, AlgorithmParameters params)
            throws InvalidKeyException, InvalidAlgorithmParameterException
    {
        init(opmode, key, params, JCAUtil.getDefSecureRandom());
    }

    /**
     * Initializes this {@code Cipher} object with a key, a set of algorithm
     * parameters, and a source of randomness.
     *
     * <p>The {@code Cipher} object is initialized for one of the following four
     * operations:
     * encryption, decryption, key wrapping or  key unwrapping, depending
     * on the value of {@code opmode}.
     *
     * <p>If this cipher requires any algorithm parameters and
     * {@code params} is {@code 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} if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #getParameters() getParameters} or
     * {@link #getIV() getIV} (if the parameter is an IV).
     *
     * <p>If this cipher requires algorithm parameters that cannot be
     * derived from the input parameters, and there are no reasonable
     * provider-specific default values, initialization will
     * necessarily fail.
     *
     * <p>If this cipher (including its feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them from {@code random}.
     *
     * <p>Note that when a {@code Cipher} object is initialized, it loses all
     * previously-acquired state. In other words, initializing a {@code Cipher}
     * object is equivalent to creating a new instance of that {@code Cipher}
     * object and initializing it.
     *
     * @param opmode the operation mode of this {@code Cipher} object
     * (this is one of the following: {@code ENCRYPT_MODE},
     * {@code DECRYPT_MODE}, {@code WRAP_MODE}
     * or {@code UNWRAP_MODE})
     * @param key the encryption key
     * @param params the algorithm parameters
     * @param random the source of randomness
     *
     * @throws InvalidKeyException if the given key is inappropriate for
     * initializing this cipher, or its keysize exceeds the maximum allowable
     * keysize (as determined from the configured jurisdiction policy files)
     * @throws InvalidAlgorithmParameterException if the given algorithm
     * parameters are inappropriate for this cipher,
     * or this cipher requires
     * algorithm parameters and {@code params} is {@code null}, or the given
     * algorithm parameters imply a cryptographic strength that would exceed
     * the legal limits (as determined from the configured jurisdiction
     * policy files)
     * @throws UnsupportedOperationException if {@code opmode} is
     * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
     * by the underlying {@code CipherSpi}
     * @throws InvalidParameterException if {@code opmode} is not one of the
     * recognized values
     */
    public final void init(int opmode, Key key, AlgorithmParameters params,
                           SecureRandom random)
            throws InvalidKeyException, InvalidAlgorithmParameterException
    {
        initialized = false;
        checkOpmode(opmode);

        if (spi != null) {
            checkCryptoPerm(spi, key, params);
            spi.engineInit(opmode, key, params, random);
        } else {
            chooseProvider(I_PARAMS, opmode, key, null, params, random);
        }

        initialized = true;
        this.opmode = opmode;

        if (!skipDebug && pdebug != null) {
            pdebug.println(this.toString());
        }
    }

    /**
     * Initializes this {@code Cipher} object with the public key from the given
     * certificate.
     * <p> The {@code Cipher} object is initialized for one of the following
     * four operations:
     * encryption, decryption, key wrapping or  key unwrapping, depending
     * on the value of {@code opmode}.
     *
     * <p>If the certificate is of type X.509 and has a <i>key usage</i>
     * extension field marked as critical, and the value of the <i>key usage</i>
     * extension field implies that the public key in
     * the certificate and its corresponding private key are not
     * supposed to be used for the operation represented by the value
     * of {@code opmode},
     * an {@code InvalidKeyException}
     * is thrown.
     *
     * <p> If this cipher requires any algorithm parameters that cannot be
     * derived from the public key in the given certificate, 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} if it is being initialized for decryption or
     * key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #getParameters() getParameters} or
     * {@link #getIV() getIV} (if the parameter is an IV).
     *
     * <p>If this cipher requires algorithm parameters that cannot be
     * derived from the input parameters, and there are no reasonable
     * provider-specific default values, initialization will
     * necessarily fail.
     *
     * <p>If this cipher (including its feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them using the
     * {@code SecureRandom}
     * implementation of the highest-priority
     * installed provider as the source of randomness.
     * (If none of the installed providers supply an implementation of
     * SecureRandom, a system-provided source of randomness will be used.)
     *
     * <p>Note that when a {@code Cipher} object is initialized, it loses all
     * previously-acquired state. In other words, initializing a {@code Cipher}
     * object is equivalent to creating a new instance of that {@code Cipher}
     * object and initializing it.
     *
     * @param opmode the operation mode of this {@code Cipher} object
     * (this is one of the following:
     * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},
     * {@code WRAP_MODE} or {@code UNWRAP_MODE})
     * @param certificate the certificate
     *
     * @throws InvalidKeyException if the public key in the given
     * certificate is inappropriate for initializing this cipher, or this
     * cipher requires algorithm parameters that cannot be determined from the
     * public key in the given certificate, or the keysize of the public key
     * in the given certificate has a keysize that exceeds the maximum
     * allowable keysize (as determined by the configured jurisdiction policy
     * files)
     * @throws UnsupportedOperationException if {@code opmode} is
     * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
     * by the underlying {@code CipherSpi}
     * @throws InvalidParameterException if {@code opmode} is not one of the
     * recognized values
     */
    public final void init(int opmode, Certificate certificate)
            throws InvalidKeyException
    {
        init(opmode, certificate, JCAUtil.getDefSecureRandom());
    }

    /**
     * Initializes this {@code Cipher} object with the public key from the given
     * certificate and a source of randomness.
     *
     * <p>The {@code Cipher} object is initialized for one of the following four
     * operations: encryption, decryption, key wrapping
     * or key unwrapping, depending on
     * the value of {@code opmode}.
     *
     * <p>If the certificate is of type X.509 and has a <i>key usage</i>
     * extension field marked as critical, and the value of the <i>key usage</i>
     * extension field implies that the public key in
     * the certificate and its corresponding private key are not
     * supposed to be used for the operation represented by the value of
     * {@code opmode},
     * an {@code InvalidKeyException}
     * is thrown.
     *
     * <p>If this cipher requires any algorithm parameters that cannot be
     * derived from the public key in the given {@code certificate},
     * 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} if it is being
     * initialized for decryption or key unwrapping.
     * The generated parameters can be retrieved using
     * {@link #getParameters() getParameters} or
     * {@link #getIV() getIV} (if the parameter is an IV).
     *
     * <p>If this cipher requires algorithm parameters that cannot be
     * derived from the input parameters, and there are no reasonable
     * provider-specific default values, initialization will
     * necessarily fail.
     *
     * <p>If this cipher (including its feedback or padding scheme)
     * requires any random bytes (e.g., for parameter generation), it will get
     * them from {@code random}.
     *
     * <p>Note that when a {@code Cipher} object is initialized, it loses all
     * previously-acquired state. In other words, initializing a {@code Cipher}
     * object is equivalent to creating a new instance of that {@code Cipher}
     * object and initializing it.
     *
     * @param opmode the operation mode of this {@code Cipher} object
     * (this is one of the following:
     * {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},
     * {@code WRAP_MODE} or {@code UNWRAP_MODE})
     * @param certificate the certificate
     * @param random the source of randomness
     *
     * @throws InvalidKeyException if the public key in the given
     * certificate is inappropriate for initializing this cipher, or this
     * cipher
     * requires algorithm parameters that cannot be determined from the
     * public key in the given certificate, or the keysize of the public key
     * in the given certificate has a keysize that exceeds the maximum
     * allowable keysize (as determined by the configured jurisdiction policy
     * files)
     * @throws UnsupportedOperationException if {@code opmode} is
     * {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented
     * by the underlying {@code CipherSpi}
     * @throws InvalidParameterException if {@code opmode} is not one of the
     * recognized values
     */
    public final void init(int opmode, Certificate certificate,
                           SecureRandom random)
            throws InvalidKeyException
    {
        initialized = false;
        checkOpmode(opmode);

        // Check key usage if the certificate is of type X.509.
        if (certificate instanceof java.security.cert.X509Certificate) {
            // Check whether the cert has a key usage extension
            // marked as a critical extension.
            X509Certificate cert = (X509Certificate)certificate;
            Set<String> critSet = cert.getCriticalExtensionOIDs();

            if (critSet != null && !critSet.isEmpty()
                && critSet.contains(KnownOIDs.KeyUsage.value())) {
                boolean[] keyUsageInfo = cert.getKeyUsage();
                // keyUsageInfo[2] is for keyEncipherment;
                // keyUsageInfo[3] is for dataEncipherment.
                if ((keyUsageInfo != null) &&
                    (((opmode == Cipher.ENCRYPT_MODE) &&
                      (keyUsageInfo.length > 3) &&
                      (keyUsageInfo[3] == false)) ||
                     ((opmode == Cipher.WRAP_MODE) &&
                      (keyUsageInfo.length > 2) &&
                      (keyUsageInfo[2] == false)))) {
                    throw new InvalidKeyException("Wrong key usage");
                }
            }
        }

        PublicKey publicKey =
            (certificate==null? null:certificate.getPublicKey());

        if (spi != null) {
            checkCryptoPerm(spi, publicKey);
            spi.engineInit(opmode, publicKey, random);
        } else {
            try {
                chooseProvider(I_CERT, opmode, publicKey, null, null, random);
            } catch (InvalidAlgorithmParameterException e) {
                // should never occur
                throw new InvalidKeyException(e);
            }
        }

        initialized = true;
        this.opmode = opmode;

        if (!skipDebug && pdebug != null) {
            pdebug.println(this.toString());
        }
    }

    /**
     * Ensures that {@code Cipher} object is in a valid state for update() and
     * doFinal() calls - should be initialized and in {@code ENCRYPT_MODE} or
     * {@code DECRYPT_MODE}.
     * @throws IllegalStateException if this {@code Cipher} object is not in
     * valid state
     */
    private void checkCipherState() {
        if (!(this instanceof NullCipher)) {
            if (!initialized) {
                throw new IllegalStateException("Cipher not initialized");
            }
            if ((opmode != Cipher.ENCRYPT_MODE) &&
                (opmode != Cipher.DECRYPT_MODE)) {
                throw new IllegalStateException("Cipher not initialized " +
                                                "for encryption/decryption");
            }
        }
    }

    /**
     * Continues a multiple-part encryption or decryption operation
     * (depending on how this {@code Cipher} object was initialized),
     * processing another data part.
     *
     * <p>The bytes in the {@code input} buffer are processed, and the
     * result is stored in a new buffer.
     *
     * <p>If {@code input} has a length of zero, this method returns
     * {@code null}.
     *
     * @param input the input buffer
     *
     * @return the new buffer with the result, or {@code null} if this
     * cipher is a block cipher and the input data is too short to result in a
     * new block
     *
     * @throws IllegalStateException if this {@code Cipher} object is in a
     * wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     */
    public final byte[] update(byte[] input) {
        checkCipherState();

        // Input sanity check
        if (input == null) {
            throw new IllegalArgumentException("Null input buffer");
        }

        chooseFirstProvider();
        if (input.length == 0) {
            return null;
        }
        return spi.engineUpdate(input, 0, input.length);
    }

    /**
     * Continues a multiple-part encryption or decryption operation
     * (depending on how this {@code Cipher} object was initialized),
     * processing another data part.
     *
     * <p>The first {@code inputLen} bytes in the {@code input}
     * buffer, starting at {@code inputOffset} inclusive, are processed,
     * and the result is stored in a new buffer.
     *
     * <p>If {@code inputLen} is zero, this method returns
     * {@code null}.
     *
     * @param input the input buffer
     * @param inputOffset the offset in {@code input} where the input
     * starts
     * @param inputLen the input length
     *
     * @return the new buffer with the result, or {@code null} if this
     * cipher is a block cipher and the input data is too short to result in a
     * new block.
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     */
    public final byte[] update(byte[] input, int inputOffset, int inputLen) {
        checkCipherState();

        // Input sanity check
        if (input == null || inputOffset < 0
            || inputLen > (input.length - inputOffset) || inputLen < 0) {
            throw new IllegalArgumentException("Bad arguments");
        }

        chooseFirstProvider();
        if (inputLen == 0) {
            return null;
        }
        return spi.engineUpdate(input, inputOffset, inputLen);
    }

    /**
     * Continues a multiple-part encryption or decryption operation
     * (depending on how this {@code Cipher} object was initialized),
     * processing another data part.
     *
     * <p>The first {@code inputLen} bytes in the {@code input}
     * buffer, starting at {@code inputOffset} inclusive, are processed,
     * and the result is stored in the {@code output} buffer.
     *
     * <p>If the {@code output} buffer is too small to hold the result,
     * a {@code ShortBufferException} is thrown. In this case, repeat this
     * call with a larger output buffer. Use
     * {@link #getOutputSize(int) getOutputSize} to determine how big
     * the output buffer should be.
     *
     * <p>If {@code inputLen} is zero, this method returns
     * a length of zero.
     *
     * <p>Note: this method should be copy-safe, which means the
     * {@code input} and {@code output} buffers can reference
     * the same byte array and no unprocessed input data is overwritten
     * when the result is copied into the output buffer.
     *
     * @param input the input buffer
     * @param inputOffset the offset in {@code input} where the input
     * starts
     * @param inputLen the input length
     * @param output the buffer for the result
     *
     * @return the number of bytes stored in {@code output}
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws ShortBufferException if the given output buffer is too small
     * to hold the result
     */
    public final int update(byte[] input, int inputOffset, int inputLen,
                            byte[] output)
            throws ShortBufferException {
        checkCipherState();

        // Input sanity check
        if (input == null || inputOffset < 0
            || inputLen > (input.length - inputOffset) || inputLen < 0) {
            throw new IllegalArgumentException("Bad arguments");
        }

        chooseFirstProvider();
        if (inputLen == 0) {
            return 0;
        }
        return spi.engineUpdate(input, inputOffset, inputLen,
                                      output, 0);
    }

    /**
     * Continues a multiple-part encryption or decryption operation
     * (depending on how this {@code Cipher} object was initialized),
     * processing another data part.
     *
     * <p>The first {@code inputLen} bytes in the {@code input}
     * buffer, starting at {@code inputOffset} inclusive, are processed,
     * and the result is stored in the {@code output} buffer, starting at
     * {@code outputOffset} inclusive.
     *
     * <p>If the {@code output} buffer is too small to hold the result,
     * a {@code ShortBufferException} is thrown. In this case, repeat this
     * call with a larger output buffer. Use
     * {@link #getOutputSize(int) getOutputSize} to determine how big
     * the output buffer should be.
     *
     * <p>If {@code inputLen} is zero, this method returns
     * a length of zero.
     *
     * <p>Note: this method should be copy-safe, which means the
     * {@code input} and {@code output} buffers can reference
     * the same byte array and no unprocessed input data is overwritten
     * when the result is copied into the output buffer.
     *
     * @param input the input buffer
     * @param inputOffset the offset in {@code input} where the input
     * starts
     * @param inputLen the input length
     * @param output the buffer for the result
     * @param outputOffset the offset in {@code output} where the result
     * is stored
     *
     * @return the number of bytes stored in {@code output}
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws ShortBufferException if the given output buffer is too small
     * to hold the result
     */
    public final int update(byte[] input, int inputOffset, int inputLen,
                            byte[] output, int outputOffset)
            throws ShortBufferException {
        checkCipherState();

        // Input sanity check
        if (input == null || inputOffset < 0
            || inputLen > (input.length - inputOffset) || inputLen < 0
            || outputOffset < 0) {
            throw new IllegalArgumentException("Bad arguments");
        }

        chooseFirstProvider();
        if (inputLen == 0) {
            return 0;
        }
        return spi.engineUpdate(input, inputOffset, inputLen,
                                      output, outputOffset);
    }

    /**
     * Continues a multiple-part encryption or decryption operation
     * (depending on how this {@code Cipher} object was initialized),
     * processing another data part.
     *
     * <p>All {@code input.remaining()} bytes starting at
     * {@code input.position()} 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()} bytes are insufficient to
     * hold the result, a {@code ShortBufferException} is thrown.
     * In this case, repeat this call with a larger output buffer. Use
     * {@link #getOutputSize(int) getOutputSize} to determine how big
     * the output buffer should be.
     *
     * <p>Note: this method should be copy-safe, which means the
     * {@code input} and {@code output} buffers can reference
     * the same block of memory and no unprocessed input data is overwritten
     * when the result is copied into the output buffer.
     *
     * @param input the input ByteBuffer
     * @param output the output ByteByffer
     *
     * @return the number of bytes stored in {@code output}
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws IllegalArgumentException if input and output are the
     *   same object
     * @throws ReadOnlyBufferException if the output buffer is read-only
     * @throws ShortBufferException if there is insufficient space in the
     * output buffer
     * @since 1.5
     */
    public final int update(ByteBuffer input, ByteBuffer output)
            throws ShortBufferException {
        checkCipherState();

        if ((input == null) || (output == null)) {
            throw new IllegalArgumentException("Buffers must not be null");
        }
        if (input == output) {
            throw new IllegalArgumentException("Input and output buffers must "
                + "not be the same object, consider using buffer.duplicate()");
        }
        if (output.isReadOnly()) {
            throw new ReadOnlyBufferException();
        }

        chooseFirstProvider();
        return spi.engineUpdate(input, output);
    }

    /**
     * Finishes a multiple-part encryption or decryption operation, depending
     * on how this {@code Cipher} object was initialized.
     *
     * <p>Input data that may have been buffered during a previous
     * {@code update} operation is processed, with padding (if requested)
     * being applied.
     * If an AEAD mode such as GCM/CCM is being used, the authentication
     * tag is appended in the case of encryption, or verified in the
     * case of decryption.
     * The result is stored in a new buffer.
     *
     * <p>Upon finishing, this method resets this {@code Cipher} object
     * to the state it was in when previously initialized via a call to
     * {@code init}.
     * 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 init}) more data.
     *
     * <p>Note: if any exception is thrown, this {@code Cipher} object
     * may need to be reset before it can be used again.
     *
     * @return the new buffer with the result
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws 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.
     * @throws BadPaddingException if this {@code Cipher} object is in
     * decryption mode, and (un)padding has been requested, but the decrypted
     * data is not bounded by the appropriate padding bytes
     * @throws AEADBadTagException if this {@code Cipher} object is decrypting
     * in an AEAD mode (such as GCM/CCM), and the received authentication tag
     * does not match the calculated value
     */
    public final byte[] doFinal()
            throws IllegalBlockSizeException, BadPaddingException {
        checkCipherState();

        chooseFirstProvider();
        return spi.engineDoFinal(null, 0, 0);
    }

    /**
     * Finishes a multiple-part encryption or decryption operation, depending
     * on how this {@code Cipher} object was initialized.
     *
     * <p>Input data that may have been buffered during a previous
     * {@code update} operation is processed, with padding (if requested)
     * being applied.
     * If an AEAD mode such as GCM/CCM is being used, the authentication
     * tag is appended in the case of encryption, or verified in the
     * case of decryption.
     * The result is stored in the {@code output} buffer, starting at
     * {@code outputOffset} inclusive.
     *
     * <p>If the {@code output} buffer is too small to hold the result,
     * a {@code ShortBufferException} is thrown. In this case, repeat this
     * call with a larger output buffer. Use
     * {@link #getOutputSize(int) getOutputSize} to determine how big
     * the output buffer should be.
     *
     * <p>Upon finishing, this method resets this {@code Cipher} object
     *  to the state it was in when previously initialized via a call to
     * {@code init}.
     * 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 init}) more data.
     *
     * <p>Note: if any exception is thrown, this {@code Cipher} object
     * may need to be reset before it can be used again.
     *
     * @param output the buffer for the result
     * @param outputOffset the offset in {@code output} where the result
     * is stored
     *
     * @return the number of bytes stored in {@code output}
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws 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.
     * @throws ShortBufferException if the given output buffer is too small
     * to hold the result
     * @throws BadPaddingException if this {@code Cipher} object is in
     * decryption mode, and (un)padding has been requested, but the
     * decrypted data is not bounded by the appropriate padding bytes
     * @throws AEADBadTagException if this {@code Cipher} object is decrypting
     * in an AEAD mode (such as GCM/CCM), and the received authentication tag
     * does not match the calculated value
     */
    public final int doFinal(byte[] output, int outputOffset)
            throws IllegalBlockSizeException, ShortBufferException,
               BadPaddingException {
        checkCipherState();

        // Input sanity check
        if ((output == null) || (outputOffset < 0)) {
            throw new IllegalArgumentException("Bad arguments");
        }

        chooseFirstProvider();
        return spi.engineDoFinal(null, 0, 0, output, outputOffset);
    }

    /**
     * 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 {@code Cipher} object was initialized.
     *
     * <p>The bytes in the {@code input} buffer, and any input bytes that
     * may have been buffered during a previous {@code update} operation,
     * are processed, with padding (if requested) being applied.
     * If an AEAD mode such as GCM/CCM is being used, the authentication
     * tag is appended in the case of encryption, or verified in the
     * case of decryption.
     * The result is stored in a new buffer.
     *
     * <p>Upon finishing, this method resets this {@code Cipher} object
     * to the state it was in when previously initialized via a call to
     * {@code init}.
     * 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 init}) more data.
     *
     * <p>Note: if any exception is thrown, this {@code Cipher} object
     * may need to be reset before it can be used again.
     *
     * @param input the input buffer
     *
     * @return the new buffer with the result
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws 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.
     * @throws BadPaddingException if this {@code Cipher} object is in
     * decryption mode, and (un)padding has been requested, but the
     * decrypted data is not bounded by the appropriate padding bytes
     * @throws AEADBadTagException if this {@code Cipher} object is decrypting
     * in an AEAD mode (such as GCM/CCM), and the received authentication tag
     * does not match the calculated value
     */
    public final byte[] doFinal(byte[] input)
            throws IllegalBlockSizeException, BadPaddingException {
        checkCipherState();

        // Input sanity check
        if (input == null) {
            throw new IllegalArgumentException("Null input buffer");
        }

        chooseFirstProvider();
        return spi.engineDoFinal(input, 0, input.length);
    }

    /**
     * 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 {@code Cipher} object was initialized.
     *
     * <p>The first {@code inputLen} bytes in the {@code input}
     * buffer, starting at {@code inputOffset} inclusive, and any input
     * bytes that may have been buffered during a previous {@code update}
     * operation, are processed, with padding (if requested) being applied.
     * If an AEAD mode such as GCM/CCM is being used, the authentication
     * tag is appended in the case of encryption, or verified in the
     * case of decryption.
     * The result is stored in a new buffer.
     *
     * <p>Upon finishing, this method resets this {@code Cipher} object
     * to the state it was in when previously initialized via a call to
     * {@code init}.
     * 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 init}) more data.
     *
     * <p>Note: if any exception is thrown, this {@code 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} where the input
     * starts
     * @param inputLen the input length
     *
     * @return the new buffer with the result
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws 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.
     * @throws BadPaddingException if this {@code Cipher} object is in
     * decryption mode, and (un)padding has been requested, but the decrypted
     * data is not bounded by the appropriate padding bytes
     * @throws AEADBadTagException if this {@code Cipher} object is decrypting
     * in an AEAD mode (such as GCM/CCM), and the received authentication tag
     * does not match the calculated value
     */
    public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
            throws IllegalBlockSizeException, BadPaddingException {
        checkCipherState();

        // Input sanity check
        if (input == null || inputOffset < 0
            || inputLen > (input.length - inputOffset) || inputLen < 0) {
            throw new IllegalArgumentException("Bad arguments");
        }

        chooseFirstProvider();
        return spi.engineDoFinal(input, inputOffset, inputLen);
    }

    /**
     * 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 {@code Cipher} object was initialized.
     *
     * <p>The first {@code inputLen} bytes in the {@code input}
     * buffer, starting at {@code inputOffset} inclusive, and any input
     * bytes that may have been buffered during a previous {@code update}
     * operation, are processed, with padding (if requested) being applied.
     * If an AEAD mode such as GCM/CCM is being used, the authentication
     * tag is appended in the case of encryption, or verified in the
     * case of decryption.
     * The result is stored in the {@code output} buffer.
     *
     * <p>If the {@code output} buffer is too small to hold the result,
     * a {@code ShortBufferException} is thrown. In this case, repeat this
     * call with a larger output buffer. Use
     * {@link #getOutputSize(int) getOutputSize} to determine how big
     * the output buffer should be.
     *
     * <p>Upon finishing, this method resets this {@code Cipher} object
     * to the state it was in when previously initialized via a call to
     * {@code init}.
     * 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 init}) more data.
     *
     * <p>Note: if any exception is thrown, this {@code Cipher} object
     * may need to be reset before it can be used again.
     *
     * <p>Note: this method should be copy-safe, which means the
     * {@code input} and {@code output} buffers can reference
     * the same byte array and no unprocessed input data is overwritten
     * when the result is copied into the output buffer.
     *
     * @param input the input buffer
     * @param inputOffset the offset in {@code input} where the input
     * starts
     * @param inputLen the input length
     * @param output the buffer for the result
     *
     * @return the number of bytes stored in {@code output}
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in  or {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws 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.
     * @throws ShortBufferException if the given output buffer is too small
     * to hold the result
     * @throws BadPaddingException if this {@code Cipher} object is in
     * decryption mode, and (un)padding has been requested, but the decrypted
     * data is not bounded by the appropriate padding bytes
     * @throws AEADBadTagException if this {@code Cipher} object is decrypting
     * in an AEAD mode (such as GCM/CCM), and the received authentication tag
     * does not match the calculated value
     */
    public final int doFinal(byte[] input, int inputOffset, int inputLen,
                             byte[] output)
            throws ShortBufferException, IllegalBlockSizeException,
            BadPaddingException {
        checkCipherState();

        // Input sanity check
        if (input == null || inputOffset < 0
            || inputLen > (input.length - inputOffset) || inputLen < 0) {
            throw new IllegalArgumentException("Bad arguments");
        }

        chooseFirstProvider();
        return spi.engineDoFinal(input, inputOffset, inputLen,
                                       output, 0);
    }

    /**
     * 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 {@code Cipher} object was initialized.
     *
     * <p>The first {@code inputLen} bytes in the {@code input}
     * buffer, starting at {@code inputOffset} inclusive, and any input
     * bytes that may have been buffered during a previous
     * {@code update} operation, are processed, with padding
     * (if requested) being applied.
     * If an AEAD mode such as GCM/CCM is being used, the authentication
     * tag is appended in the case of encryption, or verified in the
     * case of decryption.
     * The result is stored in the {@code output} buffer, starting at
     * {@code outputOffset} inclusive.
     *
     * <p>If the {@code output} buffer is too small to hold the result,
     * a {@code ShortBufferException} is thrown. In this case, repeat this
     * call with a larger output buffer. Use
     * {@link #getOutputSize(int) getOutputSize} to determine how big
     * the output buffer should be.
     *
     * <p>Upon finishing, this method resets this {@code Cipher} object
     * to the state it was in when previously initialized via a call to
     * {@code init}.
     * 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 init}) more data.
     *
     * <p>Note: if any exception is thrown, this {@code Cipher} object
     * may need to be reset before it can be used again.
     *
     * <p>Note: this method should be copy-safe, which means the
     * {@code input} and {@code output} buffers can reference
     * the same byte array and no unprocessed input data is overwritten
     * when the result is copied into the output buffer.
     *
     * @param input the input buffer
     * @param inputOffset the offset in {@code input} where the input
     * starts
     * @param inputLen the input length
     * @param output the buffer for the result
     * @param outputOffset the offset in {@code output} where the result
     * is stored
     *
     * @return the number of bytes stored in {@code output}
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws 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.
     * @throws ShortBufferException if the given output buffer is too small
     * to hold the result
     * @throws BadPaddingException if this {@code Cipher} object is in
     * decryption mode, and (un)padding has been requested, but the decrypted
     * data is not bounded by the appropriate padding bytes
     * @throws AEADBadTagException if this {@code Cipher} object is decrypting
     * in an AEAD mode (such as GCM/CCM), and the received authentication tag
     * does not match the calculated value
     */
    public final int doFinal(byte[] input, int inputOffset, int inputLen,
                             byte[] output, int outputOffset)
            throws ShortBufferException, IllegalBlockSizeException,
            BadPaddingException {
        checkCipherState();

        // Input sanity check
        if (input == null || inputOffset < 0
            || inputLen > (input.length - inputOffset) || inputLen < 0
            || outputOffset < 0) {
            throw new IllegalArgumentException("Bad arguments");
        }

        chooseFirstProvider();
        return spi.engineDoFinal(input, inputOffset, inputLen,
                                       output, outputOffset);
    }

    /**
     * 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 {@code Cipher} object was initialized.
     *
     * <p>All {@code input.remaining()} bytes starting at
     * {@code input.position()} are processed.
     * If an AEAD mode such as GCM/CCM is being used, the authentication
     * tag is appended in the case of encryption, or verified in the
     * case of decryption.
     * 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()} bytes are insufficient to
     * hold the result, a {@code ShortBufferException} is thrown.
     * In this case, repeat this call with a larger output buffer. Use
     * {@link #getOutputSize(int) getOutputSize} to determine how big
     * the output buffer should be.
     *
     * <p>Upon finishing, this method resets this {@code Cipher} object
     * to the state it was in when previously initialized via a call to
     * {@code init}.
     * 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 init}) more data.
     *
     * <p>Note: if any exception is thrown, this {@code Cipher} object
     * may need to be reset before it can be used again.
     *
     * <p>Note: this method should be copy-safe, which means the
     * {@code input} and {@code output} buffers can reference
     * the same byte array and no unprocessed input data is overwritten
     * when the result is copied into the output buffer.
     *
     * @param input the input ByteBuffer
     * @param output the output ByteBuffer
     *
     * @return the number of bytes stored in {@code output}
     *
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not
     * in {@code ENCRYPT_MODE} or {@code DECRYPT_MODE})
     * @throws IllegalArgumentException if input and output are the
     *   same object
     * @throws ReadOnlyBufferException if the output buffer is read-only
     * @throws 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.
     * @throws ShortBufferException if there is insufficient space in the
     * output buffer
     * @throws BadPaddingException if this {@code Cipher} object is in
     * decryption mode, and (un)padding has been requested, but the
     * decrypted data is not bounded by the appropriate padding bytes
     * @throws AEADBadTagException if this {@code Cipher} object is decrypting
     * in an AEAD mode (such as GCM/CCM), and the received authentication tag
     * does not match the calculated value
     *
     * @since 1.5
     */
    public final int doFinal(ByteBuffer input, ByteBuffer output)
            throws ShortBufferException, IllegalBlockSizeException,
            BadPaddingException {
        checkCipherState();

        if ((input == null) || (output == null)) {
            throw new IllegalArgumentException("Buffers must not be null");
        }
        if (input == output) {
            throw new IllegalArgumentException("Input and output buffers must "
                + "not be the same object, consider using buffer.duplicate()");
        }
        if (output.isReadOnly()) {
            throw new ReadOnlyBufferException();
        }

        chooseFirstProvider();
        return spi.engineDoFinal(input, output);
    }

    /**
     * Wrap a key.
     *
     * @param key the key to be wrapped
     *
     * @return the wrapped key
     *
     * @throws IllegalStateException if this {@code Cipher} object is in a wrong
     * state (e.g., has not been initialized, or is not in {@code WRAP_MODE})
     *
     * @throws 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
     *
     * @throws 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)
     *
     * @throws UnsupportedOperationException if the corresponding method in the
     * {@code CipherSpi} is not supported
     */
    public final byte[] wrap(Key key)
            throws IllegalBlockSizeException, InvalidKeyException {
        if (!(this instanceof NullCipher)) {
            if (!initialized) {
                throw new IllegalStateException("Cipher not initialized");
            }
            if (opmode != Cipher.WRAP_MODE) {
                throw new IllegalStateException("Cipher not initialized " +
                                                "for wrapping keys");
            }
        }

        chooseFirstProvider();
        return spi.engineWrap(key);
    }

    /**
     * Unwrap a previously wrapped key.
     *
     * @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 must be one of
     * {@code SECRET_KEY}, {@code PRIVATE_KEY}, or
     * {@code PUBLIC_KEY}
     *
     * @return the unwrapped key
     *
     * @throws IllegalStateException if this {@code Cipher} object is in a wrong
     * state (e.g., has not been initialized, or is not in {@code UNWRAP_MODE})
     *
     * @throws NoSuchAlgorithmException if no installed providers
     * can create keys of type {@code wrappedKeyType} for the
     * {@code wrappedKeyAlgorithm}
     *
     * @throws InvalidKeyException if {@code wrappedKey} does not
     * represent a wrapped key of type {@code wrappedKeyType} for
     * the {@code wrappedKeyAlgorithm}
     *
     * @throws UnsupportedOperationException if the corresponding method in the
     * {@code CipherSpi} is not supported
     */
    public final Key unwrap(byte[] wrappedKey,
                            String wrappedKeyAlgorithm,
                            int wrappedKeyType)
            throws InvalidKeyException, NoSuchAlgorithmException {

        if (!(this instanceof NullCipher)) {
            if (!initialized) {
                throw new IllegalStateException("Cipher not initialized");
            }
            if (opmode != Cipher.UNWRAP_MODE) {
                throw new IllegalStateException("Cipher not initialized " +
                                                "for unwrapping keys");
            }
        }
        if ((wrappedKeyType != SECRET_KEY) &&
            (wrappedKeyType != PRIVATE_KEY) &&
            (wrappedKeyType != PUBLIC_KEY)) {
            throw new InvalidParameterException("Invalid key type");
        }

        chooseFirstProvider();
        return spi.engineUnwrap(wrappedKey,
                                      wrappedKeyAlgorithm,
                                      wrappedKeyType);
    }

    private AlgorithmParameterSpec getAlgorithmParameterSpec(
                                      AlgorithmParameters params)
            throws InvalidParameterSpecException {
        if (params == null) {
            return null;
        }

        String alg = params.getAlgorithm().toUpperCase(Locale.ENGLISH);

        if (alg.equalsIgnoreCase("RC2")) {
            return params.getParameterSpec(RC2ParameterSpec.class);
        }

        if (alg.equalsIgnoreCase("RC5")) {
            return params.getParameterSpec(RC5ParameterSpec.class);
        }

        if (alg.startsWith("PBE")) {
            return params.getParameterSpec(PBEParameterSpec.class);
        }

        if (alg.startsWith("DES")) {
            return params.getParameterSpec(IvParameterSpec.class);
        }
        return null;
    }

    private static CryptoPermission getConfiguredPermission(
            String transformation) throws NullPointerException,
            NoSuchAlgorithmException {
        if (transformation == null) throw new NullPointerException();
        String[] parts = tokenizeTransformation(transformation);
        return JceSecurityManager.INSTANCE.getCryptoPermission(parts[0]);
    }

    /**
     * Returns the maximum key length for the specified transformation
     * according to the installed JCE jurisdiction policy files. If
     * JCE unlimited strength jurisdiction policy files are installed,
     * {@code Integer.MAX_VALUE} will be returned.
     * For more information on the default key sizes and the JCE jurisdiction
     * policy files, please see the Cryptographic defaults and limitations in
     * the {@extLink security_guide_jdk_providers JDK Providers Documentation}.
     *
     * @param transformation the cipher transformation
     * @return the maximum key length in bits or {@code Integer.MAX_VALUE}
     * @throws NullPointerException if {@code transformation} is {@code null}
     * @throws NoSuchAlgorithmException if {@code transformation}
     * is not a valid transformation, i.e. in the form of "algorithm" or
     * "algorithm/mode/padding"
     * @since 1.5
     */
    public static final int getMaxAllowedKeyLength(String transformation)
            throws NoSuchAlgorithmException {
        CryptoPermission cp = getConfiguredPermission(transformation);
        return cp.getMaxKeySize();
    }

    /**
     * Returns an {code AlgorithmParameterSpec} object which contains
     * the maximum {@code Cipher} parameter value according to the
     * jurisdiction policy file. If JCE unlimited strength jurisdiction
     * policy files are installed or there is no maximum limit on the
     * parameters for the specified transformation in the policy file,
     * {@code null} will be returned.
     *
     * @param transformation the cipher transformation
     * @return an {code AlgorithmParameterSpec} object which holds the maximum
     * value or {@code null}
     * @throws NullPointerException if {@code transformation}
     * is {@code null}
     * @throws NoSuchAlgorithmException if {@code transformation}
     * is not a valid transformation, i.e. in the form of "algorithm" or
     * "algorithm/mode/padding"
     * @since 1.5
     */
    public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
            String transformation) throws NoSuchAlgorithmException {
        CryptoPermission cp = getConfiguredPermission(transformation);
        return cp.getAlgorithmParameterSpec();
    }

    /**
     * Continues a multi-part update of the Additional Authentication
     * Data (AAD).
     * <p>
     * Calls to this method provide AAD to the {@code Cipher} object
     * when operating in modes such as AEAD (GCM/CCM).  If this
     * {@code Cipher} object is operating in either GCM or CCM mode, all AAD
     * must be supplied before beginning operations on the ciphertext
     * (via the {@code update} and {@code doFinal} methods).
     *
     * @param src the buffer containing the Additional Authentication Data
     *
     * @throws IllegalArgumentException if the {@code src}
     * byte array is {@code null}
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not in
     * {@code ENCRYPT_MODE} or {@code DECRYPT_MODE}), does not accept AAD,
     * or if operating in either GCM or CCM mode and one of the {@code update}
     * methods has already been called for the active encryption/decryption
     * operation
     * @throws UnsupportedOperationException if the corresponding method
     * in the {@code CipherSpi} has not been overridden by an
     * implementation
     *
     * @since 1.7
     */
    public final void updateAAD(byte[] src) {
        if (src == null) {
            throw new IllegalArgumentException("src buffer is null");
        }

        updateAAD(src, 0, src.length);
    }

    /**
     * Continues a multi-part update of the Additional Authentication
     * Data (AAD), using a subset of the provided buffer.
     * <p>
     * Calls to this method provide AAD to the {@code Cipher} object
     * when operating in modes such as AEAD (GCM/CCM).  If this
     * {@code Cipher} object is operating in either GCM or CCM mode,
     * all AAD must be supplied before beginning operations on the
     * ciphertext (via the {@code update} and {@code doFinal} methods).
     *
     * @param src the buffer containing the AAD
     * @param offset the offset in {@code src} where the AAD input starts
     * @param len the number of AAD bytes
     *
     * @throws IllegalArgumentException if the {@code src}
     * byte array is {@code null}, or the {@code offset} or {@code length}
     * is less than 0, or the sum of the {@code offset} and
     * {@code len} is greater than the length of the
     * {@code src} byte array
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not in
     * {@code ENCRYPT_MODE} or {@code DECRYPT_MODE}), does not accept AAD,
     * or if operating in either GCM or CCM mode and one of the {@code update}
     * methods has already been called for the active encryption/decryption
     * operation
     * @throws UnsupportedOperationException if the corresponding method
     * in the {@code CipherSpi} has not been overridden by an
     * implementation
     *
     * @since 1.7
     */
    public final void updateAAD(byte[] src, int offset, int len) {
        checkCipherState();

        // Input sanity check
        if ((src == null) || (offset < 0) || (len < 0)
                || len > (src.length - offset)) {
            throw new IllegalArgumentException("Bad arguments");
        }

        chooseFirstProvider();
        if (len == 0) {
            return;
        }
        spi.engineUpdateAAD(src, offset, len);
    }

    /**
     * Continues a multi-part update of the Additional Authentication
     * Data (AAD).
     * <p>
     * Calls to this method provide AAD to the {@code Cipher} object
     * when operating in modes such as AEAD (GCM/CCM).  If this
     * {@code Cipher} object is operating in either GCM or CCM mode, all AAD
     * must be supplied before beginning operations on the ciphertext
     * (via the {@code update} and {@code doFinal} methods).
     * <p>
     * All {@code src.remaining()} bytes starting at
     * {@code src.position()} are processed.
     * Upon return, the input buffer's position will be equal
     * to its limit; its limit will not have changed.
     *
     * @param src the buffer containing the AAD
     *
     * @throws IllegalArgumentException if the {@code src ByteBuffer}
     * is {@code null}
     * @throws IllegalStateException if this {@code Cipher} object
     * is in a wrong state (e.g., has not been initialized, or is not in
     * {@code ENCRYPT_MODE} or {@code DECRYPT_MODE}), does not accept AAD,
     * or if operating in either GCM or CCM mode and one of the {@code update}
     * methods has already been called for the active encryption/decryption
     * operation
     * @throws UnsupportedOperationException if the corresponding method
     * in the {@code CipherSpi} has not been overridden by an
     * implementation
     *
     * @since 1.7
     */
    public final void updateAAD(ByteBuffer src) {
        checkCipherState();

        // Input sanity check
        if (src == null) {
            throw new IllegalArgumentException("src ByteBuffer is null");
        }

        chooseFirstProvider();
        if (src.remaining() == 0) {
            return;
        }
        spi.engineUpdateAAD(src);
    }

    /**
     * Returns a {@code String} representation of this {@code Cipher} object.
     *
     * @implNote
     * This implementation returns a {@code String} containing the
     * transformation, mode, and provider of this {@code Cipher} object.
     * The exact format of the {@code String} is unspecified and is subject
     * to change.
     *
     * @return a String describing this {@code Cipher} object
     */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("Cipher.")
                .append(transformation)
                .append(", mode: ");
        switch (opmode) {
            case 0:
                sb.append("not initialized");
                break;
            case ENCRYPT_MODE:
                sb.append("encryption");
                break;
            case DECRYPT_MODE:
                sb.append("decryption");
                break;
            case WRAP_MODE:
                sb.append("key wrapping");
                break;
            case UNWRAP_MODE:
                sb.append("key unwrapping");
                break;
            default:
                // should never happen
                sb.append("error:").append(opmode);
        }
        sb.append(", algorithm from: ").append(getProviderName());
        return sb.toString();
    }
}
