/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.keystore.cts;

import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
import android.test.AndroidTestCase;

import junit.framework.AssertionFailedError;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Locale;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;

abstract class BlockCipherTestBase extends AndroidTestCase {

    private KeyStore mAndroidKeyStore;
    private int mNextKeyId;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mAndroidKeyStore = KeyStore.getInstance("AndroidKeyStore");
        mAndroidKeyStore.load(null);
        for (Enumeration<String> e = mAndroidKeyStore.aliases(); e.hasMoreElements();) {
            mAndroidKeyStore.deleteEntry(e.nextElement());
        }
    }

    @Override
    protected void tearDown() throws Exception {
        try {
            for (Enumeration<String> e = mAndroidKeyStore.aliases(); e.hasMoreElements();) {
                mAndroidKeyStore.deleteEntry(e.nextElement());
            }
        } finally {
            super.tearDown();
        }
    }

    protected abstract String getTransformation();
    protected abstract int getBlockSize();

    protected abstract byte[] getKatKey();
    protected abstract byte[] getKatIv();
    protected abstract AlgorithmParameterSpec getKatAlgorithmParameterSpec();
    protected abstract byte[] getKatPlaintext();
    protected abstract byte[] getKatCiphertext();
    protected abstract int getKatAuthenticationTagLengthBytes();
    protected abstract boolean isStreamCipher();
    protected abstract boolean isAuthenticatedCipher();

    protected abstract byte[] getIv(AlgorithmParameters params)
            throws InvalidParameterSpecException;

    private byte[] getKatInput(int opmode) {
        switch (opmode) {
            case Cipher.ENCRYPT_MODE:
                return getKatPlaintext();
            case Cipher.DECRYPT_MODE:
                return getKatCiphertext();
            default:
                throw new IllegalArgumentException("Invalid opmode: " + opmode);
        }
    }

    private byte[] getKatOutput(int opmode) {
        switch (opmode) {
            case Cipher.ENCRYPT_MODE:
                return getKatCiphertext();
            case Cipher.DECRYPT_MODE:
                return getKatPlaintext();
            default:
                throw new IllegalArgumentException("Invalid opmode: " + opmode);
        }
    }

    private Cipher mCipher;
    private int mOpmode;

    public void testGetAlgorithm() throws Exception {
        createCipher();
        assertEquals(getTransformation(), mCipher.getAlgorithm());
    }

    public void testGetProvider() throws Exception {
        createCipher();
        Provider expectedProvider = Security.getProvider("AndroidKeyStoreBCWorkaround");
        assertSame(expectedProvider, mCipher.getProvider());
    }

    public void testGetBlockSize() throws Exception {
        createCipher();
        assertEquals(getBlockSize(), mCipher.getBlockSize());
    }

    public void testGetExemptionMechanism() throws Exception {
        createCipher();
        assertNull(mCipher.getExemptionMechanism());
    }

    public void testGetParameters() throws Exception {
        createCipher();
        assertAlgoritmParametersIv(null);

        initKat(Cipher.ENCRYPT_MODE);
        assertAlgoritmParametersIv(getKatIv());
        doFinal(getKatPlaintext());
        assertAlgoritmParametersIv(getKatIv());

        initKat(Cipher.DECRYPT_MODE);
        assertAlgoritmParametersIv(getKatIv());
        doFinal(getKatCiphertext());
        assertAlgoritmParametersIv(getKatIv());
    }

    private void assertAlgoritmParametersIv(byte[] expectedIv)
            throws InvalidParameterSpecException {
        AlgorithmParameters actualParameters = mCipher.getParameters();
        if (expectedIv == null) {
            assertNull(actualParameters);
        } else {
            byte[] actualIv = getIv(actualParameters);
            assertEquals(expectedIv, actualIv);
        }
    }

    public void testGetOutputSizeInEncryptionMode() throws Exception {
        int blockSize = getBlockSize();
        createCipher();
        try {
            mCipher.getOutputSize(blockSize);
            fail();
        } catch (IllegalStateException expected) {}

        initKat(Cipher.ENCRYPT_MODE);
        if (isAuthenticatedCipher()) {
            // Authenticated ciphers do not return any output when decrypting until doFinal where
            // ciphertext is authenticated.
            for (int input = 0; input <= blockSize * 2; input++) {
                int actualOutputSize = mCipher.getOutputSize(input);
                int expectedOutputSize = input + getKatAuthenticationTagLengthBytes();
                if (actualOutputSize < expectedOutputSize) {
                    fail("getOutputSize(" + expectedOutputSize + ") underestimated output size"
                            + ". min expected: <" + expectedOutputSize
                            + ">, actual: <" + actualOutputSize + ">");
                }
            }
            return;
        } else if (isStreamCipher()) {
            // Unauthenticated stream ciphers do not buffer input or output.
            for (int input = 0; input <= blockSize * 2; input++) {
                int actualOutputSize = mCipher.getOutputSize(input);
                if (actualOutputSize < input) {
                    fail("getOutputSize(" + input + ") underestimated output size. min expected: <"
                            + input + ">, actual: <" + actualOutputSize + ">");
                }
            }
            return;
        }
        // Not a stream cipher -- input may be buffered.

        for (int buffered = 0; buffered < blockSize; buffered++) {
            // Assert that the output of getOutputSize is not lower than the minimum expected.
            for (int input = 0; input <= blockSize * 2; input++) {
                int inputInclBuffered = buffered + input;
                // doFinal dominates the output size.
                // One full plaintext block results in one ciphertext block.
                int minExpectedOutputSize = inputInclBuffered - (inputInclBuffered % blockSize);
                if (isPaddingEnabled()) {
                    // Regardless of whether there is a partial input block, an additional block of
                    // ciphertext should be output.
                    minExpectedOutputSize += blockSize;
                } else {
                    // When no padding is enabled, any remaining partial block of plaintext will
                    // cause an error. Thus, there's no need to account for its ciphertext.
                }
                int actualOutputSize = mCipher.getOutputSize(input);
                System.out.println("*** buffered: " + buffered + ", input: " + input + ", min: " + minExpectedOutputSize + ", actual: " + actualOutputSize);
                if (actualOutputSize < minExpectedOutputSize) {
                    fail("getOutputSize(" + input + ") underestimated output size when buffered == "
                            + buffered + ". min expected: <"
                            + minExpectedOutputSize + ">, actual: <" + actualOutputSize + ">");
                }
            }

            if (buffered == blockSize - 1) {
                break;
            }
            // Buffer one more byte of input.
            assertNull("buffered: " + buffered, update(new byte[1]));
        }
    }

    public void testGetOutputSizeInDecryptionMode() throws Exception {
        int blockSize = getBlockSize();
        createCipher();
        try {
            mCipher.getOutputSize(blockSize);
            fail();
        } catch (IllegalStateException expected) {}

        initKat(Cipher.DECRYPT_MODE);
        if ((!isAuthenticatedCipher()) && (isStreamCipher())) {
            // Unauthenticated stream ciphers do not buffer input or output.
            for (int input = 0; input <= blockSize * 2; input++) {
                int actualOutputSize = mCipher.getOutputSize(input);
                int expectedOutputSize = input;
                if (actualOutputSize < expectedOutputSize) {
                    fail("getOutputSize(" + expectedOutputSize + ") underestimated output size"
                            + ". min expected: <" + expectedOutputSize
                            + ">, actual: <" + actualOutputSize + ">");
                }
            }
            return;
        }
        // Input may be buffered.

        for (int buffered = 0; buffered < blockSize; buffered++) {
            // Assert that the output of getOutputSize is not lower than the minimum expected.
            for (int input = 0; input <= blockSize * 2; input++) {
                int inputInclBuffered = buffered + input;
                // doFinal dominates the output size.
                int minExpectedOutputSize;
                if (isAuthenticatedCipher()) {
                    // Non-stream authenticated ciphers not supported
                    assertTrue(isStreamCipher());

                    // Authenticated stream cipher
                    minExpectedOutputSize =
                            inputInclBuffered - getKatAuthenticationTagLengthBytes();
                } else {
                    // Unauthenticated block cipher.

                    // One full ciphertext block results in one ciphertext block.
                    minExpectedOutputSize = inputInclBuffered - (inputInclBuffered % blockSize);
                    if (isPaddingEnabled()) {
                        if ((inputInclBuffered % blockSize) == 0) {
                            // No more ciphertext remaining. Thus, the last plaintext block is at
                            // most blockSize - 1 bytes long.
                            minExpectedOutputSize--;
                        } else {
                            // Partial ciphertext block cannot be decrypted. Thus, the last
                            // plaintext block would not have been output.
                            minExpectedOutputSize -= blockSize;
                        }
                    } else {
                        // When no padding is enabled, any remaining ciphertext will cause a error
                        // because only full blocks can be decrypted. Thus, there's no need to
                        // account for its plaintext.
                    }
                }
                if (minExpectedOutputSize < 0) {
                    minExpectedOutputSize = 0;
                }
                int actualOutputSize = mCipher.getOutputSize(input);
                System.out.println("*** buffered: " + buffered + ", input: " + input + ", min: " + minExpectedOutputSize + ", actual: " + actualOutputSize);
                if (actualOutputSize < minExpectedOutputSize) {
                    fail("getOutputSize(" + input + ") underestimated output size when buffered == "
                            + buffered + ". min expected: <"
                            + minExpectedOutputSize + ">, actual: <" + actualOutputSize + ">");
                }
            }

            if (buffered == blockSize - 1) {
                break;
            }
            // Buffer one more byte of input.
            assertNull("buffered: " + buffered, update(new byte[1]));
        }
    }

    public void testInitRequiresIvInDecryptMode() throws Exception {
        if (getKatIv() == null) {
            // IV not used in this transformation.
            return;
        }

        createCipher();
        try {
            init(Cipher.DECRYPT_MODE, getKey());
            fail();
        } catch (InvalidKeyException expected) {}

        createCipher();
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (SecureRandom) null);
            fail();
        } catch (InvalidKeyException expected) {}

        createCipher();
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (AlgorithmParameterSpec) null, null);
            fail();
        } catch (InvalidAlgorithmParameterException expected) {}

        createCipher();
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (AlgorithmParameterSpec) null, null);
            fail();
        } catch (InvalidAlgorithmParameterException expected) {}

        createCipher();
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (AlgorithmParameters) null, null);
            fail();
        } catch (InvalidAlgorithmParameterException expected) {}

        createCipher();
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (AlgorithmParameters) null, null);
            fail();
        } catch (InvalidAlgorithmParameterException expected) {}
    }

    public void testGetIV() throws Exception {
        createCipher();
        assertNull(mCipher.getIV());

        initKat(Cipher.ENCRYPT_MODE);
        assertEquals(getKatIv(), mCipher.getIV());

        byte[] ciphertext = doFinal(new byte[getBlockSize()]);
        assertEquals(getKatIv(), mCipher.getIV());

        createCipher();
        initKat(Cipher.DECRYPT_MODE);
        assertEquals(getKatIv(), mCipher.getIV());

        doFinal(ciphertext);
        assertEquals(getKatIv(), mCipher.getIV());
    }

    public void testIvGeneratedAndUsedWhenEncryptingWithoutExplicitIv() throws Exception {
        createCipher();
        SecretKey key = getKey();
        init(Cipher.ENCRYPT_MODE, key);
        byte[] generatedIv = mCipher.getIV();
        AlgorithmParameters generatedParams = mCipher.getParameters();
        if (getKatIv() == null) {
            // IV not needed by this transformation -- shouldn't have been generated by Cipher.init
            assertNull(generatedIv);
            assertNull(generatedParams);
        } else {
            // IV is needed by this transformation -- should've been generated by Cipher.init
            assertNotNull(generatedIv);
            assertEquals(getKatIv().length, generatedIv.length);
            assertNotNull(generatedParams);
            assertEquals(generatedIv, getIv(generatedParams));
        }

        // Assert that encrypting then decrypting using the above IV (or null) results in the
        // original plaintext.
        byte[] plaintext = new byte[getBlockSize()];
        byte[] ciphertext = doFinal(plaintext);
        createCipher();
        init(Cipher.DECRYPT_MODE, key, generatedParams);
        byte[] decryptedPlaintext = mCipher.doFinal(ciphertext);
        assertEquals(plaintext, decryptedPlaintext);
    }

    public void testGeneratedIvSurvivesReset() throws Exception {
        if (getKatIv() == null) {
            // This transformation does not use an IV
            return;
        }

        createCipher();
        init(Cipher.ENCRYPT_MODE, getKey());
        byte[] iv = mCipher.getIV();
        AlgorithmParameters generatedParams = mCipher.getParameters();
        byte[] ciphertext = mCipher.doFinal(getKatPlaintext());
        // Assert that the IV is still there
        assertEquals(iv, mCipher.getIV());
        assertAlgoritmParametersIv(iv);

        if (getKatIv() != null) {
            // We try to prevent IV reuse by not letting the Cipher be reused.
            return;
        }

        // Assert that encrypting the same input after the above reset produces the same ciphertext.
        assertEquals(ciphertext, mCipher.doFinal(getKatPlaintext()));

        assertEquals(iv, mCipher.getIV());
        assertAlgoritmParametersIv(iv);

        // Just in case, test with a new instance of Cipher with the same parameters
        createCipher();
        init(Cipher.ENCRYPT_MODE, getKey(), generatedParams);
        assertEquals(ciphertext, mCipher.doFinal(getKatPlaintext()));
    }

    public void testGeneratedIvDoesNotSurviveReinitialization() throws Exception {
        if (getKatIv() == null) {
            // This transformation does not use an IV
            return;
        }

        createCipher();
        init(Cipher.ENCRYPT_MODE, getKey());
        byte[] ivBeforeReinitialization = mCipher.getIV();

        init(Cipher.ENCRYPT_MODE, getKey());
        // A new IV should've been generated
        if (Arrays.equals(ivBeforeReinitialization, mCipher.getIV())) {
            fail("Same auto-generated IV after Cipher reinitialized."
                    + " Broken implementation or you're very unlucky (p: 2^{-"
                    + (ivBeforeReinitialization.length * 8) + "})");
        }
    }

    public void testExplicitlySetIvDoesNotSurviveReinitialization() throws Exception {
        if (getKatIv() == null) {
            // This transformation does not use an IV
            return;
        }

        createCipher();
        initKat(Cipher.ENCRYPT_MODE);
        init(Cipher.ENCRYPT_MODE, getKey());
        // A new IV should've been generated
        if (Arrays.equals(getKatIv(), mCipher.getIV())) {
            fail("Auto-generated IV after Cipher reinitialized is the same as previous IV."
                    + " Broken implementation or you're very unlucky (p: 2^{-"
                    + (getKatIv().length * 8) + "})");
        }
    }

    public void testReinitializingInDecryptModeDoesNotUsePreviouslyUsedIv() throws Exception {
        if (getKatIv() == null) {
            // This transformation does not use an IV
            return;
        }

        createCipher();
        // Initialize with explicitly provided IV
        init(Cipher.ENCRYPT_MODE, getKey(), getKatAlgorithmParameterSpec());
        // Make sure the IV has been used, just in case it's set/cached lazily.
        mCipher.update(new byte[getBlockSize() * 2]);

        // IV required but not provided
        try {
            init(Cipher.DECRYPT_MODE, getKey());
            fail();
        } catch (InvalidKeyException expected) {}

        createCipher();
        // Initialize with a generated IV
        init(Cipher.ENCRYPT_MODE, getKey());
        mCipher.doFinal(getKatPlaintext());

        // IV required but not provided
        try {
            init(Cipher.DECRYPT_MODE, getKey());
            fail();
        } catch (InvalidKeyException expected) {}

        // IV required but not provided
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (SecureRandom) null);
            fail();
        } catch (InvalidKeyException expected) {}

        // IV required but not provided
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (AlgorithmParameterSpec) null);
            fail();
        } catch (InvalidAlgorithmParameterException expected) {}

        // IV required but not provided
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (AlgorithmParameterSpec) null, null);
            fail();
        } catch (InvalidAlgorithmParameterException expected) {}

        // IV required but not provided
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (AlgorithmParameters) null);
            fail();
        } catch (InvalidAlgorithmParameterException expected) {}

        // IV required but not provided
        try {
            init(Cipher.DECRYPT_MODE, getKey(), (AlgorithmParameters) null, null);
            fail();
        } catch (InvalidAlgorithmParameterException expected) {}
    }

    public void testKeyDoesNotSurviveReinitialization() throws Exception {
        assertKeyDoesNotSurviveReinitialization(Cipher.ENCRYPT_MODE);
        assertKeyDoesNotSurviveReinitialization(Cipher.DECRYPT_MODE);
    }

    private void assertKeyDoesNotSurviveReinitialization(int opmode) throws Exception {
        byte[] input = getKatInput(opmode);
        createCipher();
        byte[] katKeyBytes = getKatKey();
        SecretKey key1 = importKey(katKeyBytes);
        init(opmode, key1, getKatAlgorithmParameterSpec());
        byte[] output1 = doFinal(input);

        // Create a different key by flipping a bit in the KAT key.
        katKeyBytes[0] ^= 1;
        SecretKey key2 = importKey(katKeyBytes);

        init(opmode, key2, getKatAlgorithmParameterSpec());
        byte[] output2;
        try {
            output2 = doFinal(input);
        } catch (BadPaddingException expected) {
            // Padding doesn't decode probably because the new key is being used. This can only
            // occur is padding is used.
            return;
        }

        // Either padding wasn't used or the old key was used.
        if (Arrays.equals(output1, output2)) {
            fail("Same output when reinitialized with a different key. opmode: " + opmode);
        }
    }

    public void testDoFinalResets() throws Exception {
        assertDoFinalResetsCipher(Cipher.DECRYPT_MODE);
        assertDoFinalResetsCipher(Cipher.ENCRYPT_MODE);
    }

    private void assertDoFinalResetsCipher(int opmode) throws Exception {
        byte[] input = getKatInput(opmode);
        byte[] expectedOutput = getKatOutput(opmode);

        createCipher();
        initKat(opmode);
        assertEquals(expectedOutput, doFinal(input));

        if ((opmode == Cipher.ENCRYPT_MODE) && (getKatIv() != null)) {
            // Assert that this cipher cannot be reused (thus making IV reuse harder)
            try {
                doFinal(input);
                fail();
            } catch (IllegalStateException expected) {}
            return;
        }

        // Assert that the same output is produced after the above reset
        assertEquals(expectedOutput, doFinal(input));

        // Assert that the same output is produced after the above reset. This time, make update()
        // buffer half a block of input.
        if (input.length < getBlockSize() * 2) {
            fail("This test requires an input which is at least two blocks long");
        }
        assertEquals(expectedOutput, concat(
                update(subarray(input, 0, getBlockSize() * 3 / 2)),
                doFinal(subarray(input, getBlockSize() * 3 / 2, input.length))));

        // Assert that the same output is produced after the above reset, despite half of the block
        // having been buffered prior to the reset. This is in case the implementation does not
        // empty that buffer when resetting.
        assertEquals(expectedOutput, doFinal(input));

        // Assert that the IV with which the cipher was initialized is still there after the resets.
        assertEquals(getKatIv(), mCipher.getIV());
        assertAlgoritmParametersIv(getKatIv());
    }

    public void testUpdateWithEmptyInputReturnsCorrectValue() throws Exception {
        // Test encryption
        createCipher();
        initKat(Cipher.ENCRYPT_MODE);
        assertUpdateWithEmptyInputReturnsNull();

        // Test decryption
        createCipher();
        initKat(Cipher.DECRYPT_MODE);
        assertUpdateWithEmptyInputReturnsNull();
    }

    private void assertUpdateWithEmptyInputReturnsNull() {
        assertEquals(null, update(new byte[0]));
        assertEquals(null, update(new byte[getBlockSize() * 2], getBlockSize(), 0));
        assertEquals(null, update(new byte[getBlockSize()], 0, 0));

        // Feed two blocks through the Cipher, so that it's in a state where a block of input
        // produces a block of output.
        // Two blocks are used instead of one because when decrypting with padding enabled, output
        // lags behind input by a block because the Cipher doesn't know whether the most recent
        // input block was supposed to contain padding.
        update(new byte[getBlockSize() * 2]);

        assertEquals(null, update(new byte[0]));
        assertEquals(null, update(new byte[getBlockSize() * 2], getBlockSize(), 0));
        assertEquals(null, update(new byte[getBlockSize()], 0, 0));
    }

    public void testUpdateDoesNotProduceOutputWhenInsufficientInput() throws Exception {
        if (isStreamCipher()) {
            // Stream ciphers always produce output for non-empty input.
            return;
        }

        // Test encryption
        createCipher();
        initKat(Cipher.ENCRYPT_MODE);
        assertUpdateDoesNotProduceOutputWhenInsufficientInput();

        // Test decryption
        createCipher();
        initKat(Cipher.DECRYPT_MODE);
        assertUpdateDoesNotProduceOutputWhenInsufficientInput();
    }

    private void assertUpdateDoesNotProduceOutputWhenInsufficientInput() throws Exception {
        if (getBlockSize() < 8) {
            fail("This test isn't designed for small block size: " + getBlockSize());
        }

        assertEquals(null, update(new byte[1]));
        assertEquals(null, update(new byte[1], 0, 1));
        assertEquals(0, update(new byte[1], 0, 1, new byte[getBlockSize()]));
        assertEquals(0, update(new byte[1], 0, 1, new byte[getBlockSize()], 0));
        assertEquals(0, update(ByteBuffer.allocate(1), ByteBuffer.allocate(getBlockSize())));

        // Feed a block through the Cipher, so that it's potentially no longer in an initial state.
        byte[] output = update(new byte[getBlockSize()]);
        assertEquals(getBlockSize(), output.length);

        assertEquals(null, update(new byte[1]));
        assertEquals(null, update(new byte[1], 0, 1));
        assertEquals(0, update(new byte[1], 0, 1, new byte[getBlockSize()]));
        assertEquals(0, update(new byte[1], 0, 1, new byte[getBlockSize()], 0));
        assertEquals(0, update(ByteBuffer.allocate(1), ByteBuffer.allocate(getBlockSize())));
    }

    public void testKatOneShotEncryptUsingDoFinal() throws Exception {
        createCipher();
        assertKatOneShotTransformUsingDoFinal(
                Cipher.ENCRYPT_MODE, getKatPlaintext(), getKatCiphertext());
    }

    public void testKatOneShotDecryptUsingDoFinal() throws Exception {
        createCipher();
        assertKatOneShotTransformUsingDoFinal(
                Cipher.DECRYPT_MODE, getKatCiphertext(), getKatPlaintext());
    }

    private void assertKatOneShotTransformUsingDoFinal(
            int opmode, byte[] input, byte[] expectedOutput) throws Exception {
        int bufferWithInputInTheMiddleCleartextOffset = 5;
        byte[] bufferWithInputInTheMiddle = concat(
                new byte[bufferWithInputInTheMiddleCleartextOffset],
                input,
                new byte[4]);

        initKat(opmode);
        assertEquals(expectedOutput, doFinal(input));
        initKat(opmode);
        assertEquals(expectedOutput, doFinal(input, 0, input.length));
        initKat(opmode);
        assertEquals(expectedOutput,
                doFinal(bufferWithInputInTheMiddle,
                        bufferWithInputInTheMiddleCleartextOffset,
                        input.length));

        ByteBuffer inputBuffer = ByteBuffer.wrap(
                bufferWithInputInTheMiddle,
                bufferWithInputInTheMiddleCleartextOffset,
                input.length);
        ByteBuffer actualOutputBuffer = ByteBuffer.allocate(expectedOutput.length);
        initKat(opmode);
        assertEquals(expectedOutput.length, doFinal(inputBuffer, actualOutputBuffer));
        assertEquals(0, inputBuffer.remaining());
        assertByteBufferEquals(
                (ByteBuffer) ByteBuffer.wrap(expectedOutput).position(expectedOutput.length),
                actualOutputBuffer);
    }

    public void testKatEncryptOneByteAtATime() throws Exception {
        createCipher();
        initKat(Cipher.ENCRYPT_MODE);
        byte[] plaintext = getKatPlaintext();
        byte[] expectedCiphertext = getKatCiphertext();
        int blockSize = getBlockSize();
        if (isStreamCipher()) {
            // Stream cipher -- one byte in, one byte out
            for (int plaintextIndex = 0; plaintextIndex < plaintext.length; plaintextIndex++) {
                byte[] output = update(new byte[] {plaintext[plaintextIndex]});
                assertEquals("plaintext index: " + plaintextIndex, 1, output.length);
                assertEquals("plaintext index: " + plaintextIndex,
                        expectedCiphertext[plaintextIndex], output[0]);
            }
            byte[] finalOutput = doFinal();
            byte[] expectedFinalOutput;
            if (isAuthenticatedCipher()) {
                expectedFinalOutput =
                        subarray(expectedCiphertext, plaintext.length, expectedCiphertext.length);
            } else {
                expectedFinalOutput = EmptyArray.BYTE;
            }
            assertEquals(expectedFinalOutput, finalOutput);
        } else {
            // Not a stream cipher -- operates on full blocks only.

            // Assert that a block of output is produced once a full block of input is provided.
            // Every input block produces an output block.
            int ciphertextIndex = 0;
            for (int plaintextIndex = 0; plaintextIndex < plaintext.length; plaintextIndex++) {
                byte[] output = update(new byte[] {plaintext[plaintextIndex]});
                if ((plaintextIndex % blockSize) == blockSize - 1) {
                    // Cipher.update is expected to have output a new block
                    assertEquals(
                            "plaintext index: " + plaintextIndex,
                            subarray(
                                    expectedCiphertext,
                                    ciphertextIndex,
                                    ciphertextIndex + blockSize),
                            output);
                } else {
                    // Cipher.update is expected to have produced no output
                    assertEquals("plaintext index: " + plaintextIndex, null, output);
                }
                if (output != null) {
                    ciphertextIndex += output.length;
                }
            }

            byte[] actualFinalOutput = doFinal();
            byte[] expectedFinalOutput =
                    subarray(expectedCiphertext, ciphertextIndex, expectedCiphertext.length);
            assertEquals(expectedFinalOutput, actualFinalOutput);
        }
    }

    public void testKatDecryptOneByteAtATime() throws Exception {
        createCipher();
        initKat(Cipher.DECRYPT_MODE);
        byte[] ciphertext = getKatCiphertext();
        int plaintextIndex = 0;
        int blockSize = getBlockSize();
        byte[] expectedPlaintext = getKatPlaintext();
        boolean paddingEnabled = isPaddingEnabled();
        if (isAuthenticatedCipher()) {
            // Authenticated cipher -- no output until doFinal where ciphertext is authenticated.
            for (int ciphertextIndex = 0; ciphertextIndex < ciphertext.length; ciphertextIndex++) {
                byte[] output = update(new byte[] {ciphertext[ciphertextIndex]});
                assertEquals("ciphertext index: " + ciphertextIndex,
                        0, (output != null) ? output.length : 0);
            }
            byte[] finalOutput = doFinal();
            assertEquals(expectedPlaintext, finalOutput);
        } else if (isStreamCipher()) {
            // Unauthenticated stream cipher -- one byte in, one byte out
            for (int ciphertextIndex = 0; ciphertextIndex < ciphertext.length; ciphertextIndex++) {
                byte[] output = update(new byte[] {ciphertext[ciphertextIndex]});
                assertEquals("ciphertext index: " + ciphertextIndex, 1, output.length);
                assertEquals("ciphertext index: " + ciphertextIndex,
                        expectedPlaintext[ciphertextIndex], output[0]);
            }
            byte[] finalOutput = doFinal();
            assertEquals(0, finalOutput.length);
        } else {
            // Unauthenticated block cipher -- operates in full blocks only

            // Assert that a block of output is produced once a full block of input is provided.
            // When padding is used, output is produced one input byte later: once the first byte of the
            // next input block is provided.
            for (int ciphertextIndex = 0; ciphertextIndex < ciphertext.length; ciphertextIndex++) {
                byte[] output = update(new byte[] {ciphertext[ciphertextIndex]});
                boolean outputExpected =
                        ((paddingEnabled)
                                && (ciphertextIndex > 0) && ((ciphertextIndex % blockSize) == 0))
                        || ((!paddingEnabled) && ((ciphertextIndex % blockSize) == blockSize - 1));

                if (outputExpected) {
                    assertEquals(
                            "ciphertext index: " + ciphertextIndex,
                            subarray(expectedPlaintext, plaintextIndex, plaintextIndex + blockSize),
                            output);
                } else {
                    assertEquals("ciphertext index: " + ciphertextIndex, null, output);
                }

                if (output != null) {
                    plaintextIndex += output.length;
                }
            }

            byte[] actualFinalOutput = doFinal();
            byte[] expectedFinalOutput =
                    subarray(expectedPlaintext, plaintextIndex, expectedPlaintext.length);
            assertEquals(expectedFinalOutput, actualFinalOutput);
        }
    }

    public void testUpdateAADNotSupported() throws Exception {
        createCipher();
        initKat(Cipher.ENCRYPT_MODE);
        if (isAuthenticatedCipher()) {
            assertUpdateAADSupported();
        } else {
            assertUpdateAADNotSupported();
        }

        createCipher();
        initKat(Cipher.DECRYPT_MODE);
        if (isAuthenticatedCipher()) {
            assertUpdateAADSupported();
        } else {
            assertUpdateAADNotSupported();
        }
    }

    private void assertUpdateAADNotSupported() throws Exception {
        try {
            mCipher.updateAAD(new byte[getBlockSize()]);
            fail();
        } catch (UnsupportedOperationException expected) {
        } catch (IllegalStateException expected) {}

        try {
            mCipher.updateAAD(new byte[getBlockSize()], 0, getBlockSize());
            fail();
        } catch (UnsupportedOperationException expected) {
        } catch (IllegalStateException expected) {}

        try {
            mCipher.updateAAD(ByteBuffer.allocate(getBlockSize()));
            fail();
        } catch (UnsupportedOperationException expected) {
        } catch (IllegalStateException expected) {}
    }

    private void assertUpdateAADSupported() throws Exception {
        mCipher.updateAAD(new byte[getBlockSize()]);
        mCipher.updateAAD(new byte[getBlockSize()], 0, getBlockSize());
        mCipher.updateAAD(ByteBuffer.allocate(getBlockSize()));
    }

    // TODO: Add tests for WRAP and UNWRAP

    public void testUpdateAndDoFinalNotSupportedInWrapAndUnwrapModes() throws Exception {
        createCipher();
        assertUpdateAndDoFinalThrowIllegalStateExceprtion(
                Cipher.WRAP_MODE, getKey(), getKatAlgorithmParameterSpec());

        createCipher();
        assertUpdateAndDoFinalThrowIllegalStateExceprtion(
                Cipher.UNWRAP_MODE, getKey(), getKatAlgorithmParameterSpec());
    }

    private void assertUpdateAndDoFinalThrowIllegalStateExceprtion(
            int opmode, SecretKey key, AlgorithmParameterSpec paramSpec)
            throws Exception {
        try {
            init(opmode, key, paramSpec);
        } catch (UnsupportedOperationException e) {
            // Skip this test because wrap/unwrap is not supported by this Cipher
            return;
        }

        try {
            update(new byte[getBlockSize()]);
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            update(new byte[getBlockSize()], 0, getBlockSize());
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            update(new byte[getBlockSize()], 0, getBlockSize(), new byte[getBlockSize() * 2]);
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            update(new byte[getBlockSize()], 0, getBlockSize(), new byte[getBlockSize() * 2], 0);
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            update(ByteBuffer.allocate(getBlockSize()), ByteBuffer.allocate(getBlockSize() * 2));
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            doFinal();
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            doFinal(new byte[getBlockSize()]);
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            doFinal(new byte[getBlockSize()], 0, getBlockSize());
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            doFinal(new byte[getBlockSize() * 2], 0);
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            doFinal(new byte[getBlockSize()], 0, getBlockSize(), new byte[getBlockSize() * 2]);
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            doFinal(new byte[getBlockSize()], 0, getBlockSize(), new byte[getBlockSize() * 2], 0);
            fail();
        } catch (IllegalStateException expected) {}

        init(opmode, key, paramSpec);
        try {
            doFinal(ByteBuffer.allocate(getBlockSize()), ByteBuffer.allocate(getBlockSize() * 2));
            fail();
        } catch (IllegalStateException expected) {}
    }

    public void testGeneratedPadding() throws Exception {
        // Assert that the Cipher under test correctly handles plaintexts of various lengths.
        if (isStreamCipher()) {
            // Not applicable to stream ciphers
            return;
        }

        // Encryption of basePlaintext and additional data should result in baseCiphertext and some
        // data (some of which may be padding).
        int blockSize = getBlockSize();
        byte[] basePlaintext = subarray(getKatPlaintext(), 0, blockSize);
        byte[] baseCiphertext = subarray(getKatCiphertext(), 0, blockSize);
        boolean paddingEnabled = isPaddingEnabled();

        for (int lastInputBlockUnusedByteCount = 0;
                lastInputBlockUnusedByteCount < blockSize;
                lastInputBlockUnusedByteCount++) {
            byte[] plaintext = concat(basePlaintext, new byte[lastInputBlockUnusedByteCount]);
            createCipher();
            initKat(Cipher.ENCRYPT_MODE);

            if ((!paddingEnabled) && ((lastInputBlockUnusedByteCount % blockSize) != 0)) {
                // Without padding, plaintext which does not end with a full block should be
                // rejected.
                try {
                    doFinal(plaintext);
                    fail();
                } catch (IllegalBlockSizeException expected) {}
                continue;
            }
            byte[] ciphertext = doFinal(plaintext);

            assertEquals(
                    "lastInputBlockUnusedByteCount: " + lastInputBlockUnusedByteCount,
                    baseCiphertext,
                    subarray(ciphertext, 0, baseCiphertext.length));

            int expectedCiphertextLength = getExpectedCiphertextLength(plaintext.length);
            int expectedDecryptedPlaintextLength =
                    (paddingEnabled) ? plaintext.length : expectedCiphertextLength;
            assertEquals(
                    "lastInputBlockUnusedByteCount: " + lastInputBlockUnusedByteCount,
                    expectedCiphertextLength,
                    ciphertext.length);
            initKat(Cipher.DECRYPT_MODE);
            byte[] decryptedPlaintext = doFinal(ciphertext);
            assertEquals(
                    "lastInputBlockUnusedByteCount: " + lastInputBlockUnusedByteCount,
                    expectedDecryptedPlaintextLength,
                    decryptedPlaintext.length);
            assertEquals(
                    "lastInputBlockUnusedByteCount: " + lastInputBlockUnusedByteCount,
                    basePlaintext,
                    subarray(decryptedPlaintext, 0, basePlaintext.length));
        }
    }

    public void testDecryptWithMangledPadding() throws Exception {
        if (!isPaddingEnabled()) {
            // Test not applicable when padding not in use
            return;
        }

        createCipher();
        initKat(Cipher.DECRYPT_MODE);
        byte[] ciphertext = getKatCiphertext();
        // Flip a bit in the last byte of ciphertext -- this should result in the last plaintext
        // block getting mangled. In turn, this should result in bad padding.
        ciphertext[ciphertext.length - 1] ^= 1;
        try {
            doFinal(ciphertext);
            fail();
        } catch (BadPaddingException expected) {}
    }

    public void testDecryptWithMissingPadding() throws Exception {
        if (!isPaddingEnabled()) {
            // Test not applicable when padding not in use
            return;
        }

        createCipher();
        initKat(Cipher.DECRYPT_MODE);
        byte[] ciphertext = subarray(getKatCiphertext(), 0, getBlockSize());
        try {
            doFinal(ciphertext);
            fail();
        } catch (BadPaddingException expected) {}
    }

    public void testUpdateCopySafe() throws Exception {
        // Assert that when input and output buffers passed to Cipher.update reference the same
        // byte array, then no input data is overwritten before it's consumed.
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, 0, 0);
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, 0, 1);
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, 1, 0);
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, 0, getBlockSize() - 1);
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, 0, getBlockSize());
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, 0, getBlockSize() + 1);
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, getBlockSize() * 2 - 1, 0);
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, getBlockSize() * 2, 0);
        assertUpdateCopySafe(Cipher.ENCRYPT_MODE, getBlockSize() * 2 + 1, 0);

        assertUpdateCopySafe(Cipher.DECRYPT_MODE, 0, 0);
        assertUpdateCopySafe(Cipher.DECRYPT_MODE, 0, 1);
        assertUpdateCopySafe(Cipher.DECRYPT_MODE, 1, 0);
        assertUpdateCopySafe(Cipher.DECRYPT_MODE, 0, getBlockSize() - 1);
        assertUpdateCopySafe(Cipher.DECRYPT_MODE, 0, getBlockSize());
        assertUpdateCopySafe(Cipher.DECRYPT_MODE, 0, getBlockSize() + 1);
        assertUpdateCopySafe(Cipher.DECRYPT_MODE, getBlockSize() * 2 - 1, 0);
        assertUpdateCopySafe(Cipher.DECRYPT_MODE, getBlockSize() * 2, 0);
        assertUpdateCopySafe(Cipher.DECRYPT_MODE, getBlockSize() * 2 + 1, 0);
    }

    private void assertUpdateCopySafe(
            int opmode, int inputOffsetInBuffer, int outputOffsetInBuffer)
            throws Exception {
        int blockSize = getBlockSize();
        byte[] input;
        byte[] expectedOutput;
        switch (opmode) {
            case Cipher.ENCRYPT_MODE:
                input = getKatPlaintext();
                if (isStreamCipher()) {
                    if (isAuthenticatedCipher()) {
                        expectedOutput = subarray(getKatCiphertext(), 0, input.length);
                    } else {
                        expectedOutput = getKatCiphertext();
                    }
                } else {
                    // Update outputs exactly one block of ciphertext for one block of plaintext,
                    // excluding padding.
                    expectedOutput = subarray(
                            getKatCiphertext(), 0, (input.length / blockSize) * blockSize);
                }
                break;
            case Cipher.DECRYPT_MODE:
                input = getKatCiphertext();
                if (isAuthenticatedCipher()) {
                    expectedOutput = EmptyArray.BYTE;
                } else if (isStreamCipher()) {
                    expectedOutput = getKatPlaintext();
                } else {
                    expectedOutput = getKatPlaintext();
                    if (isPaddingEnabled()) {
                        // When padding is enabled, update will not output the last block of
                        // plaintext because it doesn't know whether more ciphertext will be
                        // provided.
                        expectedOutput = subarray(
                                expectedOutput, 0, ((input.length / blockSize) - 1) * blockSize);
                    } else {
                        // When no padding is used, one block of ciphertext results in one block of
                        // plaintext.
                        expectedOutput = subarray(
                                expectedOutput, 0, (input.length - (input.length % blockSize)));
                    }
                }
                break;
            default:
                throw new AssertionFailedError("Unsupported opmode: " + opmode);
        }

        int inputEndIndexInBuffer = inputOffsetInBuffer + input.length;
        int outputEndIndexInBuffer = outputOffsetInBuffer + expectedOutput.length;

        // Test the update(byte[], int, int, byte[], int) variant
        byte[] buffer = new byte[Math.max(inputEndIndexInBuffer, outputEndIndexInBuffer)];
        System.arraycopy(input, 0, buffer, inputOffsetInBuffer, input.length);
        createCipher();
        initKat(opmode);
        assertEquals(expectedOutput.length,
                update(buffer, inputOffsetInBuffer, input.length,
                        buffer, outputOffsetInBuffer));
        assertEquals(expectedOutput,
                subarray(buffer, outputOffsetInBuffer, outputEndIndexInBuffer));

        if (outputOffsetInBuffer == 0) {
            // We can use the update variant which assumes that output offset is 0.
            buffer = new byte[Math.max(inputEndIndexInBuffer, outputEndIndexInBuffer)];
            System.arraycopy(input, 0, buffer, inputOffsetInBuffer, input.length);
            createCipher();
            initKat(opmode);
            assertEquals(expectedOutput.length,
                    update(buffer, inputOffsetInBuffer, input.length, buffer));
            assertEquals(expectedOutput,
                    subarray(buffer, outputOffsetInBuffer, outputEndIndexInBuffer));
        }

        // Test the update(ByteBuffer, ByteBuffer) variant
        buffer = new byte[Math.max(inputEndIndexInBuffer, outputEndIndexInBuffer)];
        System.arraycopy(input, 0, buffer, inputOffsetInBuffer, input.length);
        ByteBuffer inputBuffer = ByteBuffer.wrap(buffer, inputOffsetInBuffer, input.length);
        ByteBuffer outputBuffer =
                ByteBuffer.wrap(buffer, outputOffsetInBuffer, expectedOutput.length);
        createCipher();
        initKat(opmode);
        assertEquals(expectedOutput.length, update(inputBuffer, outputBuffer));
        assertEquals(expectedOutput,
                subarray(buffer, outputOffsetInBuffer, outputEndIndexInBuffer));
    }

    public void testDoFinalCopySafe() throws Exception {
        // Assert that when input and output buffers passed to Cipher.doFinal reference the same
        // byte array, then no input data is overwritten before it's consumed.
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, 0, 0);
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, 0, 1);
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, 1, 0);
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, 0, getBlockSize() - 1);
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, 0, getBlockSize());
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, 0, getBlockSize() + 1);
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, getBlockSize() * 2 - 1, 0);
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, getBlockSize() * 2, 0);
        assertDoFinalCopySafe(Cipher.ENCRYPT_MODE, getBlockSize() * 2 + 1, 0);

        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, 0, 0);
        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, 0, 1);
        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, 1, 0);
        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, 0, getBlockSize() - 1);
        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, 0, getBlockSize());
        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, 0, getBlockSize() + 1);
        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, getBlockSize() * 2 - 1, 0);
        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, getBlockSize() * 2, 0);
        assertDoFinalCopySafe(Cipher.DECRYPT_MODE, getBlockSize() * 2 + 1, 0);
    }

    private void assertDoFinalCopySafe(
            int opmode, int inputOffsetInBuffer, int outputOffsetInBuffer)
            throws Exception {
        byte[] input = getKatInput(opmode);
        byte[] expectedOutput = getKatOutput(opmode);

        int inputEndIndexInBuffer = inputOffsetInBuffer + input.length;
        int outputEndIndexInBuffer = outputOffsetInBuffer + expectedOutput.length;

        // Test the doFinal(byte[], int, int, byte[], int) variant
        byte[] buffer = new byte[Math.max(inputEndIndexInBuffer, outputEndIndexInBuffer)];
        System.arraycopy(input, 0, buffer, inputOffsetInBuffer, input.length);
        createCipher();
        initKat(opmode);
        assertEquals(expectedOutput.length,
                doFinal(buffer, inputOffsetInBuffer, input.length,
                        buffer, outputOffsetInBuffer));
        assertEquals(expectedOutput,
                subarray(buffer, outputOffsetInBuffer, outputEndIndexInBuffer));

        if (outputOffsetInBuffer == 0) {
            // We can use the doFinal variant which assumes that output offset is 0.
            buffer = new byte[Math.max(inputEndIndexInBuffer, outputEndIndexInBuffer)];
            System.arraycopy(input, 0, buffer, inputOffsetInBuffer, input.length);
            createCipher();
            initKat(opmode);
            assertEquals(expectedOutput.length,
                    doFinal(buffer, inputOffsetInBuffer, input.length, buffer));
            assertEquals(expectedOutput,
                    subarray(buffer, outputOffsetInBuffer, outputEndIndexInBuffer));
        }

        // Test the doFinal(ByteBuffer, ByteBuffer) variant
        buffer = new byte[Math.max(inputEndIndexInBuffer, outputEndIndexInBuffer)];
        System.arraycopy(input, 0, buffer, inputOffsetInBuffer, input.length);
        ByteBuffer inputBuffer = ByteBuffer.wrap(buffer, inputOffsetInBuffer, input.length);
        ByteBuffer outputBuffer =
                ByteBuffer.wrap(buffer, outputOffsetInBuffer, expectedOutput.length);
        createCipher();
        initKat(opmode);
        assertEquals(expectedOutput.length, doFinal(inputBuffer, outputBuffer));
        assertEquals(expectedOutput,
                subarray(buffer, outputOffsetInBuffer, outputEndIndexInBuffer));
    }

    private void createCipher() throws NoSuchAlgorithmException,
            NoSuchPaddingException  {
        mCipher = Cipher.getInstance(getTransformation());
    }

    private String getKeyAlgorithm() {
        String transformation = getTransformation();
        int delimiterIndex = transformation.indexOf('/');
        if (delimiterIndex == -1) {
            fail("Unexpected transformation: " + transformation);
        }
        return transformation.substring(0, delimiterIndex);
    }

    private String getBlockMode() {
        String transformation = getTransformation();
        int delimiterIndex = transformation.indexOf('/');
        if (delimiterIndex == -1) {
            fail("Unexpected transformation: " + transformation);
        }
        int nextDelimiterIndex = transformation.indexOf('/', delimiterIndex + 1);
        if (nextDelimiterIndex == -1) {
            fail("Unexpected transformation: " + transformation);
        }
        return transformation.substring(delimiterIndex + 1, nextDelimiterIndex);
    }

    private String getPadding() {
        String transformation = getTransformation();
        int delimiterIndex = transformation.indexOf('/');
        if (delimiterIndex == -1) {
            fail("Unexpected transformation: " + transformation);
        }
        int nextDelimiterIndex = transformation.indexOf('/', delimiterIndex + 1);
        if (nextDelimiterIndex == -1) {
            fail("Unexpected transformation: " + transformation);
        }
        return transformation.substring(nextDelimiterIndex + 1);
    }

    private SecretKey getKey() {
        return importKey(getKatKey());
    }

    private SecretKey importKey(byte[] keyMaterial) {
        try {
            int keyId = mNextKeyId++;
            String keyAlias = "key" + keyId;
            mAndroidKeyStore.setEntry(
                    keyAlias,
                    new KeyStore.SecretKeyEntry(new SecretKeySpec(keyMaterial, getKeyAlgorithm())),
                    new KeyProtection.Builder(
                            KeyProperties.PURPOSE_ENCRYPT
                                    | KeyProperties.PURPOSE_DECRYPT)
                            .setBlockModes(getBlockMode())
                            .setEncryptionPaddings(getPadding())
                            .setRandomizedEncryptionRequired(false)
                            .build());
            return (SecretKey) mAndroidKeyStore.getKey(keyAlias, null);
        } catch (Exception e) {
            throw new RuntimeException("Failed to import key into AndroidKeyStore", e);
        }
    }

    private boolean isPaddingEnabled() {
        return !getTransformation().toLowerCase(Locale.US).endsWith("/nopadding");
    }

    private int getExpectedCiphertextLength(int plaintextLength) {
        int blockSize = getBlockSize();
        if (isStreamCipher()) {
            // Padding not supported for stream ciphers
            assertFalse(isPaddingEnabled());
            return plaintextLength;
        } else {
            if (isPaddingEnabled()) {
                return ((plaintextLength / blockSize) + 1) * blockSize;
            } else {
                return ((plaintextLength + blockSize - 1) / blockSize) * blockSize;
            }
        }
    }

    private void initKat(int opmode)
            throws InvalidKeyException, InvalidAlgorithmParameterException {
        init(opmode, getKey(), getKatAlgorithmParameterSpec());
    }

    private void init(int opmode, Key key, AlgorithmParameters spec)
            throws InvalidKeyException, InvalidAlgorithmParameterException {
        mCipher.init(opmode, key, spec);
        mOpmode = opmode;
    }

    private void init(int opmode, Key key, AlgorithmParameters spec, SecureRandom random)
            throws InvalidKeyException, InvalidAlgorithmParameterException {
        mCipher.init(opmode, key, spec, random);
        mOpmode = opmode;
    }

    private void init(int opmode, Key key, AlgorithmParameterSpec spec)
            throws InvalidKeyException, InvalidAlgorithmParameterException {
        mCipher.init(opmode, key, spec);
        mOpmode = opmode;
    }

    private void init(int opmode, Key key, AlgorithmParameterSpec spec, SecureRandom random)
            throws InvalidKeyException, InvalidAlgorithmParameterException {
        mCipher.init(opmode, key, spec, random);
        mOpmode = opmode;
    }

    private void init(int opmode, Key key) throws InvalidKeyException {
        mCipher.init(opmode, key);
        mOpmode = opmode;
    }

    private void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
        mCipher.init(opmode, key, random);
        mOpmode = opmode;
    }

    private byte[] doFinal() throws IllegalBlockSizeException, BadPaddingException {
        return mCipher.doFinal();
    }

    private byte[] doFinal(byte[] input) throws IllegalBlockSizeException, BadPaddingException {
        return mCipher.doFinal(input);
    }

    private byte[] doFinal(byte[] input, int inputOffset, int inputLen)
            throws IllegalBlockSizeException, BadPaddingException {
        return mCipher.doFinal(input, inputOffset, inputLen);
    }

    private int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output)
            throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
        return mCipher.doFinal(input, inputOffset, inputLen, output);
    }

    private int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
            int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
            BadPaddingException {
        return mCipher.doFinal(input, inputOffset, inputLen, output, outputOffset);
    }

    private int doFinal(byte[] output, int outputOffset) throws IllegalBlockSizeException,
            ShortBufferException, BadPaddingException {
        return mCipher.doFinal(output, outputOffset);
    }

    private int doFinal(ByteBuffer input, ByteBuffer output) throws ShortBufferException,
            IllegalBlockSizeException, BadPaddingException {
        return mCipher.doFinal(input, output);
    }

    private boolean isEncrypting() {
        return (mOpmode == Cipher.ENCRYPT_MODE) || (mOpmode == Cipher.WRAP_MODE);
    }

    private void assertUpdateOutputSize(int inputLength, int outputLength) {
        if ((isAuthenticatedCipher()) && (!isEncrypting())) {
            assertEquals("Output of update must be empty for authenticated cipher when decrypting",
                    0, outputLength);
            return;
        }

        if (isStreamCipher()) {
            if (outputLength != inputLength) {
                fail("Output of update (" + outputLength + ") not same size as input ("
                        + inputLength + ")");
            }
        } else {
            if ((outputLength % getBlockSize()) != 0) {
                fail("Output of update (" + outputLength + ") not a multiple of block size ("
                        + getBlockSize() + ")");
            }
        }
    }

    private byte[] update(byte[] input) {
        byte[] output = mCipher.update(input);
        assertUpdateOutputSize(
                (input != null) ? input.length : 0, (output != null) ? output.length : 0);
        return output;
    }

    private byte[] update(byte[] input, int offset, int len) {
        byte[] output = mCipher.update(input, offset, len);
        assertUpdateOutputSize(len, (output != null) ? output.length : 0);

        return output;
    }

    private int update(byte[] input, int offset, int len, byte[] output)
            throws ShortBufferException {
        int outputLen = mCipher.update(input, offset, len, output);
        assertUpdateOutputSize(len, outputLen);

        return outputLen;
    }

    private int update(byte[] input, int offset, int len, byte[] output, int outputOffset)
            throws ShortBufferException {
        int outputLen = mCipher.update(input, offset, len, output, outputOffset);
        assertUpdateOutputSize(len, outputLen);

        return outputLen;
    }

    private int update(ByteBuffer input, ByteBuffer output) throws ShortBufferException {
        int inputLimitBefore = input.limit();
        int outputLimitBefore = output.limit();
        int inputLen = input.remaining();
        int outputPosBefore = output.position();

        int outputLen = mCipher.update(input, output);

        assertUpdateOutputSize(inputLen, outputLen);
        assertEquals(inputLimitBefore, input.limit());
        assertEquals(input.limit(), input.position());

        assertEquals(outputLimitBefore, output.limit());
        assertEquals(outputPosBefore + outputLen, output.position());

        return outputLen;
    }

    @SuppressWarnings("unused")
    private static void assertEquals(Buffer expected, Buffer actual) {
        throw new RuntimeException(
                "Comparing ByteBuffers using their .equals is probably not what you want"
                + " -- use assertByteBufferEquals instead.");
    }

    /**
     * Asserts that the position, limit, and capacity of the provided buffers are the same, and that
     * their contents (from position {@code 0} to capacity) are the same.
     */
    private static void assertByteBufferEquals(ByteBuffer expected, ByteBuffer actual) {
        if (expected == null) {
            if (actual == null) {
                return;
            } else {
                fail("Expected: null, actual: " + bufferToString(actual));
            }
        } else {
            if (actual == null) {
                fail("Expected: " + bufferToString(expected) + ", actual: null");
            } else {
                if ((expected.capacity() != actual.capacity())
                        || (expected.position() != actual.position())
                        || (expected.limit() != actual.limit())
                        || (!equals(expected.array(), expected.arrayOffset(), expected.capacity(),
                                    actual.array(), actual.arrayOffset(), actual.capacity()))) {
                    fail("Expected: " + bufferToString(expected)
                            + ", actual: " + bufferToString(actual));
                }
            }
        }
    }

    private static String bufferToString(ByteBuffer buffer) {
        return "ByteBuffer[pos: " + buffer.position() + ", limit: " + buffer.limit()
                + ", capacity: " + buffer.capacity()
                + ", backing array: " + HexEncoding.encode(
                        buffer.array(), buffer.arrayOffset(), buffer.capacity()) + "]";
    }

    private static boolean equals(byte[] arr1, int offset1, int len1, byte[] arr2, int offset2,
            int len2) {
        if (arr1 == null) {
            return (arr2 == null);
        } else if (arr2 == null) {
            return (arr1 == null);
        } else {
            if (len1 != len2) {
                return false;
            }
            for (int i = 0; i < len1; i++) {
                if (arr1[i + offset1] != arr2[i + offset2]) {
                    return false;
                }
            }
            return true;
        }
    }

    private static byte[] subarray(byte[] array, int beginIndex, int endIndex) {
        byte[] result = new byte[endIndex - beginIndex];
        System.arraycopy(array, beginIndex, result, 0, result.length);
        return result;
    }

    private static byte[] concat(byte[]... arrays) {
        int resultLength = 0;
        for (byte[] array : arrays) {
            resultLength += (array != null) ? array.length : 0;
        }

        byte[] result = new byte[resultLength];
        int resultOffset = 0;
        for (byte[] array : arrays) {
            if (array != null) {
                System.arraycopy(array, 0, result, resultOffset, array.length);
                resultOffset += array.length;
            }
        }
        return result;
    }

    private static void assertEquals(byte[] expected, byte[] actual) {
        assertEquals(null, expected, actual);
    }

    private static void assertEquals(String message, byte[] expected, byte[] actual) {
        if (!Arrays.equals(expected, actual)) {
            StringBuilder detail = new StringBuilder();
            if (expected != null) {
                detail.append("Expected (" + expected.length + " bytes): <"
                        + HexEncoding.encode(expected) + ">");
            } else {
                detail.append("Expected: null");
            }
            if (actual != null) {
                detail.append(", actual (" + actual.length + " bytes): <"
                        + HexEncoding.encode(actual) + ">");
            } else {
                detail.append(", actual: null");
            }
            if (message != null) {
                fail(message + ": " + detail);
            } else {
                fail(detail.toString());
            }
        }
    }
}
