From 98cb588a7ca0cee8133f3e7094cce4c1d9276533 Mon Sep 17 00:00:00 2001 From: valeriep Date: Mon, 7 Mar 2011 14:14:37 -0800 Subject: [PATCH] 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 --- .../sun/security/pkcs11/P11RSACipher.java | 19 +++- .../sun/security/pkcs11/SunPKCS11.java | 4 +- .../security/pkcs11/Cipher/TestRSACipher.java | 104 +++++++++--------- .../pkcs11/Cipher/TestRSACipherWrap.java | 55 ++++----- .../pkcs11/Cipher/TestRawRSACipher.java | 84 ++++++++++++++ 5 files changed, 184 insertions(+), 82 deletions(-) create mode 100644 test/sun/security/pkcs11/Cipher/TestRawRSACipher.java diff --git a/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/share/classes/sun/security/pkcs11/P11RSACipher.java index 18f3ab450..d9dc4e77e 100644 --- a/src/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/src/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -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 @@ final class P11RSACipher extends CipherSpi { // 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 @@ final class P11RSACipher extends CipherSpi { // 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 @@ final class P11RSACipher extends CipherSpi { 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 @@ final class P11RSACipher extends CipherSpi { 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 --git a/src/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/share/classes/sun/security/pkcs11/SunPKCS11.java index d1a1db3de..d54c56173 100644 --- a/src/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/src/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -627,8 +627,10 @@ public final class SunPKCS11 extends AuthProvider { 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 --git a/test/sun/security/pkcs11/Cipher/TestRSACipher.java b/test/sun/security/pkcs11/Cipher/TestRSACipher.java index f1adba35d..4f27ff5de 100644 --- a/test/sun/security/pkcs11/Cipher/TestRSACipher.java +++ b/test/sun/security/pkcs11/Cipher/TestRSACipher.java @@ -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 @@ import javax.crypto.*; 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 @@ public class TestRSACipher extends PKCS11Test { b = new byte[16]; random.nextBytes(b); - Cipher c1 = Cipher.getInstance("RSA/ECB/PKCS1Padding", p); - Cipher c2 = Cipher.getInstance("RSA/ECB/PKCS1Padding", "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); + for (String rsaAlgo: RSA_ALGOS) { + Cipher c1 = Cipher.getInstance(rsaAlgo, p); + Cipher c2 = Cipher.getInstance(rsaAlgo, "SunJCE"); - // invalid data - c1.init(Cipher.DECRYPT_MODE, publicKey); - try { + c1.init(Cipher.ENCRYPT_MODE, publicKey); + e = c1.doFinal(b); + c1.init(Cipher.DECRYPT_MODE, privateKey); 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); - - // 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 { + 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(); + } + + 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(); - 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 --git a/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java b/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java index 159bb50a0..c00b39942 100644 --- a/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java +++ b/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java @@ -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 @@ import javax.crypto.spec.SecretKeySpec; 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 --git a/test/sun/security/pkcs11/Cipher/TestRawRSACipher.java b/test/sun/security/pkcs11/Cipher/TestRawRSACipher.java new file mode 100644 index 000000000..d1dd02060 --- /dev/null +++ b/test/sun/security/pkcs11/Cipher/TestRawRSACipher.java @@ -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()); + } +} -- GitLab