diff --git a/src/share/classes/sun/security/pkcs11/P11Cipher.java b/src/share/classes/sun/security/pkcs11/P11Cipher.java index 1ea39e799d1ad9c786c5befcd151ee92e321bf3f..5568887a5f61a40f80c1774a5fbf7e2a49c7b8b4 100644 --- a/src/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/src/share/classes/sun/security/pkcs11/P11Cipher.java @@ -74,7 +74,7 @@ final class P11Cipher extends CipherSpi { // DEC: return the length of trailing padding bytes given the specified // padded data int unpad(byte[] paddedData, int len) - throws BadPaddingException; + throws BadPaddingException, IllegalBlockSizeException; } private static class PKCS5Padding implements Padding { @@ -96,9 +96,10 @@ final class P11Cipher extends CipherSpi { } public int unpad(byte[] paddedData, int len) - throws BadPaddingException { - if (len < 1 || len > paddedData.length) { - throw new BadPaddingException("Invalid pad array length!"); + throws BadPaddingException, IllegalBlockSizeException { + if ((len < 1) || (len % blockSize != 0)) { + throw new IllegalBlockSizeException + ("Input length must be multiples of " + blockSize); } byte padValue = paddedData[len - 1]; if (padValue < 1 || padValue > blockSize) { diff --git a/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java b/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java new file mode 100644 index 0000000000000000000000000000000000000000..f0721daa2e5355600f25998b83dabeb849c4c4b0 --- /dev/null +++ b/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2010, 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 6687725 + * @summary Test internal PKCS5Padding impl with various error conditions. + * @author Valerie Peng + * @library .. + */ +import java.io.*; +import java.nio.*; +import java.util.*; + +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.*; +import javax.crypto.spec.IvParameterSpec; + +public class TestPKCS5PaddingError extends PKCS11Test { + private static class CI { // class for holding Cipher Information + String transformation; + String keyAlgo; + + CI(String transformation, String keyAlgo) { + this.transformation = transformation; + this.keyAlgo = keyAlgo; + } + } + + private static final CI[] TEST_LIST = { + // algorithms which use the native padding impl + new CI("DES/CBC/PKCS5Padding", "DES"), + new CI("DESede/CBC/PKCS5Padding", "DESede"), + new CI("AES/CBC/PKCS5Padding", "AES"), + // algorithms which use SunPKCS11's own padding impl + new CI("DES/ECB/PKCS5Padding", "DES"), + new CI("DESede/ECB/PKCS5Padding", "DESede"), + new CI("AES/ECB/PKCS5Padding", "AES"), + }; + + private static StringBuffer debugBuf = new StringBuffer(); + + public void main(Provider p) throws Exception { + boolean status = true; + Random random = new Random(); + + try { + byte[] plainText = new byte[200]; + + for (int i = 0; i < TEST_LIST.length; i++) { + CI currTest = TEST_LIST[i]; + System.out.println("===" + currTest.transformation + "==="); + try { + KeyGenerator kg = + KeyGenerator.getInstance(currTest.keyAlgo, p); + SecretKey key = kg.generateKey(); + Cipher c1 = Cipher.getInstance(currTest.transformation, + "SunJCE"); + c1.init(Cipher.ENCRYPT_MODE, key); + byte[] cipherText = c1.doFinal(plainText); + AlgorithmParameters params = c1.getParameters(); + Cipher c2 = Cipher.getInstance(currTest.transformation, p); + c2.init(Cipher.DECRYPT_MODE, key, params); + + // 1st test: wrong output length + // NOTE: Skip NSS since it reports CKR_DEVICE_ERROR when + // the data passed to its EncryptUpdate/DecryptUpdate is + // not multiple of blocks + if (!p.getName().equals("SunPKCS11-NSS")) { + try { + System.out.println("Testing with wrong cipherText length"); + c2.doFinal(cipherText, 0, cipherText.length - 2); + } catch (IllegalBlockSizeException ibe) { + // expected + } catch (Exception ex) { + System.out.println("Error: Unexpected Ex " + ex); + ex.printStackTrace(); + } + } + // 2nd test: wrong padding value + try { + System.out.println("Testing with wrong padding bytes"); + cipherText[cipherText.length - 1]++; + c2.doFinal(cipherText); + } catch (BadPaddingException bpe) { + // expected + } catch (Exception ex) { + System.out.println("Error: Unexpected Ex " + ex); + ex.printStackTrace(); + } + System.out.println("DONE"); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skipping unsupported algorithm: " + + nsae); + } + } + } catch (Exception ex) { + // print out debug info when exception is encountered + if (debugBuf != null) { + System.out.println(debugBuf.toString()); + debugBuf = new StringBuffer(); + } + throw ex; + } + } + + public static void main(String[] args) throws Exception { + main(new TestPKCS5PaddingError()); + } +}