changeset 11465:2fa1296ac3d9

8041787: Need new regressions tests for buffer handling for PBE algorithms Reviewed-by: vinnie Contributed-by: rhalade <rajan.halade@oracle.com>
author vinnie
date Wed, 15 Jul 2015 18:12:48 +0100
parents 543b8ffec404
children 5afcccb74f00
files test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/AESPBEWrapper.java test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBECipherWrapper.java test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBESameBuffer.java test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBEWrapper.java test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBEWrapperCreator.java test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBKDF2Wrapper.java test/com/sun/crypto/provider/Cipher/PBE/PBMacBuffer.java test/com/sun/crypto/provider/Cipher/PBE/PBMacDoFinalVsUpdate.java test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBECons.java
diffstat 9 files changed, 1224 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/AESPBEWrapper.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+import java.io.PrintStream;
+import java.security.AlgorithmParameters;
+import java.security.InvalidKeyException;
+import java.security.Provider;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * Wrapper class to test a given AES-based PBE algorithm.
+ *
+ * @author Alexander Fomin
+ */
+public class AESPBEWrapper extends PBEWrapper {
+
+    private AlgorithmParameters pbeParams;
+
+    /**
+     * Constructor. Instantiate Cipher using the given AES-based PBE algorithms.
+     *
+     * @param p security Provider
+     * @param algo PKDF2 algorithm
+     * @param passwd password phrase
+     * @param out print stream
+     * @throws Exception all exceptions are thrown
+     */
+    public AESPBEWrapper(Provider p, String algo, String passwd,
+            PrintStream out) throws Exception {
+        super(algo,
+                SecretKeyFactory.getInstance(algo, p).generateSecret(
+                        new PBEKeySpec(passwd.toCharArray())),
+                Cipher.getInstance(algo, p), out);
+    }
+
+    /**
+     * Perform encryption/decryption operation (depending on the specified
+     * edMode) on the same byte buffer. Compare result with the result at an
+     * allocated buffer. If both results are equal - return true, otherwise
+     * return false.
+     *
+     * @param edMode specified mode
+     * @param inputText text to decrypt
+     * @param offset offset in the text
+     * @param len input length
+     * @return ture - test passed; false - test failed
+     */
+    @Override
+    public boolean execute(int edMode, byte[] inputText, int offset, int len) {
+        try {
+            // init Cipher
+            if (Cipher.ENCRYPT_MODE == edMode) {
+                ci.init(Cipher.ENCRYPT_MODE, this.key);
+                pbeParams = ci.getParameters();
+            } else {
+                ci.init(Cipher.DECRYPT_MODE, this.key, pbeParams);
+            }
+
+            // First, generate the cipherText at an allocated buffer
+            byte[] outputText = ci.doFinal(inputText, offset, len);
+
+            // Second, generate cipherText again at the same buffer of plainText
+            int myoff = offset / 2;
+            int off = ci.update(inputText, offset, len, inputText, myoff);
+            ci.doFinal(inputText, myoff + off);
+
+            if (this.algo.endsWith("AES_256")) {
+                out.print("Expected exception uncaught, "
+                        + "keyStrength > 128 within " + this.algo);
+
+                return false;
+            }
+
+            // Compare to see whether the two results are the same or not
+            return equalsBlock(inputText, myoff, outputText, 0,
+                    outputText.length);
+        } catch (Exception ex) {
+            if ((ex instanceof InvalidKeyException)
+                    && this.algo.endsWith("AES_256")) {
+                out.println("Expected InvalidKeyException exception: "
+                        + ex.getMessage());
+
+                return true;
+            }
+
+            out.println("Catch unexpected exception within " + algo);
+            ex.printStackTrace(out);
+
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBECipherWrapper.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @author Valerie PENG
+ * @author Yun Ke
+ * @author Alexander Fomin
+ * @author rhalade
+ */
+import java.security.spec.AlgorithmParameterSpec;
+
+import java.util.StringTokenizer;
+
+import java.security.InvalidKeyException;
+import java.security.Provider;
+
+import java.io.PrintStream;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+
+public class PBECipherWrapper extends PBEWrapper {
+
+    private final AlgorithmParameterSpec aps;
+
+    public PBECipherWrapper(
+            Provider p, String algo, String passwd, PrintStream out)
+            throws Exception {
+        super(algo,
+                SecretKeyFactory.getInstance(
+                        new StringTokenizer(algo, "/").nextToken(), p).generateSecret(
+                        new PBEKeySpec(passwd.toCharArray())),
+                Cipher.getInstance(algo, p), out);
+
+        int SALT_SIZE = 8;
+        aps = new PBEParameterSpec(generateSalt(SALT_SIZE), ITERATION_COUNT);
+    }
+
+    @Override
+    public boolean execute(int edMode, byte[] inputText, int offset,
+            int len) {
+        StringTokenizer st = new StringTokenizer(algo, "/");
+        String baseAlgo = st.nextToken().toUpperCase();
+
+        // Perform encryption or decryption depends on the specified edMode
+        try {
+            ci.init(edMode, key, aps);
+
+            // First, generate the cipherText at an allocated buffer
+            byte[] outputText = ci.doFinal(inputText, offset, len);
+
+            // Second, generate cipherText again at the same buffer of
+            // plainText
+            int myoff = offset / 2;
+            int off = ci.update(inputText, offset, len, inputText, myoff);
+
+            ci.doFinal(inputText, myoff + off);
+
+            if (baseAlgo.endsWith("TRIPLEDES")
+                    || baseAlgo.endsWith("AES_256")) {
+                out.print("Expected exception uncaught,"
+                        + "keyStrength > 128 within " + this.algo);
+
+                return false;
+            }
+
+            // Compare to see whether the two results are the same or not
+            boolean result = equalsBlock(inputText, myoff, outputText, 0,
+                    outputText.length);
+
+            return result;
+        } catch (Exception ex) {
+            if ((ex instanceof InvalidKeyException)
+                    && (baseAlgo.endsWith("TRIPLEDES")
+                    || baseAlgo.endsWith("AES_256"))) {
+                out.println("Expected InvalidKeyException exception: "
+                        + ex.getMessage());
+
+                return true;
+            }
+
+            out.println("Catch unexpected exception within " + algo);
+            ex.printStackTrace(out);
+
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBESameBuffer.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8041787
+ * @library .
+ * @build PBEWrapper PBEWrapperCreator PBKDF2Wrapper AESPBEWrapper PBECipherWrapper
+ * @summary Verify that same encrypt/decrypt buffer can be used for PBE ciphers
+ * @author Alexander Fomin
+ * @author rhalade
+ * @run main PBESameBuffer
+ */
+import java.io.PrintStream;
+import java.security.*;
+import java.util.Random;
+import javax.crypto.Cipher;
+
+public class PBESameBuffer {
+
+    private static final String[] pbeAlgorithms = {
+        "pbeWithMD5ANDdes", "PBEWithMD5AndDES/CBC/PKCS5Padding",
+        "pbeWithMD5ANDtripledes", "PBEWithMD5AndTRIPLEDES/CBC/PKCS5Padding",
+        "PBEwithSHA1AndDESede", "PBEwithSHA1AndDESede/CBC/PKCS5Padding",
+        "PBEwithSHA1AndRC2_40", "PBEwithSHA1AndRC2_40/CBC/PKCS5Padding",
+        "PBEWithSHA1AndRC2_128", "PBEWithSHA1AndRC2_128/CBC/PKCS5Padding",
+        "PBEWithSHA1AndRC4_40", "PBEWithSHA1AndRC4_40/ECB/NoPadding",
+        "PBEWithSHA1AndRC4_128", "PBEWithSHA1AndRC4_128/ECB/NoPadding",
+        "PBEWithHmacSHA1AndAES_128",
+        "PBEWithHmacSHA224AndAES_128",
+        "PBEWithHmacSHA256AndAES_128",
+        "PBEWithHmacSHA384AndAES_128",
+        "PBEWithHmacSHA512AndAES_128",
+        "PBEWithHmacSHA1AndAES_256",
+        "PBEWithHmacSHA224AndAES_256",
+        "PBEWithHmacSHA256AndAES_256",
+        "PBEWithHmacSHA384AndAES_256",
+        "PBEWithHmacSHA512AndAES_256",
+        "PBKDF2WithHmacSHA1",
+        "PBKDF2WithHmacSHA224",
+        "PBKDF2WithHmacSHA256",
+        "PBKDF2WithHmacSHA384",
+        "PBKDF2WithHmacSHA512"
+    };
+
+    private static final String PBEPASS = "Hush, it's supposed to be a secret!";
+
+    private static final int INPUT_LENGTH = 800;
+    private static final int[] OFFSETS = {0, 1, 2, 3};
+    private static final int NUM_PAD_BYTES = 8;
+    private static final int PBKDF2_ADD_PAD_BYTES = 8;
+
+    private static int OUTPUT_OFFSET;
+
+    public static void main(String[] args) {
+        if (!(new PBESameBuffer().test(args, System.out))) {
+            throw new RuntimeException("Some PBE algorithm tests failed");
+        }
+    }
+
+    public boolean test(String[] args, PrintStream out) {
+        boolean result = true;
+
+        Provider p = Security.getProvider("SunJCE");
+
+        for (int loop : OFFSETS) {
+            OUTPUT_OFFSET = loop;
+
+            // generate input data
+            byte[] inputText = new byte[INPUT_LENGTH + NUM_PAD_BYTES
+                    + OUTPUT_OFFSET * 2 + PBKDF2_ADD_PAD_BYTES];
+            new Random().nextBytes(inputText);
+
+            for (String algorithm : pbeAlgorithms) {
+                out.println("=> Testing algorithm " + algorithm + " and offset "
+                        + OUTPUT_OFFSET + ":");
+
+                try {
+                    // Initialize Cipher and key for this algorithm
+                    PBEWrapper pbeCi = PBEWrapperCreator.createWrapper(p,
+                            algorithm,
+                            PBEPASS,
+                            out);
+
+                    // Encrypt
+                    if ((pbeCi != null) && (!pbeCi.execute(Cipher.ENCRYPT_MODE,
+                            inputText,
+                            OUTPUT_OFFSET * 2,
+                            INPUT_LENGTH))) {
+                        result = false;
+                    }
+
+                    // PBKDF2 required 16 byte padding
+                    int padLength = getPadLength(algorithm);
+
+                    // Decrypt
+                    // Note: inputText is implicitly padded by the above encrypt
+                    // operation so decrypt operation can safely proceed
+                    if ((pbeCi != null) && (!pbeCi.execute(Cipher.DECRYPT_MODE,
+                            inputText,
+                            OUTPUT_OFFSET,
+                            INPUT_LENGTH + padLength))) {
+                        result = false;
+                    }
+                } catch (Exception ex) {
+                    ex.printStackTrace(out);
+                    result = false;
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Get the padding length for the given algorithm
+     *
+     * @param theAlgName algorithm name
+     * @return padding length for the given algorithm
+     */
+    private int getPadLength(String theAlgName) {
+        if (theAlgName.toUpperCase().contains("PBKDF2")) {
+            return NUM_PAD_BYTES + PBKDF2_ADD_PAD_BYTES;
+        }
+
+        if (theAlgName.toUpperCase().contains("AES")) {
+            return NUM_PAD_BYTES + PBKDF2_ADD_PAD_BYTES;
+        }
+
+        return NUM_PAD_BYTES;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBEWrapper.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+import java.io.PrintStream;
+import java.util.Random;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+
+/**
+ * PBEWrapper is the abstract class for all concrete PBE Cipher wrappers. A
+ * PBEWrapper object encapsulates the information and behavior needed to test if
+ * the multiple-part encryption/decryption is performing by expected way on the
+ * same byte buffer.
+ *
+ * @author Alexandr Fomin
+ * @author rhalade
+ */
+public abstract class PBEWrapper {
+
+    protected final static int ITERATION_COUNT = 1000;
+
+    protected final SecretKey key;
+    protected final Cipher ci;
+    protected final String algo;
+    protected final PrintStream out;
+
+    public PBEWrapper(String pAlgo, SecretKey pKey, Cipher pCi,
+            PrintStream pOut ){
+        this.algo = pAlgo;
+        this.key = pKey;
+        this.ci = pCi;
+        this.out = pOut;
+    }
+
+    /**
+     * Abstract method need to be implemented in the subclasses.
+     *
+     * @param edMode Cipher mode - encrypt/decrypt
+     * @param inputText byte buffer to process
+     * @param offset offset in byte the inputText
+     * @param len length of byte to process in inputText
+     * @return true if cipher operation is successful, false otherwise
+     */
+    public abstract boolean execute(int edMode, byte[] inputText, int offset,
+            int len);
+
+    /**
+     * An utility method to prepare "salt" for following Secret Key generation.
+     *
+     * @param numberOfBytes number of bytes in salt
+     * @return randomly generated byte array
+     */
+    protected static byte[] generateSalt(int numberOfBytes) {
+        byte[] salt = new byte[numberOfBytes];
+        new Random().nextBytes(salt);
+        return salt;
+    }
+
+    /**
+     * An utility method to check if two byte arrays are equal
+     *
+     * @param b1 first byte array
+     * @param off1 offset to compare from in b1
+     * @param b2 second byte array
+     * @param off2 offset to compare from in b2
+     * @param len length to compare
+     * @return true of arrays are equal, false otherwise
+     */
+    protected boolean equalsBlock(byte[] b1, int off1,
+            byte[] b2, int off2, int len) {
+        for (int i = off1, j = off2, k = 0; k < len; i++, j++, k++) {
+            if (b1[i] != b2[j]) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBEWrapperCreator.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+import java.security.Provider;
+import java.io.PrintStream;
+
+/**
+ * An utility class to create PBEWrapper object for the TestCipherSameBuffer
+ * test.
+ *
+ * @author Alexander Fomin
+ */
+public class PBEWrapperCreator {
+
+    private static final String PBKDF2 = "PBKDF2";
+    private static final String AES = "AES";
+
+    /**
+     * Create PBEWrapper for the TestCipherSameBuffer test using given
+     * parameters.
+     *
+     * @param p security provider
+     * @param algo algorithms to test
+     * @param passwd a password phrase
+     * @param out print stream object
+     * @return PBEWrapper in accordance to requested algorithm
+     * @throws Exception all exception are thrown.
+     */
+    public static PBEWrapper createWrapper(Provider p, String algo,
+            String passwd, PrintStream out) throws Exception {
+        if (algo.toUpperCase().contains(PBKDF2)) {
+            return new PBKDF2Wrapper(p, algo, passwd, out);
+        } else if (algo.toUpperCase().contains(AES)) {
+            return new AESPBEWrapper(p, algo, passwd, out);
+        } else {
+            return new PBECipherWrapper(p, algo, passwd, out);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBKDF2Wrapper.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+import java.io.PrintStream;
+import java.security.Provider;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Wrapper class to test a given SecretKeyFactory.PBKDF2 algorithm.
+ *
+ * @author Alexander Fomin
+ */
+public class PBKDF2Wrapper extends PBEWrapper {
+    private static final String CIPHER_TANSFORMATION = "AES/CBC/PKCS5Padding";
+    private static final int SALT_SIZE = 64;
+    private static final int PKDF2_DEFAULT_KEY_LEN = 128;
+
+    private static volatile byte[] iv;
+
+    /**
+     * PBKDF2Wrapper constructor. Instantiate Cipher using
+     * "AES/CBC/PKCS5Padding" transformation. Generate a secret key using given
+     * PKDF2 algorithms.
+     *
+     * @param p security Provider
+     * @param algo PKDF2 algorithm
+     * @param passwd password phrase
+     * @param out print stream
+     * @throws Exception all exceptions are thrown
+     */
+    public PBKDF2Wrapper(Provider p, String algo, String passwd,
+            PrintStream out) throws Exception {
+        super(algo,
+                SecretKeyFactory.getInstance(algo, p).generateSecret(
+                        new PBEKeySpec(passwd.toCharArray(),
+                generateSalt(SALT_SIZE), ITERATION_COUNT, PKDF2_DEFAULT_KEY_LEN)),
+                Cipher.getInstance(CIPHER_TANSFORMATION, p), out);
+    }
+
+    /**
+     * Perform encryption/decryption operation (depending on the specified
+     * edMode) on the same byte buffer. Compare result with the result at an
+     * allocated buffer. If both results are equal - return true, otherwise
+     * return false.
+     *
+     * @param edMode specified mode
+     * @param inputText text to decrypt
+     * @param offset offset in the text
+     * @param len input length
+     * @return ture - test passed; false - test failed
+     */
+    @Override
+    public boolean execute(int edMode, byte[] inputText, int offset, int len) {
+        int needBytesForResult = -1;
+        String KEY_ALGORITHM = "AES";
+
+        try {
+            // init Cipher
+            if (Cipher.ENCRYPT_MODE == edMode) {
+                ci.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getEncoded(),
+                        KEY_ALGORITHM));
+                iv = ci.getParameters().getParameterSpec(IvParameterSpec.class).
+                        getIV();
+            } else {
+                ci.init(Cipher.DECRYPT_MODE,
+                        new SecretKeySpec(key.getEncoded(), KEY_ALGORITHM),
+                        new IvParameterSpec(iv));
+            }
+
+            // First, generate the cipherText at an allocated buffer
+            byte[] outputText = ci.doFinal(inputText, offset, len);
+
+            // Second, generate cipherText again at the same buffer of plainText
+            int myoff = offset / 2;
+            int off = ci.update(inputText, offset, len, inputText, myoff);
+            ci.doFinal(inputText, myoff + off);
+
+            // Compare to see whether the two results are the same or not
+            return equalsBlock(inputText, myoff, outputText, 0,
+                    outputText.length);
+        } catch (Exception ex) {
+            out.println("Catch unexpected exception within " + algo
+                    + " " + edMode + ": " + ex.getMessage()
+                    + ". getOutputSize()" + "returned " + needBytesForResult);
+            ex.printStackTrace(out);
+
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PBMacBuffer.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+import java.nio.ByteBuffer;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Random;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * @test
+ * @bug 8041787
+ * @summary verify that Mac.update works with different size ByteBuffer
+ * @author Alexander Fomin
+ * @run main PBMacBuffer
+ */
+public class PBMacBuffer {
+
+    private final int LARGE_SIZE = 500000;
+
+    public static void main(String[] args) {
+        String[] PBMAC1Algorithms = {
+            "HmacPBESHA1",
+            "PBEWithHmacSHA1",
+            "PBEWithHmacSHA224",
+            "PBEWithHmacSHA256",
+            "PBEWithHmacSHA384",
+            "PBEWithHmacSHA512"
+        };
+
+        String[] PBKDF2Algorithms = {
+            "PBKDF2WithHmacSHA1",
+            "PBKDF2WithHmacSHA224",
+            "PBKDF2WithHmacSHA256",
+            "PBKDF2WithHmacSHA384",
+            "PBKDF2WithHmacSHA512"
+        };
+
+        PBMacBuffer testRunner = new PBMacBuffer();
+        boolean failed = false;
+
+        for (String thePBMacAlgo : PBMAC1Algorithms) {
+
+            for (String thePBKDF2Algo : PBKDF2Algorithms) {
+
+                System.out.println("Running test with " + thePBMacAlgo
+                        + " and " + thePBKDF2Algo + ":");
+                try {
+                    if (!testRunner.doTest(thePBMacAlgo, thePBKDF2Algo)) {
+                        failed = true;
+                    }
+                } catch (NoSuchAlgorithmException | InvalidKeyException |
+                        InvalidKeySpecException e) {
+                    failed = true;
+                    e.printStackTrace(System.out);
+                    System.out.println("Test FAILED.");
+                }
+            }
+        }
+
+        if (failed) {
+            throw new RuntimeException("One or more tests failed....");
+        }
+    }
+
+    /**
+     * Tests Mac.update(ByteBuffer input) method. Three test cases are
+     * performed: - large ByteBuffer test case to test if the update() method
+     * process a large ByteBuffer correctly; - empty ByteBuffer test case to
+     * test if the update() method process an empty ByteBuffer correctly; - NULL
+     * ByteBuffer test case to test if the update() method throws expected
+     * IllegalArgumentException exception.
+     *
+     * @param theMacAlgo PBMAC algorithm to test
+     * @param thePBKDF2Algo PBKDF2 algorithm to test
+     * @return true - test passed; false - otherwise.
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeyException
+     * @throws InvalidKeySpecException
+     * @see javax.crypto.Mac
+     */
+    protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
+            throws NoSuchAlgorithmException, InvalidKeyException,
+            InvalidKeySpecException {
+        // obtain a SecretKey using PBKDF2
+        SecretKey key = getSecretKey(thePBKDF2Algo);
+
+        // Instantiate Mac object and init it with a SecretKey
+        Mac theMac = Mac.getInstance(theMacAlgo);
+        theMac.init(key);
+
+        // Do large ByteBuffer test case
+        if (!largeByteBufferTest(theMac)) {
+            System.out.println("Large ByteBuffer test case failed.");
+            return false;
+        }
+
+        // Do empty ByteBuffer test case
+        if (!emptyByteBufferTest(theMac)) {
+            System.out.println("Empty ByteBuffer test case failed.");
+            return false;
+        }
+
+        // Do null ByteBuffer test case
+        if (!nullByteBufferTest(theMac)) {
+            System.out.println("NULL ByteBuffer test case failed.");
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Large ByteBuffer test case. Generate random ByteBuffer of LARGE_SIZE
+     * size. Performs MAC operation with the given Mac object (theMac
+     * parameter).Verifies the assertion "Upon return, the buffer's position
+     * will be equal to its limit; its limit will not have changed".
+     *
+     * @param theMac MAC object to test.
+     * @return true - test case passed; false - otherwise;
+     */
+    protected boolean largeByteBufferTest(Mac theMac) {
+        ByteBuffer buf = generateRandomByteBuffer(LARGE_SIZE);
+        int limitBefore = buf.limit();
+
+        theMac.update(buf);
+        theMac.doFinal();
+
+        int limitAfter = buf.limit();
+        int positonAfter = buf.position();
+
+        if (limitAfter != limitBefore) {
+            System.out.println("FAIL: Buffer's limit has been chenged.");
+            return false;
+        }
+
+        if (positonAfter != limitAfter) {
+            System.out.println("FAIL: "
+                    + "Buffer's position isn't equal to its limit");
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Empty ByteBuffer test case. Generates an empty ByteBuffer. Perform MAC
+     * operation. No exceptions are expected.
+     *
+     * @param theMac
+     * @return true - test case pass; exception otherwise
+     */
+    protected boolean emptyByteBufferTest(Mac theMac) {
+        ByteBuffer buf = generateRandomByteBuffer(0);
+        theMac.update(buf);
+        theMac.doFinal();
+        return true;
+    }
+
+    /**
+     * NULL ByteBuffer test case. Pass NULL ByteBuffer to Mac.update(ByteBuffer
+     * buffer) method. An IllegalArgumentException expected.
+     *
+     * @param theMac Mac object to test.
+     * @return true - test case pass; false - otherwise.
+     */
+    protected boolean nullByteBufferTest(Mac theMac) {
+        try {
+            ByteBuffer buf = null;
+            theMac.update(buf);
+            theMac.doFinal();
+        } catch (IllegalArgumentException e) {
+            // expected exception has been thrown
+            return true;
+        }
+
+        System.out.println("FAIL: "
+                + "IllegalArgumentException hasn't been thrown as expected");
+
+        return false;
+    }
+
+    /**
+     * Get SecretKey for the given PBKDF2 algorithm.
+     *
+     * @param thePBKDF2Algorithm - PBKDF2 algorithm
+     * @return SecretKey according to thePBKDF2Algorithm
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    protected SecretKey getSecretKey(String thePBKDF2Algorithm)
+            throws NoSuchAlgorithmException, InvalidKeySpecException {
+        // Prepare salt
+        byte[] salt = new byte[64]; // PKCS #5 v2.1 recommendation
+        new SecureRandom().nextBytes(salt);
+
+        // Generate secret key
+        PBEKeySpec pbeKeySpec = new PBEKeySpec(
+                "A #pwd# implied to be hidden!".toCharArray(),
+                salt, 1000, 128);
+        SecretKeyFactory keyFactory
+                = SecretKeyFactory.getInstance(thePBKDF2Algorithm);
+        return keyFactory.generateSecret(pbeKeySpec);
+    }
+
+    /**
+     * An utility method to generate a random ByteBuffer of the requested size.
+     *
+     * @param size size of the ByteBuffer.
+     * @return ByteBuffer populated random data;
+     */
+    private ByteBuffer generateRandomByteBuffer(int size) {
+        // generate randome byte array
+        byte[] data = new byte[size];
+        new Random().nextBytes(data);
+
+        // create ByteBuffer
+        ByteBuffer bb = ByteBuffer.wrap(data);
+
+        return bb;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PBMacDoFinalVsUpdate.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * @test
+ * @bug 8041787
+ * @summary Check if doFinal and update operation result in same PBMac
+ * @author Alexander Fomin
+ * @run main PBMacDoFinalVsUpdate
+ */
+public class PBMacDoFinalVsUpdate {
+
+    public static void main(String[] args) {
+        String[] PBMAC1Algorithms = {
+            "HmacPBESHA1",
+            "PBEWithHmacSHA1",
+            "PBEWithHmacSHA224",
+            "PBEWithHmacSHA256",
+            "PBEWithHmacSHA384",
+            "PBEWithHmacSHA512"
+        };
+
+        String[] PBKDF2Algorithms = {
+            "PBKDF2WithHmacSHA1",
+            "PBKDF2WithHmacSHA224",
+            "PBKDF2WithHmacSHA256",
+            "PBKDF2WithHmacSHA384",
+            "PBKDF2WithHmacSHA512"
+        };
+
+        PBMacDoFinalVsUpdate testRunner = new PBMacDoFinalVsUpdate();
+        boolean failed = false;
+
+        for (String thePBMacAlgo : PBMAC1Algorithms) {
+
+            for (String thePBKDF2Algo : PBKDF2Algorithms) {
+
+                System.out.println("Running test with " + thePBMacAlgo
+                        + " and " + thePBKDF2Algo + ":");
+                try {
+                    if (!testRunner.doTest(thePBMacAlgo, thePBKDF2Algo)) {
+                        failed = true;
+                    }
+                } catch (NoSuchAlgorithmException | InvalidKeyException |
+                        InvalidKeySpecException e) {
+                    failed = true;
+                    e.printStackTrace(System.out);
+                    System.out.println("Test FAILED.");
+                }
+            }
+        }
+
+        if (failed) {
+            throw new RuntimeException("One or more tests failed....");
+        }
+    }
+
+    /**
+     * Uses a random generator to initialize a message, instantiate a Mac object
+     * according to the given PBMAC1 algorithm, initialize the object with a
+     * SecretKey derived using PBKDF2 algorithm (see PKCS #5 v21, chapter 7.1),
+     * feed the message into the Mac object all at once and get the output MAC
+     * as result1. Reset the Mac object, chop the message into three pieces,
+     * feed into the Mac object sequentially, and get the output MAC as result2.
+     * Finally, compare result1 and result2 and see if they are the same.
+     *
+     * @param theMacAlgo PBMAC algorithm to test
+     * @param thePBKDF2Algo PBKDF2 algorithm to test
+     * @return true - the test is passed; false - otherwise.
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeyException
+     * @throws InvalidKeySpecException
+     */
+    protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
+            throws NoSuchAlgorithmException, InvalidKeyException,
+            InvalidKeySpecException {
+        int OFFSET = 5;
+
+        // Some message for which a MAC result will be calculated
+        byte[] plain = new byte[25];
+        new SecureRandom().nextBytes(plain);
+
+        // Form tail - is one of the three pieces
+        byte[] tail = new byte[plain.length - OFFSET];
+        System.arraycopy(plain, OFFSET, tail, 0, tail.length);
+
+        // Obtain a SecretKey using PBKDF2
+        SecretKey key = getSecretKey(thePBKDF2Algo);
+
+        // Instantiate Mac object and init it with a SecretKey and calc result1
+        Mac theMac = Mac.getInstance(theMacAlgo);
+        theMac.init(key);
+        byte[] result1 = theMac.doFinal(plain);
+
+        if (!isMacLengthExpected(theMacAlgo, result1.length)) {
+            return false;
+        }
+
+        // Reset Mac and calculate result2
+        theMac.reset();
+        theMac.update(plain[0]);
+        theMac.update(plain, 1, OFFSET - 1);
+        byte[] result2 = theMac.doFinal(tail);
+
+        // Return result
+        if (!java.util.Arrays.equals(result1, result2)) {
+            System.out.println("result1 and result2 are not the same:");
+            System.out.println("result1: " + dumpByteArray(result1));
+            System.out.println("result2: " + dumpByteArray(result2));
+            return false;
+        } else {
+            System.out.println("Resulted MAC with update and doFinal is same");
+        }
+
+        return true;
+    }
+
+    /**
+     * Get SecretKey for the given PBKDF2 algorithm.
+     *
+     * @param thePBKDF2Algorithm - PBKDF2 algorithm
+     * @return SecretKey according to thePBKDF2Algorithm
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    protected SecretKey getSecretKey(String thePBKDF2Algorithm)
+            throws NoSuchAlgorithmException, InvalidKeySpecException {
+        // Prepare salt
+        byte[] salt = new byte[64]; // PKCS #5 v2.1 recommendation
+        new SecureRandom().nextBytes(salt);
+
+        // Generate secret key
+        PBEKeySpec pbeKeySpec = new PBEKeySpec(
+                "A #pwd# implied to be hidden!".toCharArray(),
+                salt, 1000, 128);
+        SecretKeyFactory keyFactory
+                = SecretKeyFactory.getInstance(thePBKDF2Algorithm);
+        return keyFactory.generateSecret(pbeKeySpec);
+    }
+
+    /**
+     * Check if the lengthToCheck is expected length for the given MACAlgo.
+     *
+     * @param MACAlgo PBMAC algorithm
+     * @param lengthToCheck the length of MAC need to check
+     * @return true - lengthToCheck is expected length for the MACAlgo; false -
+     * otherwise.
+     */
+    protected boolean isMacLengthExpected(String MACAlgo, int lengthToCheck) {
+        java.util.regex.Pattern p = java.util.regex.Pattern.compile("(\\d+)",
+                java.util.regex.Pattern.CASE_INSENSITIVE);
+        java.util.regex.Matcher m = p.matcher(MACAlgo);
+        int val = 0;
+
+        if (m.find()) {
+            val = Integer.parseInt(m.group(1));
+        }
+
+        // HmacPBESHA1 should return MAC 20 byte length
+        if ((val == 1) && (lengthToCheck == 20)) {
+            return true;
+        }
+
+        return (val / 8) == lengthToCheck;
+    }
+
+    /**
+     * An utility method to dump a byte array for debug output.
+     *
+     * @param theByteArray the byte array to dump
+     * @return string representation of the theByteArray in Hex.
+     */
+    protected String dumpByteArray(byte[] theByteArray) {
+        StringBuilder buf = new StringBuilder();
+
+        for (byte b : theByteArray) {
+            buf.append(Integer.toHexString(b));
+        }
+
+        return buf.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBECons.java	Wed Jul 15 18:12:48 2015 +0100
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 2014, 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.
+ *
+ * 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.
+ */
+
+import java.io.PrintStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+
+/**
+ * @test
+ * @bug 8041787
+ * @summary Verify that for PBEWithMD5AndDES cipher, only CBC mode and
+ * PKCS#5Padding is allowed
+ * @author Yun Ke
+ * @author Bill Situ
+ * @author Yu-Ching (Valerie) PENG
+ * @run main TestCipherKeyWrapperPBEKey
+ */
+public class TestCipherPBECons {
+
+    private static final String[] PBEAlgorithms = {"pbeWithMD5ANDdes",
+        "PBEWithMD5AndTripleDES"};
+    private static final String[] cipherModes = {"ECb", "cbC", "cFB", "Cfb32",
+        "OfB", "oFb64", "pCbC"};
+    private static final String[] cipherPaddings = {"Pkcs5Padding", "NoPaDDing"};
+
+    public static void main(String[] args) {
+        TestCipherPBECons test = new TestCipherPBECons();
+        Provider sunjce = Security.getProvider("SunJCE");
+
+        if (!test.runAll(sunjce, System.out)) {
+            throw new RuntimeException("One or more tests have failed....");
+        }
+    }
+
+    public boolean runAll(Provider p, PrintStream out) {
+        boolean finalResult = true;
+
+        for (String algorithm : PBEAlgorithms) {
+            for (String mode : cipherModes) {
+                for (String padding : cipherPaddings) {
+                    out.println("Running test with " + algorithm
+                            + "/" + mode + "/" + padding);
+                    try {
+                        if (!runTest(p, algorithm, mode, padding, out)) {
+                            finalResult = false;
+                            out.println("STATUS: Failed");
+                        } else {
+                            out.println("STATUS: Passed");
+                        }
+                    } catch (Exception ex) {
+                        finalResult = false;
+                        ex.printStackTrace(out);
+                        out.println("STATUS:Failed");
+                    }
+                }
+            }
+        }
+
+        return finalResult;
+    }
+
+    public boolean runTest(Provider p, String algo, String mo, String pad,
+            PrintStream out) throws Exception {
+        try {
+            // Initialization
+            Cipher ci = Cipher.getInstance(algo + "/" + mo + "/" + pad, p);
+
+            // No exception thrown, must be of the right mode and right
+            // padding scheme
+            return (mo.equalsIgnoreCase("CBC"))
+                    && (pad.equalsIgnoreCase("PKCS5Padding"));
+        } catch (NoSuchAlgorithmException ex) {
+            if (p.getName().compareTo("SunJCE") == 0) {
+                if (!(mo.equalsIgnoreCase("CBC")
+                        && pad.equalsIgnoreCase("PKCS5Padding"))) {
+                    out.println("NoSuchAlgorithmException is as expected");
+                    return true;
+                }
+            }
+
+            out.println("Caught exception: " + ex.getMessage());
+            throw ex;
+        } catch (NoSuchPaddingException ex) {
+            if (mo.equalsIgnoreCase("CBC")
+                    && pad.equalsIgnoreCase("NoPadding")) {
+                out.println("NoSuchPaddingException is as expected");
+                return true;
+            } else {
+                out.println("Caught unexpected exception: " + ex.getMessage());
+                return false;
+            }
+        }
+    }
+}