# HG changeset patch # User valeriep # Date 1299536077 28800 # Node ID f5d3509ad92b7d3792846f69c91c9f397f53b54c # Parent a5d07d83b4b1dafd653958522aea9d457b7627cf 6994008: PKCS11 should support "RSA" and "RSA/ECB/NoPadding" ciphers Summary: Add support for RSA_X_509 mechanism and aliasing of "RSA" to "RSA/ECB/PKCS1Padding". Reviewed-by: wetmore diff -r a5d07d83b4b1 -r f5d3509ad92b jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java --- a/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java Mon Mar 07 11:36:37 2011 -0800 +++ b/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java Mon Mar 07 14:14:37 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -62,6 +62,11 @@ // mode constant for public key decryption (verifying) private final static int MODE_VERIFY = 4; + // padding type constant for NoPadding + private final static int PAD_NONE = 1; + // padding type constant for PKCS1Padding + private final static int PAD_PKCS1 = 2; + // token instance private final Token token; @@ -77,6 +82,9 @@ // mode, one of MODE_* above private int mode; + // padding, one of PAD_* above + private int padType; + private byte[] buffer; private int bufOfs; @@ -113,8 +121,10 @@ protected void engineSetPadding(String padding) throws NoSuchPaddingException { String lowerPadding = padding.toLowerCase(Locale.ENGLISH); - if (lowerPadding.equals("pkcs1Padding")) { - // empty + if (lowerPadding.equals("pkcs1padding")) { + padType = PAD_PKCS1; + } else if (lowerPadding.equals("nopadding")) { + padType = PAD_NONE; } else { throw new NoSuchPaddingException("Unsupported padding " + padding); } @@ -209,7 +219,8 @@ int n = (p11Key.keyLength() + 7) >> 3; outputSize = n; buffer = new byte[n]; - maxInputSize = encrypt ? (n - PKCS1_MIN_PADDING_LENGTH) : n; + maxInputSize = ((padType == PAD_PKCS1 && encrypt) ? + (n - PKCS1_MIN_PADDING_LENGTH) : n); try { initialize(); } catch (PKCS11Exception e) { diff -r a5d07d83b4b1 -r f5d3509ad92b jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java --- a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java Mon Mar 07 11:36:37 2011 -0800 +++ b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java Mon Mar 07 14:14:37 2011 -0800 @@ -627,8 +627,10 @@ m(CKM_BLOWFISH_CBC)); // XXX RSA_X_509, RSA_OAEP not yet supported - d(CIP, "RSA/ECB/PKCS1Padding", P11RSACipher, + d(CIP, "RSA/ECB/PKCS1Padding", P11RSACipher, s("RSA"), m(CKM_RSA_PKCS)); + d(CIP, "RSA/ECB/NoPadding", P11RSACipher, + m(CKM_RSA_X_509)); d(SIG, "RawDSA", P11Signature, s("NONEwithDSA"), m(CKM_DSA)); diff -r a5d07d83b4b1 -r f5d3509ad92b jdk/test/sun/security/pkcs11/Cipher/TestRSACipher.java --- a/jdk/test/sun/security/pkcs11/Cipher/TestRSACipher.java Mon Mar 07 11:36:37 2011 -0800 +++ b/jdk/test/sun/security/pkcs11/Cipher/TestRSACipher.java Mon Mar 07 14:14:37 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -23,7 +23,7 @@ /** * @test - * @bug 4898468 + * @bug 4898468 6994008 * @summary basic test for RSA cipher * @author Andreas Sterbenz * @library .. @@ -38,9 +38,12 @@ public class TestRSACipher extends PKCS11Test { + private static final String[] RSA_ALGOS = + { "RSA/ECB/PKCS1Padding", "RSA" }; + public void main(Provider p) throws Exception { try { - Cipher.getInstance("RSA/ECB/PKCS1Padding", p); + Cipher.getInstance(RSA_ALGOS[0], p); } catch (GeneralSecurityException e) { System.out.println("Not supported by provider, skipping"); return; @@ -55,57 +58,58 @@ b = new byte[16]; random.nextBytes(b); - Cipher c1 = Cipher.getInstance("RSA/ECB/PKCS1Padding", p); - Cipher c2 = Cipher.getInstance("RSA/ECB/PKCS1Padding", "SunJCE"); + for (String rsaAlgo: RSA_ALGOS) { + Cipher c1 = Cipher.getInstance(rsaAlgo, p); + Cipher c2 = Cipher.getInstance(rsaAlgo, "SunJCE"); - c1.init(Cipher.ENCRYPT_MODE, publicKey); - e = c1.doFinal(b); - c1.init(Cipher.DECRYPT_MODE, privateKey); - d = c1.doFinal(e); - match(b, d); - c2.init(Cipher.DECRYPT_MODE, privateKey); - d = c2.doFinal(e); - match(b, d); + c1.init(Cipher.ENCRYPT_MODE, publicKey); + e = c1.doFinal(b); + c1.init(Cipher.DECRYPT_MODE, privateKey); + d = c1.doFinal(e); + match(b, d); + c2.init(Cipher.DECRYPT_MODE, privateKey); + d = c2.doFinal(e); + match(b, d); - // invalid data - c1.init(Cipher.DECRYPT_MODE, publicKey); - try { - d = c1.doFinal(e); - throw new Exception("completed call"); - } catch (BadPaddingException ee) { - ee.printStackTrace(); - } + // invalid data + c1.init(Cipher.DECRYPT_MODE, publicKey); + try { + d = c1.doFinal(e); + throw new Exception("completed call"); + } catch (BadPaddingException ee) { + ee.printStackTrace(); + } - c1.init(Cipher.ENCRYPT_MODE, privateKey); - e = c1.doFinal(b); - c1.init(Cipher.DECRYPT_MODE, publicKey); - d = c1.doFinal(e); - match(b, d); - c2.init(Cipher.DECRYPT_MODE, publicKey); - d = c2.doFinal(e); - match(b, d); + c1.init(Cipher.ENCRYPT_MODE, privateKey); + e = c1.doFinal(b); + c1.init(Cipher.DECRYPT_MODE, publicKey); + d = c1.doFinal(e); + match(b, d); + c2.init(Cipher.DECRYPT_MODE, publicKey); + d = c2.doFinal(e); + match(b, d); - // reinit tests - c1.init(Cipher.ENCRYPT_MODE, privateKey); - c1.init(Cipher.ENCRYPT_MODE, privateKey); - e = c1.doFinal(b); - e = c1.doFinal(b); - c1.update(b); - c1.update(b); - c1.init(Cipher.ENCRYPT_MODE, privateKey); - e = c1.doFinal(); - e = c1.doFinal(); - c1.update(b); - e = c1.doFinal(); + // reinit tests + c1.init(Cipher.ENCRYPT_MODE, privateKey); + c1.init(Cipher.ENCRYPT_MODE, privateKey); + e = c1.doFinal(b); + e = c1.doFinal(b); + c1.update(b); + c1.update(b); + c1.init(Cipher.ENCRYPT_MODE, privateKey); + e = c1.doFinal(); + e = c1.doFinal(); + c1.update(b); + e = c1.doFinal(); - c1.update(new byte[256]); - try { - e = c1.doFinal(); - throw new Exception("completed call"); - } catch (IllegalBlockSizeException ee) { - System.out.println(ee); + c1.update(new byte[256]); + try { + e = c1.doFinal(); + throw new Exception("completed call"); + } catch (IllegalBlockSizeException ee) { + System.out.println(ee); + } } - } private static void match(byte[] b1, byte[] b2) throws Exception { diff -r a5d07d83b4b1 -r f5d3509ad92b jdk/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java --- a/jdk/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java Mon Mar 07 11:36:37 2011 -0800 +++ b/jdk/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java Mon Mar 07 14:14:37 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -23,7 +23,7 @@ /** * @test - * @bug 6572331 + * @bug 6572331 6994008 * @summary basic test for RSA cipher key wrapping functionality * @author Valerie Peng * @library .. @@ -38,47 +38,48 @@ public class TestRSACipherWrap extends PKCS11Test { - private static final String RSA_ALGO = "RSA/ECB/PKCS1Padding"; + private static final String[] RSA_ALGOS = + { "RSA/ECB/PKCS1Padding", "RSA" }; public void main(Provider p) throws Exception { try { - Cipher.getInstance(RSA_ALGO, p); + Cipher.getInstance(RSA_ALGOS[0], p); } catch (GeneralSecurityException e) { - System.out.println("Not supported by provider, skipping"); + System.out.println(RSA_ALGOS[0] + " unsupported, skipping"); return; } KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", p); kpg.initialize(1024); KeyPair kp = kpg.generateKeyPair(); - PublicKey publicKey = kp.getPublic(); - PrivateKey privateKey = kp.getPrivate(); - Cipher cipherPKCS11 = Cipher.getInstance(RSA_ALGO, p); - Cipher cipherJce = Cipher.getInstance(RSA_ALGO, "SunJCE"); + for (String rsaAlgo: RSA_ALGOS) { + Cipher cipherPKCS11 = Cipher.getInstance(rsaAlgo, p); + Cipher cipherJce = Cipher.getInstance(rsaAlgo, "SunJCE"); - String algos[] = {"AES", "RC2", "Blowfish"}; - int keySizes[] = {128, 256}; + String algos[] = {"AES", "RC2", "Blowfish"}; + int keySizes[] = {128, 256}; - for (int j = 0; j < algos.length; j++) { - String algorithm = algos[j]; - KeyGenerator keygen = + for (int j = 0; j < algos.length; j++) { + String algorithm = algos[j]; + KeyGenerator keygen = KeyGenerator.getInstance(algorithm); - for (int i = 0; i < keySizes.length; i++) { - SecretKey secretKey = null; - System.out.print("Generate " + keySizes[i] + "-bit " + + for (int i = 0; i < keySizes.length; i++) { + SecretKey secretKey = null; + System.out.print("Generate " + keySizes[i] + "-bit " + algorithm + " key using "); - try { - keygen.init(keySizes[i]); - secretKey = keygen.generateKey(); - System.out.println(keygen.getProvider().getName()); - } catch (InvalidParameterException ipe) { - secretKey = new SecretKeySpec(new byte[32], algorithm); - System.out.println("SecretKeySpec class"); + try { + keygen.init(keySizes[i]); + secretKey = keygen.generateKey(); + System.out.println(keygen.getProvider().getName()); + } catch (InvalidParameterException ipe) { + secretKey = new SecretKeySpec(new byte[32], algorithm); + System.out.println("SecretKeySpec class"); + } + test(kp, secretKey, cipherPKCS11, cipherJce); + test(kp, secretKey, cipherPKCS11, cipherPKCS11); + test(kp, secretKey, cipherJce, cipherPKCS11); } - test(kp, secretKey, cipherPKCS11, cipherJce); - test(kp, secretKey, cipherPKCS11, cipherPKCS11); - test(kp, secretKey, cipherJce, cipherPKCS11); } } } diff -r a5d07d83b4b1 -r f5d3509ad92b jdk/test/sun/security/pkcs11/Cipher/TestRawRSACipher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/pkcs11/Cipher/TestRawRSACipher.java Mon Mar 07 14:14:37 2011 -0800 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2011, 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 6994008 + * @summary basic test for RSA/ECB/NoPadding cipher + * @author Valerie Peng + * @library .. + */ + +import javax.crypto.*; +import java.io.*; +import javax.crypto.spec.SecretKeySpec; +import java.security.*; +import java.util.*; + +public class TestRawRSACipher extends PKCS11Test { + + public void main(Provider p) throws Exception { + try { + Cipher.getInstance("RSA/ECB/NoPadding", p); + } catch (GeneralSecurityException e) { + System.out.println("Not supported by provider, skipping"); + return; + } + + final int KEY_LEN = 1024; + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", p); + kpGen.initialize(KEY_LEN); + KeyPair kp = kpGen.generateKeyPair(); + Random random = new Random(); + byte[] plainText, cipherText, recoveredText; + plainText = new byte[KEY_LEN/8]; + random.nextBytes(plainText); + plainText[0] = 0; // to ensure that it's less than modulus + + Cipher c1 = Cipher.getInstance("RSA/ECB/NoPadding", p); + Cipher c2 = Cipher.getInstance("RSA/ECB/NoPadding", "SunJCE"); + + c1.init(Cipher.ENCRYPT_MODE, kp.getPublic()); + c2.init(Cipher.DECRYPT_MODE, kp.getPrivate()); + + cipherText = c1.doFinal(plainText); + recoveredText = c2.doFinal(cipherText); + if (!Arrays.equals(plainText, recoveredText)) { + throw new RuntimeException("E/D Test against SunJCE Failed!"); + } + + c2.init(Cipher.ENCRYPT_MODE, kp.getPublic()); + c1.init(Cipher.DECRYPT_MODE, kp.getPrivate()); + cipherText = c2.doFinal(plainText); + recoveredText = c1.doFinal(cipherText); + if (!Arrays.equals(plainText, recoveredText)) { + throw new RuntimeException("D/E Test against SunJCE Failed!"); + } + + System.out.println("Test Passed"); + } + + public static void main(String[] args) throws Exception { + main(new TestRawRSACipher()); + } +}