6572331: regression: cipher.wrap operation fails with CKR_ATTRIBUTE_VALUE_INVALID
Check supported key size range and use encryption if needed Reviewed-by: andreas
This commit is contained in:
parent
83d7d2cdfb
commit
4b9b2408f3
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
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);
|
||||
}
|
||||
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");
|
||||
}
|
||||
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);
|
||||
|
109
jdk/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java
Normal file
109
jdk/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user