# HG changeset patch # User tyan # Date 1443043694 0 # Node ID 2322e6c2a03297dabede871e6748a9c91febece6 # Parent b65c2f5d4d01254910676f3e5b5c836af9dcec53 8048604: Tests for strong crypto ciphers Summary: SQE test co-location effort Reviewed-by: valeriep diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/CICOChainingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/CICOChainingTest.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2007, 2015, 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.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.Arrays; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; + +/* + * @test + * @bug 8048604 + * @summary This test verifies the assertion "The chaining feature of + * Filter streams should be supported." for feature "CipherInputStream & + * CipherOutputStream" + * @run main CICOChainingTest + */ +public class CICOChainingTest { + /** + * Plain text length. + */ + private static final int PLAIN_TEXT_LENGTH = 200; + + public static void main(String argv[]) throws Exception { + CICOChainingTest test = new CICOChainingTest(); + test.chainTest(true); + test.chainTest(false); + } + + /** + * Chain CipherInputStream/CipherOutputStream with other stream, encrypt + * the text and decrypt it, recovered text is supposed to be same as + * original text. + * @param useInt true if read byte by byte false if read with buffer. + * @throws IOException any I/O operation failed. + */ + public void chainTest(boolean useInt) throws IOException { + byte[] plainText = TestUtilities.generateBytes(PLAIN_TEXT_LENGTH); + byte[] recoveredText = new byte[plainText.length]; + // Do initialization + try (MyNullCipherInputStream ciInput1 = new MyNullCipherInputStream( + new ByteArrayInputStream(plainText)); + PipedOutputStream piOut = new PipedOutputStream(); + MyNullCipherInputStream ciInput2 = new MyNullCipherInputStream( + new PipedInputStream(piOut)); + MyNullCipherOutputStream ciOut = new MyNullCipherOutputStream( + piOut);) { + if (useInt) { + int buffer = ciInput1.read(); + while (buffer != -1) { + piOut.write(buffer); + buffer = ciInput1.read(); + } + } else { + byte[] buffer = new byte[20]; + int len = ciInput1.read(buffer); + while (len != -1) { + ciOut.write(buffer, 0, len); + len = ciInput1.read(buffer); + } + } + ciOut.flush(); + piOut.flush(); + // Get the output + ciInput2.read(recoveredText); + if (ciInput2.available() > 0) { + throw new RuntimeException("Expected no data from ciInput2, but" + + " ciInput2.available() = " + ciInput2.available()); + } + } + // Verify output is same to input. + if (!Arrays.equals(plainText, recoveredText)) { + throw new RuntimeException("plainText:" + new String(plainText) + + " recoveredText:" + new String(recoveredText) + + " Test failed due to result compare fail"); + } + } +} + +class MyNullCipherInputStream extends CipherInputStream { + + public MyNullCipherInputStream(InputStream is) { + super(is); + } +} + +class MyNullCipherOutputStream extends CipherOutputStream { + + public MyNullCipherOutputStream(OutputStream os) { + super(os); + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/CICODESFuncTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/CICODESFuncTest.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2007, 2015, 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 static java.lang.System.out; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.SecretKey; +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.spec.IvParameterSpec; + +/* + * @test + * @bug 8048604 + * @summary to verify cipherInputStream and cipherInputStream cipher function + * @run main CICODESFuncTest + */ +public class CICODESFuncTest { + /** + * Algorithms name. + */ + private static final String[] ALGORITHMS = { "DES", "DESede", "Blowfish" }; + private static final String[] MODES = { "ECB", "CBC", "CFB", "CFB24", + "CFB32", "CFB40", "CFB72", "OFB", "OFB20", "OFB48", "OFB56", + "OFB64", "PCBC" }; + /** + * Padding mode. + */ + private static final String[] PADDINGS = { "noPadding", "pkcs5padding" }; + /** + * Plain text length. + */ + private static final int TEXT_LENGTH = 80; + /** + * Initialization vector length. + */ + private static final int IV_LENGTH = 8; + + public static void main(String[] args) throws Exception { + Provider provider = Security.getProvider("SunJCE"); + if (provider == null) { + throw new RuntimeException("SunJCE provider does not exist."); + } + for (String algorithm : ALGORITHMS) { + for (String mode : MODES) { + // We only test noPadding and pkcs5padding for CFB72, OFB20, ECB + // PCBC and CBC. Otherwise test noPadding only. + int padKinds = 1; + if (mode.equalsIgnoreCase("CFB72") + || mode.equalsIgnoreCase("OFB20") + || mode.equalsIgnoreCase("ECB") + || mode.equalsIgnoreCase("PCBC") + || mode.equalsIgnoreCase("CBC")) { + padKinds = PADDINGS.length; + } + // PKCS5padding is meaningful only for ECB, CBC, PCBC + for (int k = 0; k < padKinds; k++) { + for (ReadModel readMode : ReadModel.values()) { + runTest(provider, algorithm, mode, PADDINGS[k], readMode); + } + } + } + } + } + + private static void runTest(Provider p, String algo, String mo, String pad, + ReadModel whichRead) throws GeneralSecurityException, IOException { + // Do initialization + byte[] plainText = TestUtilities.generateBytes(TEXT_LENGTH); + byte[] iv = TestUtilities.generateBytes(IV_LENGTH); + AlgorithmParameterSpec aps = new IvParameterSpec(iv); + try { + KeyGenerator kg = KeyGenerator.getInstance(algo, p); + out.println(algo + "/" + mo + "/" + pad + "/" + whichRead); + SecretKey key = kg.generateKey(); + Cipher ci1 = Cipher.getInstance(algo + "/" + mo + "/" + pad, p); + if ("CFB72".equalsIgnoreCase(mo) || "OFB20".equalsIgnoreCase(mo)) { + throw new RuntimeException( + "NoSuchAlgorithmException not throw when mode" + + " is CFB72 or OFB20"); + } + Cipher ci2 = Cipher.getInstance(algo + "/" + mo + "/" + pad, p); + if ("ECB".equalsIgnoreCase(mo)) { + ci1.init(Cipher.ENCRYPT_MODE, key); + ci2.init(Cipher.DECRYPT_MODE, key); + } else { + ci1.init(Cipher.ENCRYPT_MODE, key, aps); + ci2.init(Cipher.DECRYPT_MODE, key, aps); + } + ByteArrayOutputStream baOutput = new ByteArrayOutputStream(); + try (CipherInputStream cInput + = new CipherInputStream( + new ByteArrayInputStream(plainText), ci1); + CipherOutputStream ciOutput + = new CipherOutputStream(baOutput, ci2);) { + // Read from the input and write to the output using 2 types + // of buffering : byte[] and int + whichRead.read(cInput, ciOutput, ci1, plainText.length); + } + // Verify input and output are same. + if (!Arrays.equals(plainText, baOutput.toByteArray())) { + throw new RuntimeException("Test failed due to compare fail "); + } + } catch (NoSuchAlgorithmException nsaEx) { + if ("CFB72".equalsIgnoreCase(mo) || "OFB20".equalsIgnoreCase(mo)) { + out.println("NoSuchAlgorithmException is expected for CFB72 and OFB20"); + } else { + throw new RuntimeException("Unexpected exception testing: " + + algo + "/" + mo + "/" + pad + "/" + whichRead, nsaEx); + } + } + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/CICOSkipTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/CICOSkipTest.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2007, 2015, 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 static java.lang.System.out; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidKeySpecException; +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; + +/* + * @test + * @bug 8048604 + * @summary This test verifies the assertion "The skip feature of Filter + * streams should be supported." for feature + * CipherInputStream and CipherOutputStream + */ +public class CICOSkipTest { + /** + * Block length. + */ + private static final int BLOCK = 50; + + /** + * Saving bytes length. + */ + private static final int SAVE = 45; + + /** + * Plain text length. + */ + private static final int PLAIN_TEXT_LENGTH = 800; + + /** + * Skip reading byte size. This should be same to BLOCK - SAVE + */ + private static final int DISCARD = BLOCK - SAVE; + + private static final String[] ALGOS = {"DES", "DESede", "Blowfish"}; + private static final String[] MODES = {"ECB", "CBC", "CFB", "CFB32", + "OFB", "OFB64", "PCBC"}; + private static final String[] PADDINGS = {"NoPadding", "Pkcs5Padding"}; + private static final String[] PBE_ALGOS = {"PBEWithMD5AndDES", + "PBEWithMD5AndDES/CBC/PKCS5Padding"}; + + public static void main(String[] args) throws Exception { + // how many kinds of padding mode such as PKCS5padding and NoPadding + for (String algo : ALGOS) { + for (String mode : MODES) { + int padKinds = 1; + if (mode.equalsIgnoreCase("ECB") + || mode.equalsIgnoreCase("PCBC") + || mode.equalsIgnoreCase("CBC")) { + padKinds = PADDINGS.length; + } + // PKCS5padding is meaningful only for ECB, CBC, PCBC + for (int k = 0; k < padKinds; k++) { + String info = algo + "/" + mode + "/" + PADDINGS[k]; + try { + CipherGenerator cg = new CipherGenerator(algo, mode, + PADDINGS[k]); + for (ReadMethod model : ReadMethod.values()) { + runTest(cg.getPair(), info, model); + } + } catch (LengthLimitException exp) { + // skip this if this key length is larger than what's + // configured in the jce jurisdiction policy files + out.println(exp.getMessage() + " is expected."); + } + } + } + } + for (String pbeAlgo : PBE_ALGOS) { + for (ReadMethod model : ReadMethod.values()) { + System.out.println("Testing Algorithm : " + pbeAlgo + + " ReadMethod : " + model); + runTest(new CipherGenerator(pbeAlgo).getPair(), pbeAlgo, model); + } + } + } + + private static void runTest(Cipher[] pair, String info, ReadMethod whichRead) + throws IOException { + byte[] plainText = TestUtilities.generateBytes(PLAIN_TEXT_LENGTH); + out.println("Testing: " + info + "/" + whichRead); + try (ByteArrayInputStream baInput = new ByteArrayInputStream(plainText); + CipherInputStream ciInput1 = new CipherInputStream(baInput, + pair[0]); + CipherInputStream ciInput2 = new CipherInputStream(ciInput1, + pair[1]);) { + // Skip 5 bytes after read 45 bytes and repeat until finish + // (Read from the input and write to the output using 2 types + // of buffering : byte[] and int) + // So output has size: + // (OVERALL/BLOCK)* SAVE = (800 / 50) * 45 = 720 bytes + int numOfBlocks = plainText.length / BLOCK; + + // Output buffer. + byte[] outputText = new byte[numOfBlocks * SAVE]; + int index = 0; + for (int i = 0; i < numOfBlocks; i++) { + index = whichRead.readByte(ciInput2, outputText, SAVE, index); + // If available is more than expected discard byte size. Skip + // discard bytes, otherwise try to read discard bytes by read. + if (ciInput2.available() >= DISCARD) { + ciInput2.skip(DISCARD); + } else { + for (int k = 0; k < DISCARD; k++) { + ciInput2.read(); + } + } + } + // Verify output is same as input + if (!TestUtilities + .equalsBlockPartial(plainText, outputText, BLOCK, SAVE)) { + throw new RuntimeException("Test failed with compare fail"); + } + } + } +} + +class CipherGenerator { + /** + * Initialization vector length. + */ + private static final int IV_LENGTH = 8; + + private static final String PASSWD = "Sesame!(@#$%^&*)"; + + private final Cipher[] pair = new Cipher[2]; + + // For DES/DESede ciphers + CipherGenerator(String algo, String mo, String pad) + throws NoSuchAlgorithmException, + InvalidAlgorithmParameterException, InvalidKeyException, + NoSuchPaddingException, SecurityException, LengthLimitException { + // Do initialization + KeyGenerator kg = KeyGenerator.getInstance(algo); + SecretKey key = kg.generateKey(); + if (key.getEncoded().length * 8 > Cipher.getMaxAllowedKeyLength(algo)) { + // skip this if this key length is larger than what's + // configured in the jce jurisdiction policy files + throw new LengthLimitException( + "Skip this test if key length is larger than what's" + + "configured in the jce jurisdiction policy files"); + } + AlgorithmParameterSpec aps = null; + if (!mo.equalsIgnoreCase("ECB")) { + byte[] iv = TestUtilities.generateBytes(IV_LENGTH); + aps = new IvParameterSpec(iv); + } + initCiphers(algo + "/" + mo + "/" + pad, key, aps); + } + + // For PBE ciphers + CipherGenerator(String algo) throws NoSuchAlgorithmException, + InvalidAlgorithmParameterException, InvalidKeyException, + NoSuchPaddingException, InvalidKeySpecException { + // Do initialization + byte[] salt = TestUtilities.generateBytes(IV_LENGTH); + int iterCnt = 6; + SecretKeyFactory skf = SecretKeyFactory.getInstance(algo.split("/")[0]); + SecretKey key = skf + .generateSecret(new PBEKeySpec(PASSWD.toCharArray())); + AlgorithmParameterSpec aps = new PBEParameterSpec(salt, iterCnt); + initCiphers(algo, key, aps); + } + + private void initCiphers(String algo, SecretKey key, + AlgorithmParameterSpec aps) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + Provider provider = Security.getProvider("SunJCE"); + if (provider == null) { + throw new RuntimeException("SunJCE provider does not exist."); + } + Cipher ci1 = Cipher.getInstance(algo, provider); + ci1.init(Cipher.ENCRYPT_MODE, key, aps); + pair[0] = ci1; + Cipher ci2 = Cipher.getInstance(algo, provider); + ci2.init(Cipher.DECRYPT_MODE, key, aps); + pair[1] = ci2; + } + + Cipher[] getPair() { + return pair; + } +} + +enum ReadMethod { + // read one byte at a time for save times + READ_ONE_BYTE { + @Override + int readByte(CipherInputStream ciIn2, byte[] outputText, int save, + int index) throws IOException { + for (int j = 0; j < save; j++, index++) { + int buffer0 = ciIn2.read(); + if (buffer0 != -1) { + outputText[index] = (byte) buffer0; + } else { + break; + } + } + return index; + } + }, + // read a chunk of save bytes if possible + READ_BLOCK { + @Override + int readByte(CipherInputStream ciIn2, byte[] outputText, int save, + int index) throws IOException { + int len1 = ciIn2.read(outputText, index, save); + out.println("Init: index=" + index + ",len=" + len1); + // read more until save bytes + index += len1; + int len2 = 0; + while (len1 != save && len2 != -1) { + len2 = ciIn2.read(outputText, index, save - len1); + out.println("Cont: index=" + index + ",len=" + len2); + len1 += len2; + index += len2; + } + return index; + } + }; + + abstract int readByte(CipherInputStream ciIn2, byte[] outputText, int save, + int index) throws IOException; +}; + +class LengthLimitException extends Exception { + + public LengthLimitException(String string) { + super(string); + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/AESPBEWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/AESPBEWrapper.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007, 2015, 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.AlgorithmParameters; +import java.security.GeneralSecurityException; +import java.security.Provider; +import java.security.Security; +import javax.crypto.SecretKey; +import javax.crypto.Cipher; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; + +/** + * Wrapper class to test a given AES-based PBE algorithm. + */ +public class AESPBEWrapper extends AbstractPBEWrapper { + /** + * the algorithm parameters. + */ + private AlgorithmParameters pbeParams; + + /** + * the encryption key. + */ + private final SecretKey key; + + /** + * The Wrapper constructor. Instantiate Cipher using the given AES-based PBE + * algorithm. + * + * @param algo AES-based PBE algorithm. + * @param passwd password phrase. + * @throws GeneralSecurityException all security exceptions are thrown. + */ + public AESPBEWrapper(PBEAlgorithm algo, String passwd) + throws GeneralSecurityException { + // salt and iteration count will be generated during encryption + super(algo, passwd, 0); + + // Generate secret key. We expect no mode and padding specified. + SecretKeyFactory skf = SecretKeyFactory.getInstance(algo.baseAlgo); + key = skf.generateSecret(new PBEKeySpec(passwd.toCharArray())); + } + + /** + * Initiate the Cipher object using given "mode". + * @return a cipher object. + * @throws GeneralSecurityException all security exceptions are thrown. + */ + @Override + protected Cipher initCipher(int mode) throws GeneralSecurityException { + Provider provider = Security.getProvider("SunJCE"); + if (provider == null) { + throw new RuntimeException("SunJCE provider does not exist."); + } + // get Cipher instance + Cipher ci = Cipher.getInstance(transformation, provider); + if (Cipher.ENCRYPT_MODE == mode) { + ci.init(Cipher.ENCRYPT_MODE, key); + pbeParams = ci.getParameters(); + } else { + ci.init(Cipher.DECRYPT_MODE, key, pbeParams); + } + return ci; + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/AbstractPBEWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/AbstractPBEWrapper.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2007, 2015, 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.GeneralSecurityException; +import javax.crypto.Cipher; + +/** + * PBEWrapper is an abstract class for all concrete PBE Cipher wrappers. + */ +public abstract class AbstractPBEWrapper { + /** + * Iteration count. + */ + public static final int DEFAULT_ITERATION = 1000; + + public static final String PBKDF2 = "PBKDF2"; + public static final String AES = "AES"; + public static final String DEFAULT = "default"; + + /** + * transformation the name of the transformation, e.g., + * DES/CBC/PKCS5Padding + */ + protected final String transformation; + + /** + * the standard name of the requested secret-key algorithm. + */ + protected final String baseAlgo; + + /** + * The contents of salt are copied to protect against subsequent + * modification. + */ + protected final byte[] salt; + + /** + * Password. + */ + protected final String password; + + /** + * PBEWrapper creator. + * + * @param algo PBE algorithm to test + * @param passwd a password phrase + * @return PBEWrapper in accordance to requested algo. + * @throws GeneralSecurityException all exceptions are thrown. + */ + public static AbstractPBEWrapper createWrapper(PBEAlgorithm algo, String passwd) + throws GeneralSecurityException { + switch (algo.type) { + case PBKDF2: + return new PBKDF2Wrapper(algo, passwd); + case AES: + return new AESPBEWrapper(algo, passwd); + default: + return new DefaultPBEWrapper(algo, passwd); + } + } + + /** + * PBEWrapper constructor. + * + * @param algo algorithm to wrap + * @param password password phrase + * @param saltSize salt size (defined in subclasses) + */ + protected AbstractPBEWrapper(PBEAlgorithm algo, String password, int saltSize) { + this.transformation = algo.getTransformation(); + this.baseAlgo = algo.baseAlgo; + this.salt = TestUtilities.generateBytes(saltSize); + this.password = password; + } + + /** + * Initialize Cipher object for the operation requested in the mode parameter. + * + * @param mode encryption or decryption + * @return a cipher initialize by mode. + * @throws GeneralSecurityException all security exceptions are thrown. + */ + protected abstract Cipher initCipher(int mode) throws GeneralSecurityException; +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICOPBEFuncTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICOPBEFuncTest.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2015, 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 8048604 + * @summary This test verifies the assertion "The encrypt/decrypt + * mechanism of cipher should perform correctly." for feature + * "CipherInputStream & CipherOutputStream". + * @library ../ + * @run main CICOPBEFuncTest + */ + +import java.util.Arrays; +import javax.crypto.Cipher; + +public class CICOPBEFuncTest { + + public static void main(String[] args) throws Exception { + for (PBEAlgorithm algorithm : PBEAlgorithm.values()) { + // int buffertin test + String algo = algorithm.baseAlgo.toUpperCase(); + if (!algo.contains("TRIPLEDES") && !algo.contains("AES_256") + || Cipher.getMaxAllowedKeyLength(algo) > 128) { + // skip this if this key length is larger than what's + // configured in the jce jurisdiction policy files + System.out.println("Testing " + algorithm.getTransformation()); + for (String type : Arrays.asList(CICO_PBE_Test.INT_BYTE_BUFFER, + CICO_PBE_Test.BYTE_ARR_BUFFER)) { + new CICO_PBE_RW_Test(algorithm) + .proceedTest(type); + new CICO_PBE_SKIP_Test(algorithm) + .proceedTest(type); + } + } + } + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_RW_Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_RW_Test.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2007, 2015, 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.ByteArrayOutputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; + +import javax.crypto.CipherOutputStream; + +/** + * CICO PBE Read/Write functional test. + * + * Verifies for the given PBE algorithm if the encrypt/decrypt mechanism is + * performed correctly for CipherInputStream and CipherOutputStream. + * + * Test scenario: + * 1. initializes plain text with random generated data. + * 2. for the given PBE algorithm instantiates encrypt and decrypt Ciphers. + * 3. instantiates CipherInputStream with the encrypt Cipher. + * 4. instantiates CipherOutputStream with the decrypt Cipher. + * 5. performs reading from the CipherInputStream (encryption data) and writing + * to the CipherOutputStream (decryption). As a result the output of the + * CipherOutputStream should be the same as an original plain text. + * 6. compares if the original plain text is the same as the output of the + * CipherOutputStream. + * + * The test implements 2 test cases in accordance with buffering type: + * 1. byte array buffering + * 2. int buffering + */ +public class CICO_PBE_RW_Test extends CICO_PBE_Test { + + public CICO_PBE_RW_Test(PBEAlgorithm pbeAlgo) + throws GeneralSecurityException { + super(pbeAlgo); + } + + /** + * The CICO PBE RW test specific part of the super.doTest(). Implements the + * scenario in accordance to the class description. + * @param type byteArrayBuffering or intByteBuffering + * @throws IOException any I/O operation failed. + * @throws GeneralSecurityException any security error. + */ + @Override + public void proceedTest(String type) throws IOException, + GeneralSecurityException { + ByteArrayOutputStream baOutput = new ByteArrayOutputStream(); + try (CipherOutputStream ciOutput = new CipherOutputStream(baOutput, + getDecryptCipher())) { + if (type.equals(CICO_PBE_Test.BYTE_ARR_BUFFER)) { + proceedTestUsingByteArrayBuffer(ciOutput); + } else { + proceedTestUsingIntBuffer(ciOutput); + } + ciOutput.flush(); + } + // Compare input and output + if (!TestUtilities.equalsBlock(plainText, baOutput.toByteArray(), TEXT_SIZE)) { + throw new RuntimeException("outputText not same with expectedText" + + " when test " + type); + } + } + + /** + * Implements byte array buffering type test case of the CICO PBE RW test. + * @param ciOutput output stream for data written. + * @throws java.io.IOException any I/O operation failed. + */ + public void proceedTestUsingByteArrayBuffer( + CipherOutputStream ciOutput) throws IOException { + byte[] buffer = new byte[TEXT_SIZE]; + int len = getCiInput().read(buffer); + while (len != -1) { + ciOutput.write(buffer, 0, len); + len = getCiInput().read(buffer); + } + } + + /** + * Implements int buffering type test case. + * @param ciOutput output stream for data written. + * @throws java.io.IOException any I/O operation failed. + */ + public void proceedTestUsingIntBuffer(CipherOutputStream ciOutput) + throws IOException { + int buffer = getCiInput().read(); + while (buffer != -1) { + ciOutput.write(buffer); + buffer = getCiInput().read(); + } + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_SKIP_Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_SKIP_Test.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2007, 2015, 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.IOException; +import java.security.GeneralSecurityException; +import javax.crypto.CipherInputStream; + +/** + * CICO PBE SKIP functional test. + * + * Verifies for the given PBE algorithm if the encrypt/decrypt mechanism is + * performed correctly for CipherInputStream when skip() method is used. + * + * Test scenario: + * 1. initializes plain text with random generated data with length TEXT_SIZE. + * 2. for the given PBE algorithm instantiates encrypt and decrypt Ciphers. + * 3. instantiates CipherInputStream 1 with the encrypt Cipher. + * 4. instantiates CipherInputStream 2 with the CipherInputStream 1 and decrypt + * Cipher. + * 5. the plain text is divided on TEXT_SIZE/BLOCK blocks. Reading from + * CipherInputStream 2 one block at time. The last BLOCK - SAVE bytes are + * skipping for each block. Therefor the plain text data go through + * CipherInputStream 1 (encrypting) and CipherInputStream 2 (decrypting). + * As a result the output should equal to the original text except DISCARD + * byte for each block are skipped. + * 6. get the standard output. + * 7. compares the expected standard output with the output of the + * CipherInputStream 2. If it is the same the test passed. Otherwise it + * failed. Any uncaught exceptions should be considered as an error. + * The test implements 2 test cases in accordance with a buffering type: + * 1. byte array buffering + * 2. int buffering + */ +public class CICO_PBE_SKIP_Test extends CICO_PBE_Test { + /** + * Block size. + */ + private static final int BLOCK = 50; + + /** + * Valid reading byte size. + */ + private static final int SAVE = 45; + + /** + * Skip reading byte size. This should be same to BLOCK - SAVE + */ + private static final int DISCARD = BLOCK - SAVE; + + /** + * Number of blocks. + */ + private static final int NUMBER_OF_BLOCKS = TEXT_SIZE / BLOCK; + + private final byte[] outputText; + /** + * CICO PBE Skip test constructor + * + * @param pbeAlgo the PBE algorithm to test. + * @throws java.security.GeneralSecurityException + */ + public CICO_PBE_SKIP_Test(PBEAlgorithm pbeAlgo) + throws GeneralSecurityException { + super(pbeAlgo); + outputText = new byte[NUMBER_OF_BLOCKS * SAVE]; + } + + /** + * Implements byte array buffering type test case of the CICO SKIP test. + * + * @param blockNum block number to read. + */ + private void proceedSkipTestUsingByteArrayBufferingType( + CipherInputStream ciIn2, int blockNum) throws IOException { + int index = blockNum * SAVE; + int len1 = ciIn2.read(outputText, index, SAVE); + // read more until SAVE bytes + index += len1; + int len2 = 0; + int totalRead = len1; + while (len1 != SAVE && len2 != -1) { + len2 = ciIn2.read(outputText, index, SAVE - len1); + len1 += len2; + index += len2; + totalRead += len2; + } + if (totalRead != SAVE) { + throw new RuntimeException("Read bytes number " + totalRead + + " does not equal to given number " + SAVE); + } + } + + /** + * Implements int buffering type test case of the CICO SKIP test. + * + * @param blockNum block number to read. + */ + private void proceedSkipTestUsingIntBufferingType(CipherInputStream ciIn2, + int blockNum) throws IOException { + int index = blockNum * SAVE; + int totalRead = 0; + for (int j = 0; j < SAVE; j++, index++) { + int buffer0 = ciIn2.read(); + if (buffer0 != -1) { + outputText[index] = (byte) buffer0; + totalRead++; + } else { + break; + } + } + if (totalRead != SAVE) { + throw new RuntimeException("Read bytes number " + totalRead + + " does not equal to given number " + SAVE); + } + } + + /** + * The CICO PBE SKIP test specific part of the super.doTest(). Implements + * the scenario in accordance to the class description. + * @throws java.io.IOException any I/O failed. + */ + @Override + public void proceedTest(String type) throws IOException { + System.out.println("Test type: " + type); + // init second input stream with decrypt Cipher + try (CipherInputStream ciIn2 = new CipherInputStream(getCiInput(), + getDecryptCipher())) { + for (int i = 0; i < NUMBER_OF_BLOCKS; i++) { + if (type.equals(CICO_PBE_Test.BYTE_ARR_BUFFER)) { + proceedSkipTestUsingByteArrayBufferingType(ciIn2, i); + } else { + proceedSkipTestUsingIntBufferingType(ciIn2, i); + } + if (ciIn2.available() >= DISCARD) { + ciIn2.skip(DISCARD); + } else { + for (int k = 0; k < DISCARD; k++) { + ciIn2.read(); + } + } + } + } + if (!TestUtilities.equalsBlockPartial(plainText, outputText, BLOCK, SAVE)) { + throw new RuntimeException("outputText not same with expectedText" + + " when test " + type); + } + } + +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_Test.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2007, 2015, 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.ByteArrayInputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; + +/** + * This is an abstract class for CipherInputStream/CipherOutputStream PBE + * functional tests. + */ +public abstract class CICO_PBE_Test { + /** + * Sample string for byte buffer. + */ + public static final String BYTE_ARR_BUFFER = "byteArrayBuffering"; + + /** + * Sample string for int buffer. + */ + public static final String INT_BYTE_BUFFER = "intByteBuffering"; + public static final String PASS_PHRASE = "Some password phrase!"; + + /** + * Text string size. + */ + public static final int TEXT_SIZE = 800; + + protected final byte[] plainText; + private final Cipher encryptCipher, decryptCipher; + + /** + * An CipherInputStream for reading cipher and plain text. + */ + private final CipherInputStream ciInput; + + /** + * Constructor by algorithm. + * @param pbeAlgo PBE algorithm to test. + * @throws GeneralSecurityException if any security error. + */ + public CICO_PBE_Test(PBEAlgorithm pbeAlgo) throws GeneralSecurityException { + // Do initialization of the plainText + plainText = TestUtilities.generateBytes(TEXT_SIZE); + // Do initialization of the ciphers + AbstractPBEWrapper pbeWrap = AbstractPBEWrapper.createWrapper(pbeAlgo, PASS_PHRASE); + encryptCipher = pbeWrap.initCipher(Cipher.ENCRYPT_MODE); + decryptCipher = pbeWrap.initCipher(Cipher.DECRYPT_MODE); + // init cipher input stream + ciInput = new CipherInputStream(new ByteArrayInputStream(plainText), + encryptCipher); + } + + protected byte[] getPlainText() { + return plainText; + } + + /** + * The body of the test. Should be defined in subclasses. + * @param type byteArrayBuffering or intByteBuffering + * @throws IOException I/O operation failed. + * @throws GeneralSecurityException all exceptions thrown. + */ + protected abstract void proceedTest(String type) + throws IOException, GeneralSecurityException; + + protected Cipher getEncryptCipher() { + return encryptCipher; + } + + public CipherInputStream getCiInput() { + return ciInput; + } + + public Cipher getDecryptCipher() { + return decryptCipher; + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CipherNCFuncTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CipherNCFuncTest.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2001, 2015, 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 8048604 + * @library /lib/testlibrary/ + * @summary This test verifies the assertion "There should be no transformation + * on the plaintext/ciphertext in encryption/decryption mechanism" for + * feature "NullCipher". + */ +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NullCipher; +import javax.crypto.ShortBufferException; +import jdk.testlibrary.RandomFactory; + +public class CipherNCFuncTest { + public static void main(String[] args) throws ShortBufferException, + IllegalBlockSizeException, BadPaddingException { + byte[] plainText = new byte[801]; + // Initialization + RandomFactory.getRandom().nextBytes(plainText); + Cipher ci = new NullCipher(); + // Encryption + byte[] cipherText = new byte[ci.getOutputSize(plainText.length)]; + int offset = ci.update(plainText, 0, plainText.length, cipherText, 0); + ci.doFinal(cipherText, offset); + // Decryption + byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)]; + int len = ci.doFinal(cipherText, 0, cipherText.length, recoveredText); + // Comparison + if (len != plainText.length || + !TestUtilities.equalsBlock(plainText, cipherText, len) || + !TestUtilities.equalsBlock(plainText, recoveredText, len)) { + throw new RuntimeException( + "Test failed because plainText not equal to cipherText and revoveredText"); + } + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/DefaultPBEWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/DefaultPBEWrapper.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2007, 2015, 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.GeneralSecurityException; +import java.security.Provider; +import java.security.Security; +import javax.crypto.SecretKey; +import javax.crypto.Cipher; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; + +/** + * Default wrapper for a password based encryption Cipher. + */ + +public class DefaultPBEWrapper extends AbstractPBEWrapper { + /** + * Define default SALT size as 8. + */ + private static final int PBE_SALT_SIZE = 8; + + /** + * Default PBE wrapper constructor. + * + * @param algo PGE algorithm to wrap. + * @param passwd password phrase + */ + public DefaultPBEWrapper(PBEAlgorithm algo, String passwd) { + super(algo, passwd, PBE_SALT_SIZE); + } + + /** + * Instantiate Cipher for the PBE algorithm. + * + * @param mode Cipher mode: encrypt or decrypt. + * @return Cipher in accordance to the PBE algorithm + * @throws java.security.GeneralSecurityException + */ + @Override + protected Cipher initCipher(int mode) throws GeneralSecurityException { + Provider provider = Security.getProvider("SunJCE"); + if (provider == null) { + throw new RuntimeException("SunJCE provider does not exist."); + } + SecretKey key = SecretKeyFactory.getInstance(baseAlgo) + .generateSecret(new PBEKeySpec(password.toCharArray())); + Cipher ci = Cipher.getInstance(transformation, provider); + ci.init(mode, key, new PBEParameterSpec(salt, DEFAULT_ITERATION)); + return ci; + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/PBEAlgorithm.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/PBEAlgorithm.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007, 2015, 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.util.StringJoiner; + +public enum PBEAlgorithm { + MD5_DES("PBEWithMD5ANDdes", "", "", AbstractPBEWrapper.DEFAULT), + MD5_DES_CBC_PKCS5("PBEWithMD5AndDES", "CBC", "PKCS5Padding", + AbstractPBEWrapper.DEFAULT), + MD5_TRIPLEDES("PBEWithMD5ANDtripledes", "", "", AbstractPBEWrapper.DEFAULT), + MD5_TRIPLEDES_CBC_PKCS5("PBEWithMD5AndTRIPLEDES", "CBC", "PKCS5Padding", + AbstractPBEWrapper.DEFAULT), + SHA1_DESEDE("PBEwithSHA1AndDESede", "", "", AbstractPBEWrapper.DEFAULT), + SHA1_DESEDE_CBC_PKCS5("PBEwithSHA1AndDESede", "CBC", "PKCS5Padding", + AbstractPBEWrapper.DEFAULT), + SHA1_RC2_40("PBEwithSHA1AndRC2_40", "", "", AbstractPBEWrapper.DEFAULT), + SHA1_RC2_40_PKCS5("PBEwithSHA1Andrc2_40", "CBC", "PKCS5Padding", + AbstractPBEWrapper.DEFAULT), + SHA1_RC2_128("PBEWithSHA1AndRC2_128", "", "", AbstractPBEWrapper.DEFAULT), + SHA1_RC2_128_PKCS5("PBEWithSHA1andRC2_128", "CBC", "PKCS5Padding", + AbstractPBEWrapper.DEFAULT), + SHA1_RC4_40("PBEWithSHA1AndRC4_40", "", "", AbstractPBEWrapper.DEFAULT), + SHA1_RC4_40_ECB_NOPADDING("PBEWithsha1AndRC4_40", "ECB", "NoPadding", + AbstractPBEWrapper.DEFAULT), + SHA1_RC4_128("PBEWithSHA1AndRC4_128", "", "", AbstractPBEWrapper.DEFAULT), + SHA1_RC4_128_ECB_NOPADDING("pbeWithSHA1AndRC4_128", "ECB", "NoPadding", + AbstractPBEWrapper.DEFAULT), + HMAC_SHA1_AES_128("PBEWithHmacSHA1AndAES_128", "", "", AbstractPBEWrapper.AES), + HMAC_SHA224_AES_128("PBEWithHmacSHA224AndAES_128", "", "", AbstractPBEWrapper.AES), + HMAC_SHA256_AES_128("PBEWithHmacSHA256AndAES_128", "", "", AbstractPBEWrapper.AES), + HMAC_SHA384_AES_128("PBEWithHmacSHA384AndAES_128", "", "", AbstractPBEWrapper.AES), + HMAC_SHA512_AES_128("PBEWithHmacSHA512AndAES_128", "", "", AbstractPBEWrapper.AES), + HMAC_SHA1_AES_256("PBEWithHmacSHA1AndAES_256", "", "", AbstractPBEWrapper.AES), + HMAC_SHA224_AES_256("PBEWithHmacSHA224AndAES_256", "", "", AbstractPBEWrapper.AES), + HMAC_SHA256_AES_256("PBEWithHmacSHA256AndAES_256", "", "", AbstractPBEWrapper.AES), + HMAC_SHA384_AES_256("PBEWithHmacSHA384AndAES_256", "", "", AbstractPBEWrapper.AES), + HMAC_SHA512_AES_256("PBEWithHmacSHA512AndAES_256", "", "", AbstractPBEWrapper.AES), + PBKDF_HMAC_SHA1("PBKDF2WithHmacSHA1", "", "", AbstractPBEWrapper.PBKDF2), + PBKDF_HMAC_SHA224("PBKDF2WithHmacSHA224", "", "", AbstractPBEWrapper.PBKDF2), + PBKDF_HMAC_SHA256("PBKDF2WithHmacSHA256", "", "", AbstractPBEWrapper.PBKDF2), + PBKDF_HMAC_SHA384("PBKDF2WithHmacSHA384", "", "", AbstractPBEWrapper.PBKDF2), + PBKDF_HMAC_SHA512("PBKDF2WithHmacSHA512", "", "", AbstractPBEWrapper.PBKDF2); + final String baseAlgo; + final String mode; + final String padding; + final String type; + + PBEAlgorithm(String alg, String mode, String padding, String type) { + this.baseAlgo = alg; + this.mode = mode; + this.padding = padding; + this.type = type; + } + + public String getTransformation() { + StringJoiner sj = new StringJoiner("/"); + sj.add(baseAlgo); + if (!mode.equals("")) { + sj.add(this.mode); + } + if (!padding.equals("")) { + sj.add(this.padding); + } + return sj.toString(); + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/PBEFunc/PBKDF2Wrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/PBKDF2Wrapper.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2015, 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.GeneralSecurityException; +import java.security.Provider; +import java.security.Security; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +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. + */ +public class PBKDF2Wrapper extends AbstractPBEWrapper { + /** + * Default salt size. + */ + public static final int PBKDF2_SALT_SIZE = 64; + + /** + * Default key length. + */ + public static final int PKDF2_DEFAULT_KEY_LEN = 128; + + /** + * Default transformation. + */ + public static final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding"; + + /** + * Algorithm name. + */ + public static final String KEY_ALGORITHM = "AES"; + + /** + * Initialization vector length. + */ + private static final int IV_LENGTH = 16; + + /** + * The buffer with the IV. + */ + private final byte[] iv; + + /** + * PBKDF2Wrapper constructor. Instantiate Cipher using + * "AES/CBC/PKCS5Padding" transformation. Generate a secret key using PKDF2 + * algorithms given in the "algo" parameter. + * + * @param algo AES-based PBE algorithm. + * @param passwd password phrase. + * @throws GeneralSecurityException all security exceptions are thrown. + */ + public PBKDF2Wrapper(PBEAlgorithm algo, String passwd) + throws GeneralSecurityException { + super(algo, passwd, PBKDF2_SALT_SIZE); + iv = TestUtilities.generateBytes(IV_LENGTH); + } + + /** + * Initiate the Cipher object for PBKDF2 algorithm using given "mode". + * + * @param mode Cipher mode: encrypt or decrypt + * @return Cipher object for PBKDF2 algorithm + * @throws GeneralSecurityException all security exceptions are thrown. + */ + @Override + protected Cipher initCipher(int mode) throws GeneralSecurityException { + Provider provider = Security.getProvider("SunJCE"); + if (provider == null) { + throw new RuntimeException("SunJCE provider does not exist."); + } + // Generate secret key + PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), + salt, DEFAULT_ITERATION, PKDF2_DEFAULT_KEY_LEN); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(baseAlgo); + SecretKey key = keyFactory.generateSecret(pbeKeySpec); + + // get Cipher instance + Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION, provider); + cipher.init(mode, + new SecretKeySpec(key.getEncoded(),KEY_ALGORITHM), + new IvParameterSpec(iv)); + return cipher; + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/ReadModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/ReadModel.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2007, 2015, 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.IOException; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; + +/** + * ReadModel provides different way to test + * CipherInputStream.read()/read(byte[])/read(byte[], int, int) and + * CipherOutputStream.write(int)/write(byte[], int, int)/read(byte[]) API + */ +enum ReadModel { + READ_BYTE { + @Override + public void read(CipherInputStream cInput, CipherOutputStream ciOutput, + Cipher ciIn, int inputLen) throws IOException { + int buffer0 = cInput.read(); + while (buffer0 != -1) { + ciOutput.write(buffer0); + buffer0 = cInput.read(); + } + } + }, + READ_BUFFER { + @Override + public void read(CipherInputStream cInput, CipherOutputStream ciOutput, + Cipher ciIn, int inputLen) throws IOException { + byte[] buffer1 = new byte[20]; + int len1; + while ((len1 = cInput.read(buffer1)) != -1) { + ciOutput.write(buffer1, 0, len1); + } + + } + }, + READ_BUFFER_OFFSET { + @Override + public void read(CipherInputStream cInput, CipherOutputStream ciOutput, + Cipher ciIn, int inputLen) throws IOException { + byte[] buffer2 = new byte[ciIn.getOutputSize(inputLen)]; + int offset2 = 0; + int len2 = 0; + while (len2 != -1) { + len2 = cInput.read(buffer2, offset2, buffer2.length - offset2); + offset2 += len2; + } + ciOutput.write(buffer2); + + } + }; + + abstract public void read(CipherInputStream cInput, + CipherOutputStream ciOutput, Cipher ciIn, int inputLen) + throws IOException; +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/CICO/TestUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/CICO/TestUtilities.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2007, 2015, 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. + */ + +/* + * utility class + */ + +public class TestUtilities { + public static boolean equalsBlock(byte[] b1, byte[] b2, int len) { + for (int i = 0; i < len; i++) { + if (b1[i] != b2[i]) { + System.err.println("b1[" + i + "] : " + b1[i] + + " b2[" + i + "] : " + b2[i]); + return false; + } + } + return true; + } + + public static boolean equals(byte[] b1, byte[] b2) { + if (b2.length != b1.length) { + System.err.println("b1.length = " + b1.length + + " b2.length = " + b2.length ); + return false; + } + return equalsBlock(b1, b2, b1.length); + } + + /** + * Verify b1's partial part is same as b2. compares b1 and b2 by chopping up + * b1 into blocks of b1BKSize and b2 into blocks of b2BKSize, and then + * compare the first b2BKSize bytes of each block, return true if they equal + * , otherwise return false. + * @param b1 byte array to be compared. + * @param b2 saved byte array. + * @param b1BKSize b1's block size. + * @param b2BKSize b2's block size. + * @return true is same. false otherwise. + */ + public static boolean equalsBlockPartial(byte[] b1, byte[] b2, int b1BKSize, + int b2BKSize) { + int numOfBlock = b1.length / b1BKSize; + for (int b = 0; b < numOfBlock; b++) { + for (int i = 0; i < b2BKSize; i++) { + int j1 = b * b1BKSize + i; + int j2 = b * b2BKSize + i; + if (b1[j1] != b2[j2]) { + System.err.println("Compare failed at b1[" + j1 + "]:" + + b1[j1] + " b2[" + j2 + "]:" + b2[j2]); + return false; + } + } + } + return true; + } + + /** + * Generate a byte block by given length. The content of byte block + * is determined by the index. + * @param length length of byte array + * @return a byte array + */ + public static byte[] generateBytes(int length) { + byte[] bytes = new byte[length]; + for (int i = 0; i < length; i++) { + bytes[i] = (byte) (i & 0xff); + } + return bytes; + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/com/sun/crypto/provider/Cipher/DES/TextPKCS5PaddingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/DES/TextPKCS5PaddingTest.java Wed Sep 23 21:28:14 2015 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001, 2015, 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 8048604 + * @summary This test checks boundary conditions for testing + * ShortBufferException. + */ +import static java.lang.System.out; + +import java.security.AlgorithmParameters; +import java.security.Provider; +import java.security.Security; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +public class TextPKCS5PaddingTest { + /** + * Test plain text. + */ + private static final byte[] PLAIN_TEXT = { + 0b10001, 0b10001, 0b10001, 0b10001, + 0b10001, 0b10001, 0b11, 0b11 + }; + + public static void main(String[] args) throws Exception { + Provider provider = Security.getProvider("SunJCE"); + if (provider == null) { + throw new RuntimeException("SunJCE provider not exist"); + } + // generate no-padding cipher with secret key + Cipher c = Cipher.getInstance("DES/CBC/NoPadding", provider); + KeyGenerator kgen = KeyGenerator.getInstance("DES", provider); + SecretKey skey = kgen.generateKey(); + // this is the improperly padded plaintext + + c.init(Cipher.ENCRYPT_MODE, skey); + // encrypt plaintext + byte[] cipher = c.doFinal(PLAIN_TEXT); + AlgorithmParameters params = c.getParameters(); + // generate cipher that enforces PKCS5 padding + c = Cipher.getInstance("DES/CBC/PKCS5Padding", provider); + c.init(Cipher.DECRYPT_MODE, skey, params); + try { + c.doFinal(cipher); + throw new RuntimeException( + "ERROR: Expected BadPaddingException not thrown"); + } catch (BadPaddingException expected) { + out.println("Expected BadPaddingException thrown"); + } + + } +} diff -r b65c2f5d4d01 -r 2322e6c2a032 jdk/test/javax/crypto/KeyGenerator/TestKGParity.java --- a/jdk/test/javax/crypto/KeyGenerator/TestKGParity.java Wed Sep 23 14:14:14 2015 -0700 +++ b/jdk/test/javax/crypto/KeyGenerator/TestKGParity.java Wed Sep 23 21:28:14 2015 +0000 @@ -33,7 +33,7 @@ /* * @test * @bug 8048607 - * @compile ../../../com/sun/crypto/provider/Cipher/DES/TestUtility.java + * @library ../../../com/sun/crypto/provider/Cipher/DES/TestUtility.java * @summary Test key generation of DES and DESEDE * @key randomness */