mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-13 16:38:50 +00:00
6994008: PKCS11 should support "RSA" and "RSA/ECB/NoPadding" ciphers
Add support for RSA_X_509 mechanism and aliasing of "RSA" to "RSA/ECB/PKCS1Padding". Reviewed-by: wetmore
This commit is contained in:
parent
5f0efd5e7c
commit
1daa47b01d
@ -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) {
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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");
|
||||
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);
|
||||
|
||||
// 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();
|
||||
}
|
||||
match(b, d);
|
||||
c2.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
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);
|
||||
// invalid data
|
||||
c1.init(Cipher.DECRYPT_MODE, publicKey);
|
||||
try {
|
||||
d = c1.doFinal(e);
|
||||
throw new Exception("completed call");
|
||||
} catch (BadPaddingException ee) {
|
||||
ee.printStackTrace();
|
||||
}
|
||||
|
||||
// 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.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.update(new byte[256]);
|
||||
try {
|
||||
// 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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
84
jdk/test/sun/security/pkcs11/Cipher/TestRawRSACipher.java
Normal file
84
jdk/test/sun/security/pkcs11/Cipher/TestRawRSACipher.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user