From 6f2c4e8006430305d22b71619df7fbfccf97b9ec Mon Sep 17 00:00:00 2001 From: valeriep Date: Thu, 20 Mar 2008 17:17:10 -0700 Subject: [PATCH] 6572331: regression: cipher.wrap operation fails with CKR_ATTRIBUTE_VALUE_INVALID Summary: Check supported key size range and use encryption if needed Reviewed-by: andreas --- .../sun/security/pkcs11/P11KeyGenerator.java | 189 ++++++++++-------- .../sun/security/pkcs11/P11RSACipher.java | 56 ++++-- .../security/pkcs11/P11SecretKeyFactory.java | 145 +++++++------- .../pkcs11/Cipher/TestRSACipherWrap.java | 109 ++++++++++ 4 files changed, 322 insertions(+), 177 deletions(-) create mode 100644 test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java diff --git a/src/share/classes/sun/security/pkcs11/P11KeyGenerator.java b/src/share/classes/sun/security/pkcs11/P11KeyGenerator.java index b49cbeac0..c08c12a26 100644 --- a/src/share/classes/sun/security/pkcs11/P11KeyGenerator.java +++ b/src/share/classes/sun/security/pkcs11/P11KeyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. 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 @@ -65,10 +65,86 @@ final class P11KeyGenerator extends KeyGeneratorSpi { // are supported. private boolean supportBothKeySizes; - // min and max key sizes (in bits) for variable-key-length - // algorithms, e.g. RC4 and Blowfish - private int minKeySize; - private int maxKeySize; + /** + * Utility method for checking if the specified key size is valid + * and within the supported range. Return the significant key size + * upon successful validation. + * @param keyGenMech the PKCS#11 key generation mechanism. + * @param keySize the to-be-checked key size for this mechanism. + * @param token token which provides this mechanism. + * @return the significant key size (in bits) corresponding to the + * specified key size. + * @throws InvalidParameterException if the specified key size is invalid. + * @throws ProviderException if this mechanism isn't supported by SunPKCS11 + * or underlying native impl. + */ + static int checkKeySize(long keyGenMech, int keySize, Token token) + throws InvalidAlgorithmParameterException, ProviderException { + int sigKeySize; + switch ((int)keyGenMech) { + case (int)CKM_DES_KEY_GEN: + if ((keySize != 64) && (keySize != 56)) { + throw new InvalidAlgorithmParameterException + ("DES key length must be 56 bits"); + } + sigKeySize = 56; + break; + case (int)CKM_DES2_KEY_GEN: + case (int)CKM_DES3_KEY_GEN: + if ((keySize == 112) || (keySize == 128)) { + sigKeySize = 112; + } else if ((keySize == 168) || (keySize == 192)) { + sigKeySize = 168; + } else { + throw new InvalidAlgorithmParameterException + ("DESede key length must be 112, or 168 bits"); + } + break; + default: + // Handle all variable-key-length algorithms here + CK_MECHANISM_INFO info = null; + try { + info = token.getMechanismInfo(keyGenMech); + } catch (PKCS11Exception p11e) { + // Should never happen + throw new ProviderException + ("Cannot retrieve mechanism info", p11e); + } + if (info == null) { + // XXX Unable to retrieve the supported key length from + // the underlying native impl. Skip the checking for now. + return keySize; + } + // PKCS#11 defines these to be in number of bytes except for + // RC4 which is in bits. However, some PKCS#11 impls still use + // bytes for all mechs, e.g. NSS. We try to detect this + // inconsistency if the minKeySize seems unreasonably small. + int minKeySize = (int)info.ulMinKeySize; + int maxKeySize = (int)info.ulMaxKeySize; + if (keyGenMech != CKM_RC4_KEY_GEN || minKeySize < 8) { + minKeySize = (int)info.ulMinKeySize << 3; + maxKeySize = (int)info.ulMaxKeySize << 3; + } + // Explicitly disallow keys shorter than 40-bits for security + if (minKeySize < 40) minKeySize = 40; + if (keySize < minKeySize || keySize > maxKeySize) { + throw new InvalidAlgorithmParameterException + ("Key length must be between " + minKeySize + + " and " + maxKeySize + " bits"); + } + if (keyGenMech == CKM_AES_KEY_GEN) { + if ((keySize != 128) && (keySize != 192) && + (keySize != 256)) { + throw new InvalidAlgorithmParameterException + ("AES key length must be " + minKeySize + + (maxKeySize >= 192? ", 192":"") + + (maxKeySize >= 256? ", or 256":"") + " bits"); + } + } + sigKeySize = keySize; + } + return sigKeySize; + } P11KeyGenerator(Token token, String algorithm, long mechanism) throws PKCS11Exception { @@ -85,72 +161,44 @@ final class P11KeyGenerator extends KeyGeneratorSpi { supportBothKeySizes = (token.provider.config.isEnabled(CKM_DES2_KEY_GEN) && (token.getMechanismInfo(CKM_DES2_KEY_GEN) != null)); - } else if (this.mechanism == CKM_RC4_KEY_GEN) { - CK_MECHANISM_INFO info = token.getMechanismInfo(mechanism); - // Although PKCS#11 spec documented that these are in bits, - // NSS, for one, uses bytes. Multiple by 8 if the number seems - // unreasonably small. - if (info.ulMinKeySize < 8) { - minKeySize = (int)info.ulMinKeySize << 3; - maxKeySize = (int)info.ulMaxKeySize << 3; - } else { - minKeySize = (int)info.ulMinKeySize; - maxKeySize = (int)info.ulMaxKeySize; - } - // Explicitly disallow keys shorter than 40-bits for security - if (minKeySize < 40) minKeySize = 40; - } else if (this.mechanism == CKM_BLOWFISH_KEY_GEN) { - CK_MECHANISM_INFO info = token.getMechanismInfo(mechanism); - maxKeySize = (int)info.ulMaxKeySize << 3; - minKeySize = (int)info.ulMinKeySize << 3; - // Explicitly disallow keys shorter than 40-bits for security - if (minKeySize < 40) minKeySize = 40; } - setDefaultKeySize(); } // set default keysize and also initialize keyType private void setDefaultKeySize() { - // whether to check default key size against the min and max value - boolean validateKeySize = false; switch ((int)mechanism) { case (int)CKM_DES_KEY_GEN: keySize = 64; - significantKeySize = 56; keyType = CKK_DES; break; case (int)CKM_DES2_KEY_GEN: keySize = 128; - significantKeySize = 112; keyType = CKK_DES2; break; case (int)CKM_DES3_KEY_GEN: keySize = 192; - significantKeySize = 168; keyType = CKK_DES3; break; case (int)CKM_AES_KEY_GEN: - keyType = CKK_AES; keySize = 128; - significantKeySize = 128; + keyType = CKK_AES; break; case (int)CKM_RC4_KEY_GEN: - keyType = CKK_RC4; keySize = 128; - validateKeySize = true; + keyType = CKK_RC4; break; case (int)CKM_BLOWFISH_KEY_GEN: - keyType = CKK_BLOWFISH; keySize = 128; - validateKeySize = true; + keyType = CKK_BLOWFISH; break; default: throw new ProviderException("Unknown mechanism " + mechanism); } - if (validateKeySize && - ((keySize > maxKeySize) || (keySize < minKeySize))) { - throw new ProviderException("Unsupported key size"); + try { + significantKeySize = checkKeySize(mechanism, keySize, token); + } catch (InvalidAlgorithmParameterException iape) { + throw new ProviderException("Unsupported default key size", iape); } } @@ -170,57 +218,32 @@ final class P11KeyGenerator extends KeyGeneratorSpi { // see JCE spec protected void engineInit(int keySize, SecureRandom random) { token.ensureValid(); - switch ((int)mechanism) { - case (int)CKM_DES_KEY_GEN: - if ((keySize != this.keySize) && - (keySize != this.significantKeySize)) { - throw new InvalidParameterException - ("DES key length must be 56 bits"); - } - break; - case (int)CKM_DES2_KEY_GEN: - case (int)CKM_DES3_KEY_GEN: - long newMechanism; - if ((keySize == 112) || (keySize == 128)) { - newMechanism = CKM_DES2_KEY_GEN; - } else if ((keySize == 168) || (keySize == 192)) { - newMechanism = CKM_DES3_KEY_GEN; - } else { - throw new InvalidParameterException - ("DESede key length must be 112, or 168 bits"); - } + int newSignificantKeySize; + try { + newSignificantKeySize = checkKeySize(mechanism, keySize, token); + } catch (InvalidAlgorithmParameterException iape) { + throw (InvalidParameterException) + (new InvalidParameterException().initCause(iape)); + } + if ((mechanism == CKM_DES2_KEY_GEN) || + (mechanism == CKM_DES3_KEY_GEN)) { + long newMechanism = (newSignificantKeySize == 112 ? + CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN); if (mechanism != newMechanism) { if (supportBothKeySizes) { mechanism = newMechanism; - setDefaultKeySize(); + // Adjust keyType to reflect the mechanism change + keyType = (mechanism == CKM_DES2_KEY_GEN ? + CKK_DES2 : CKK_DES3); } else { throw new InvalidParameterException - ("Only " + significantKeySize + - "-bit DESede key length is supported"); + ("Only " + significantKeySize + + "-bit DESede is supported"); } } - break; - case (int)CKM_AES_KEY_GEN: - if ((keySize != 128) && (keySize != 192) && (keySize != 256)) { - throw new InvalidParameterException - ("AES key length must be 128, 192, or 256 bits"); - } - this.keySize = keySize; - significantKeySize = keySize; - break; - case (int)CKM_RC4_KEY_GEN: - case (int)CKM_BLOWFISH_KEY_GEN: - if ((keySize < minKeySize) || (keySize > maxKeySize)) { - throw new InvalidParameterException - (algorithm + " key length must be between " + - minKeySize + " and " + maxKeySize + " bits"); - } - this.keySize = keySize; - this.significantKeySize = keySize; - break; - default: - throw new ProviderException("Unknown mechanism " + mechanism); } + this.keySize = keySize; + this.significantKeySize = newSignificantKeySize; } // see JCE spec diff --git a/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/share/classes/sun/security/pkcs11/P11RSACipher.java index e2060c739..3b8244cc4 100644 --- a/src/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/src/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. 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 @@ -98,7 +98,6 @@ final class P11RSACipher extends CipherSpi { this.token = token; this.algorithm = "RSA"; this.mechanism = mechanism; - session = token.getOpSession(); } // modes do not make sense for RSA, but allow ECB @@ -184,7 +183,8 @@ final class P11RSACipher extends CipherSpi { throw new InvalidKeyException ("Wrap has to be used with public keys"); } - // No further setup needed for C_Wrap(). We remain uninitialized. + // No further setup needed for C_Wrap(). We'll initialize later if + // we can't use C_Wrap(). return; } else if (opmode == Cipher.UNWRAP_MODE) { if (p11Key.isPrivate() == false) { @@ -383,7 +383,8 @@ final class P11RSACipher extends CipherSpi { return implDoFinal(out, outOfs, out.length - outOfs); } - private byte[] doFinal() throws BadPaddingException, IllegalBlockSizeException { + private byte[] doFinal() throws BadPaddingException, + IllegalBlockSizeException { byte[] t = new byte[2048]; int n = implDoFinal(t, 0, t.length); byte[] out = new byte[n]; @@ -394,20 +395,37 @@ final class P11RSACipher extends CipherSpi { // see JCE spec protected byte[] engineWrap(Key key) throws InvalidKeyException, IllegalBlockSizeException { - // XXX Note that if we cannot convert key to a key on this token, - // we will fail. For example, trying a wrap an AES key on a token that - // does not support AES. - // We could implement a fallback that just encrypts the encoding - // (assuming the key is not sensitive). For now, we are operating under - // the assumption that this is not necessary. String keyAlg = key.getAlgorithm(); - P11Key secretKey = P11SecretKeyFactory.convertKey(token, key, keyAlg); + P11Key sKey = null; + try { + // The conversion may fail, e.g. trying to wrap an AES key on + // a token that does not support AES, or when the key size is + // not within the range supported by the token. + sKey = P11SecretKeyFactory.convertKey(token, key, keyAlg); + } catch (InvalidKeyException ike) { + byte[] toBeWrappedKey = key.getEncoded(); + if (toBeWrappedKey == null) { + throw new InvalidKeyException + ("wrap() failed, no encoding available", ike); + } + // Directly encrypt the key encoding when key conversion failed + implInit(Cipher.ENCRYPT_MODE, p11Key); + implUpdate(toBeWrappedKey, 0, toBeWrappedKey.length); + try { + return doFinal(); + } catch (BadPaddingException bpe) { + // should not occur + throw new InvalidKeyException("wrap() failed", bpe); + } finally { + // Restore original mode + implInit(Cipher.WRAP_MODE, p11Key); + } + } Session s = null; try { s = token.getOpSession(); - byte[] b = token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism), - p11Key.keyID, secretKey.keyID); - return b; + return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism), + p11Key.keyID, sKey.keyID); } catch (PKCS11Exception e) { throw new InvalidKeyException("wrap() failed", e); } finally { @@ -431,11 +449,13 @@ final class P11RSACipher extends CipherSpi { }; attributes = token.getAttributes (O_IMPORT, CKO_SECRET_KEY, keyType, attributes); - long keyID = token.p11.C_UnwrapKey(s.id(), new CK_MECHANISM(mechanism), - p11Key.keyID, wrappedKey, attributes); - return P11Key.secretKey(session, keyID, algorithm, 48 << 3, attributes); + long keyID = token.p11.C_UnwrapKey(s.id(), + new CK_MECHANISM(mechanism), p11Key.keyID, wrappedKey, + attributes); + return P11Key.secretKey(session, keyID, algorithm, 48 << 3, + attributes); } catch (PKCS11Exception e) { - throw new InvalidKeyException("wrap() failed", e); + throw new InvalidKeyException("unwrap() failed", e); } finally { token.releaseSession(s); } diff --git a/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java b/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java index bd09447c1..2f2053818 100644 --- a/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java +++ b/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. 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 @@ -104,9 +104,9 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { /** * Convert an arbitrary key of algorithm into a P11Key of provider. - * Used engineTranslateKey(), P11Cipher.init(), and P11Mac.init(). + * Used in engineTranslateKey(), P11Cipher.init(), and P11Mac.init(). */ - static P11Key convertKey(Token token, Key key, String algorithm) + static P11Key convertKey(Token token, Key key, String algo) throws InvalidKeyException { token.ensureValid(); if (key == null) { @@ -115,19 +115,19 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { if (key instanceof SecretKey == false) { throw new InvalidKeyException("Key must be a SecretKey"); } - long algorithmType; - if (algorithm == null) { - algorithm = key.getAlgorithm(); - algorithmType = getKeyType(algorithm); + long algoType; + if (algo == null) { + algo = key.getAlgorithm(); + algoType = getKeyType(algo); } else { - algorithmType = getKeyType(algorithm); + algoType = getKeyType(algo); long keyAlgorithmType = getKeyType(key.getAlgorithm()); - if (algorithmType != keyAlgorithmType) { - if ((algorithmType == PCKK_HMAC) || (algorithmType == PCKK_SSLMAC)) { + if (algoType != keyAlgorithmType) { + if ((algoType == PCKK_HMAC) || (algoType == PCKK_SSLMAC)) { // ignore key algorithm for MACs } else { throw new InvalidKeyException - ("Key algorithm must be " + algorithm); + ("Key algorithm must be " + algo); } } } @@ -145,7 +145,7 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { throw new InvalidKeyException("Encoded format must be RAW"); } byte[] encoded = key.getEncoded(); - p11Key = createKey(token, encoded, algorithm, algorithmType); + p11Key = createKey(token, encoded, algo, algoType); token.secretCache.put(key, p11Key); return p11Key; } @@ -160,77 +160,70 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { private static P11Key createKey(Token token, byte[] encoded, String algorithm, long keyType) throws InvalidKeyException { - int n = encoded.length; - int keyLength; - switch ((int)keyType) { - case (int)CKK_RC4: - if ((n < 5) || (n > 128)) { - throw new InvalidKeyException - ("ARCFOUR key length must be between 5 and 128 bytes"); - } - keyLength = n << 3; - break; - case (int)CKK_DES: - if (n != 8) { - throw new InvalidKeyException - ("DES key length must be 8 bytes"); - } - keyLength = 56; - fixDESParity(encoded, 0); - break; - case (int)CKK_DES3: - if (n == 16) { - keyType = CKK_DES2; - } else if (n == 24) { - keyType = CKK_DES3; - fixDESParity(encoded, 16); - } else { - throw new InvalidKeyException - ("DESede key length must be 16 or 24 bytes"); - } - fixDESParity(encoded, 0); - fixDESParity(encoded, 8); - keyLength = n * 7; - break; - case (int)CKK_AES: - if ((n != 16) && (n != 24) && (n != 32)) { - throw new InvalidKeyException - ("AES key length must be 16, 24, or 32 bytes"); - } - keyLength = n << 3; - break; - case (int)CKK_BLOWFISH: - if ((n < 5) || (n > 56)) { - throw new InvalidKeyException - ("Blowfish key length must be between 5 and 56 bytes"); - } - keyLength = n << 3; - break; - case (int)CKK_GENERIC_SECRET: - case (int)PCKK_TLSPREMASTER: - case (int)PCKK_TLSRSAPREMASTER: - case (int)PCKK_TLSMASTER: - keyType = CKK_GENERIC_SECRET; - keyLength = n << 3; - break; - case (int)PCKK_SSLMAC: - case (int)PCKK_HMAC: - if (n == 0) { - throw new InvalidKeyException - ("MAC keys must not be empty"); + int n = encoded.length << 3; + int keyLength = n; + try { + switch ((int)keyType) { + case (int)CKK_DES: + keyLength = + P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token); + fixDESParity(encoded, 0); + break; + case (int)CKK_DES3: + keyLength = + P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token); + fixDESParity(encoded, 0); + fixDESParity(encoded, 8); + if (keyLength == 112) { + keyType = CKK_DES2; + } else { + keyType = CKK_DES3; + fixDESParity(encoded, 16); + } + break; + case (int)CKK_AES: + keyLength = + P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token); + break; + case (int)CKK_RC4: + keyLength = + P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token); + break; + case (int)CKK_BLOWFISH: + keyLength = + P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n, + token); + break; + case (int)CKK_GENERIC_SECRET: + case (int)PCKK_TLSPREMASTER: + case (int)PCKK_TLSRSAPREMASTER: + case (int)PCKK_TLSMASTER: + keyType = CKK_GENERIC_SECRET; + break; + case (int)PCKK_SSLMAC: + case (int)PCKK_HMAC: + if (n == 0) { + throw new InvalidKeyException + ("MAC keys must not be empty"); + } + keyType = CKK_GENERIC_SECRET; + break; + default: + throw new InvalidKeyException("Unknown algorithm " + + algorithm); } - keyType = CKK_GENERIC_SECRET; - keyLength = n << 3; - break; - default: - throw new InvalidKeyException("Unknown algorithm " + algorithm); + } catch (InvalidAlgorithmParameterException iape) { + throw new InvalidKeyException("Invalid key for " + algorithm, + iape); + } catch (ProviderException pe) { + throw new InvalidKeyException("Could not create key", pe); } Session session = null; try { CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY), new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType), - new CK_ATTRIBUTE(CKA_VALUE, encoded), + new CK_ATTRIBUTE(CKA_VALUE, encoded) }; attributes = token.getAttributes (O_IMPORT, CKO_SECRET_KEY, keyType, attributes); diff --git a/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java b/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java new file mode 100644 index 000000000..3dcd07673 --- /dev/null +++ b/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java @@ -0,0 +1,109 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6572331 + * @summary basic test for RSA cipher key wrapping functionality + * @author Valerie Peng + * @library .. + */ +import java.io.*; +import java.util.*; + +import java.security.*; + +import javax.crypto.*; +import javax.crypto.spec.SecretKeySpec; + +public class TestRSACipherWrap extends PKCS11Test { + + private static final String RSA_ALGO = "RSA/ECB/PKCS1Padding"; + + public void main(Provider p) throws Exception { + try { + Cipher.getInstance(RSA_ALGO, p); + } catch (GeneralSecurityException e) { + System.out.println("Not supported by provider, 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"); + + String algos[] = {"AES", "RC2", "Blowfish"}; + int keySizes[] = {128, 256}; + + 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 " + + 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"); + } + test(kp, secretKey, cipherPKCS11, cipherJce); + test(kp, secretKey, cipherPKCS11, cipherPKCS11); + test(kp, secretKey, cipherJce, cipherPKCS11); + } + } + } + + private static void test(KeyPair kp, SecretKey secretKey, + Cipher wrapCipher, Cipher unwrapCipher) + throws Exception { + String algo = secretKey.getAlgorithm(); + wrapCipher.init(Cipher.WRAP_MODE, kp.getPublic()); + byte[] wrappedKey = wrapCipher.wrap(secretKey); + unwrapCipher.init(Cipher.UNWRAP_MODE, kp.getPrivate()); + Key unwrappedKey = + unwrapCipher.unwrap(wrappedKey, algo, Cipher.SECRET_KEY); + + System.out.println("Test " + wrapCipher.getProvider().getName() + + "/" + unwrapCipher.getProvider().getName() + ": "); + if (!Arrays.equals(secretKey.getEncoded(), + unwrappedKey.getEncoded())) { + throw new Exception("Test Failed!"); + } + System.out.println("Passed"); + } + + public static void main(String[] args) throws Exception { + main(new TestRSACipherWrap()); + } +} + -- GitLab