提交 f956e0fa 编写于 作者: C coffeys

8209129: Further improvements to cipher buffer management

Reviewed-by: weijun, igerasim
上级 37f10446
......@@ -73,62 +73,69 @@ public final class HmacPKCS12PBESHA1 extends HmacCore {
salt = pbeKey.getSalt(); // maybe null if unspecified
iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
} else if (key instanceof SecretKey) {
byte[] passwdBytes = key.getEncoded();
if ((passwdBytes == null) ||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
byte[] passwdBytes;
if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
(passwdBytes = key.getEncoded()) == null) {
throw new InvalidKeyException("Missing password");
}
passwdChars = new char[passwdBytes.length];
for (int i=0; i<passwdChars.length; i++) {
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
}
Arrays.fill(passwdBytes, (byte)0x00);
} else {
throw new InvalidKeyException("SecretKey of PBE type required");
}
if (params == null) {
// should not auto-generate default values since current
// javax.crypto.Mac api does not have any method for caller to
// retrieve the generated defaults.
if ((salt == null) || (iCount == 0)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec required for salt and iteration count");
}
} else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec type required");
} else {
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
// make sure the parameter values are consistent
if (salt != null) {
if (!Arrays.equals(salt, pbeParams.getSalt())) {
byte[] derivedKey;
try {
if (params == null) {
// should not auto-generate default values since current
// javax.crypto.Mac api does not have any method for caller to
// retrieve the generated defaults.
if ((salt == null) || (iCount == 0)) {
throw new InvalidAlgorithmParameterException
("Inconsistent value of salt between key and params");
("PBEParameterSpec required for salt and iteration count");
}
} else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec type required");
} else {
salt = pbeParams.getSalt();
}
if (iCount != 0) {
if (iCount != pbeParams.getIterationCount()) {
throw new InvalidAlgorithmParameterException
("Different iteration count between key and params");
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
// make sure the parameter values are consistent
if (salt != null) {
if (!Arrays.equals(salt, pbeParams.getSalt())) {
throw new InvalidAlgorithmParameterException
("Inconsistent value of salt between key and params");
}
} else {
salt = pbeParams.getSalt();
}
if (iCount != 0) {
if (iCount != pbeParams.getIterationCount()) {
throw new InvalidAlgorithmParameterException
("Different iteration count between key and params");
}
} else {
iCount = pbeParams.getIterationCount();
}
} else {
iCount = pbeParams.getIterationCount();
}
// For security purpose, we need to enforce a minimum length
// for salt; just require the minimum salt length to be 8-byte
// which is what PKCS#5 recommends and openssl does.
if (salt.length < 8) {
throw new InvalidAlgorithmParameterException
("Salt must be at least 8 bytes long");
}
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
}
derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY);
} finally {
Arrays.fill(passwdChars, '\0');
}
// For security purpose, we need to enforce a minimum length
// for salt; just require the minimum salt length to be 8-byte
// which is what PKCS#5 recommends and openssl does.
if (salt.length < 8) {
throw new InvalidAlgorithmParameterException
("Salt must be at least 8 bytes long");
}
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
}
byte[] derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY);
SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1");
super.engineInit(cipherKey, null);
}
......
......@@ -119,7 +119,7 @@ final class KeyProtector {
}
byte[] plain = key.getEncoded();
byte[] encrKey = cipher.engineDoFinal(plain, 0, plain.length);
Arrays.fill(plain, (byte) 0x00);
Arrays.fill(plain, (byte)0x00);
// wrap encrypted private key in EncryptedPrivateKeyInfo
// (as defined in PKCS#8)
......@@ -194,7 +194,7 @@ final class KeyProtector {
} catch (GeneralSecurityException gse) {
throw new UnrecoverableKeyException(gse.getMessage());
} finally {
if (plain != null) Arrays.fill(plain, (byte) 0x00);
if (plain != null) Arrays.fill(plain, (byte)0x00);
if (sKey != null) {
try {
sKey.destroy();
......
......@@ -69,7 +69,7 @@ final class PBEKey implements SecretKey {
this.key = new byte[passwd.length];
for (int i=0; i<passwd.length; i++)
this.key[i] = (byte) (passwd[i] & 0x7f);
Arrays.fill(passwd, ' ');
Arrays.fill(passwd, '\0');
type = keytype;
}
......@@ -122,7 +122,7 @@ final class PBEKey implements SecretKey {
@Override
public void destroy() {
if (key != null) {
Arrays.fill(key, (byte) 0x00);
Arrays.fill(key, (byte)0x00);
key = null;
}
}
......
......@@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
......@@ -213,35 +214,43 @@ final class PBES1Core {
throw new InvalidAlgorithmParameterException("Parameters "
+ "missing");
}
if ((key == null) ||
(key.getEncoded() == null) ||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
throw new InvalidKeyException("Missing password");
if (key == null) {
throw new InvalidKeyException("Null key");
}
if (params == null) {
// create random salt and use default iteration count
salt = new byte[8];
random.nextBytes(salt);
} else {
if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("Wrong parameter type: PBE expected");
}
salt = ((PBEParameterSpec) params).getSalt();
// salt must be 8 bytes long (by definition)
if (salt.length != 8) {
throw new InvalidAlgorithmParameterException
("Salt must be 8 bytes long");
byte[] derivedKey;
byte[] passwdBytes = key.getEncoded();
try {
if ((passwdBytes == null) ||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
throw new InvalidKeyException("Missing password");
}
iCount = ((PBEParameterSpec) params).getIterationCount();
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
if (params == null) {
// create random salt and use default iteration count
salt = new byte[8];
random.nextBytes(salt);
} else {
if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("Wrong parameter type: PBE expected");
}
salt = ((PBEParameterSpec) params).getSalt();
// salt must be 8 bytes long (by definition)
if (salt.length != 8) {
throw new InvalidAlgorithmParameterException
("Salt must be 8 bytes long");
}
iCount = ((PBEParameterSpec) params).getIterationCount();
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
}
}
derivedKey = deriveCipherKey(passwdBytes);
} finally {
if (passwdBytes != null) Arrays.fill(passwdBytes, (byte) 0x00);
}
byte[] derivedKey = deriveCipherKey(key);
// use all but the last 8 bytes as the key value
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, 0,
derivedKey.length-8, algo);
......@@ -253,16 +262,14 @@ final class PBES1Core {
cipher.init(opmode, cipherKey, ivSpec, random);
}
private byte[] deriveCipherKey(Key key) {
private byte[] deriveCipherKey(byte[] passwdBytes) {
byte[] result = null;
byte[] passwdBytes = key.getEncoded();
if (algo.equals("DES")) {
// P || S (password concatenated with salt)
byte[] concat = new byte[Math.addExact(passwdBytes.length, salt.length)];
System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
java.util.Arrays.fill(passwdBytes, (byte)0x00);
System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
// digest P || S with c iterations
......@@ -271,7 +278,7 @@ final class PBES1Core {
md.update(toBeHashed);
toBeHashed = md.digest(); // this resets the digest
}
java.util.Arrays.fill(concat, (byte)0x00);
Arrays.fill(concat, (byte)0x00);
result = toBeHashed;
} else if (algo.equals("DESede")) {
// if the 2 salt halves are the same, invert one of them
......@@ -294,8 +301,6 @@ final class PBES1Core {
// Concatenate the output from each digest round with the
// password, and use the result as the input to the next digest
// operation.
byte[] kBytes = null;
IvParameterSpec iv = null;
byte[] toBeHashed = null;
result = new byte[DESedeKeySpec.DES_EDE_KEY_LEN +
DESConstants.DES_BLOCK_SIZE];
......@@ -306,12 +311,14 @@ final class PBES1Core {
for (int j=0; j < iCount; j++) {
md.update(toBeHashed);
md.update(passwdBytes);
toBeHashed = md.digest(); // this resets the digest
toBeHashed = md.digest();
}
System.arraycopy(toBeHashed, 0, result, i*16,
toBeHashed.length);
}
}
// clear data used in message
md.reset();
return result;
}
......@@ -478,9 +485,9 @@ final class PBES1Core {
byte[] wrap(Key key)
throws IllegalBlockSizeException, InvalidKeyException {
byte[] result = null;
byte[] encodedKey = null;
try {
byte[] encodedKey = key.getEncoded();
encodedKey = key.getEncoded();
if ((encodedKey == null) || (encodedKey.length == 0)) {
throw new InvalidKeyException("Cannot get an encoding of " +
"the key to be wrapped");
......@@ -489,6 +496,8 @@ final class PBES1Core {
result = doFinal(encodedKey, 0, encodedKey.length);
} catch (BadPaddingException e) {
// Should never happen
} finally {
if (encodedKey != null) Arrays.fill(encodedKey, (byte)0x00);
}
return result;
......
......@@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
......@@ -173,101 +174,105 @@ abstract class PBES2Core extends CipherSpi {
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if ((key == null) ||
(key.getEncoded() == null) ||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
throw new InvalidKeyException("Missing password");
if (key == null) {
throw new InvalidKeyException("Null key");
}
// TBD: consolidate the salt, ic and IV parameter checks below
// Extract salt and iteration count from the key, if present
if (key instanceof javax.crypto.interfaces.PBEKey) {
salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
if (salt != null && salt.length < 8) {
throw new InvalidAlgorithmParameterException(
"Salt must be at least 8 bytes long");
}
iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
if (iCount == 0) {
iCount = DEFAULT_COUNT;
} else if (iCount < 0) {
throw new InvalidAlgorithmParameterException(
"Iteration count must be a positive number");
byte[] passwdBytes = key.getEncoded();
char[] passwdChars = null;
PBEKeySpec pbeSpec;
try {
if ((passwdBytes == null) ||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
throw new InvalidKeyException("Missing password");
}
}
// Extract salt, iteration count and IV from the params, if present
if (params == null) {
if (salt == null) {
// generate random salt and use default iteration count
salt = new byte[DEFAULT_SALT_LENGTH];
random.nextBytes(salt);
iCount = DEFAULT_COUNT;
}
if ((opmode == Cipher.ENCRYPT_MODE) ||
(opmode == Cipher.WRAP_MODE)) {
// generate random IV
byte[] ivBytes = new byte[blkSize];
random.nextBytes(ivBytes);
ivSpec = new IvParameterSpec(ivBytes);
}
} else {
if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("Wrong parameter type: PBE expected");
}
// salt and iteration count from the params take precedence
byte[] specSalt = ((PBEParameterSpec) params).getSalt();
if (specSalt != null && specSalt.length < 8) {
throw new InvalidAlgorithmParameterException(
"Salt must be at least 8 bytes long");
}
salt = specSalt;
int specICount = ((PBEParameterSpec) params).getIterationCount();
if (specICount == 0) {
specICount = DEFAULT_COUNT;
} else if (specICount < 0) {
throw new InvalidAlgorithmParameterException(
"Iteration count must be a positive number");
}
iCount = specICount;
// TBD: consolidate the salt, ic and IV parameter checks below
AlgorithmParameterSpec specParams =
((PBEParameterSpec) params).getParameterSpec();
if (specParams != null) {
if (specParams instanceof IvParameterSpec) {
ivSpec = (IvParameterSpec)specParams;
} else {
// Extract salt and iteration count from the key, if present
if (key instanceof javax.crypto.interfaces.PBEKey) {
salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
if (salt != null && salt.length < 8) {
throw new InvalidAlgorithmParameterException(
"Salt must be at least 8 bytes long");
}
iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
if (iCount == 0) {
iCount = DEFAULT_COUNT;
} else if (iCount < 0) {
throw new InvalidAlgorithmParameterException(
"Wrong parameter type: IV expected");
"Iteration count must be a positive number");
}
} else if ((opmode == Cipher.ENCRYPT_MODE) ||
}
// Extract salt, iteration count and IV from the params, if present
if (params == null) {
if (salt == null) {
// generate random salt and use default iteration count
salt = new byte[DEFAULT_SALT_LENGTH];
random.nextBytes(salt);
iCount = DEFAULT_COUNT;
}
if ((opmode == Cipher.ENCRYPT_MODE) ||
(opmode == Cipher.WRAP_MODE)) {
// generate random IV
byte[] ivBytes = new byte[blkSize];
random.nextBytes(ivBytes);
ivSpec = new IvParameterSpec(ivBytes);
// generate random IV
byte[] ivBytes = new byte[blkSize];
random.nextBytes(ivBytes);
ivSpec = new IvParameterSpec(ivBytes);
}
} else {
throw new InvalidAlgorithmParameterException(
"Missing parameter type: IV expected");
if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("Wrong parameter type: PBE expected");
}
// salt and iteration count from the params take precedence
byte[] specSalt = ((PBEParameterSpec) params).getSalt();
if (specSalt != null && specSalt.length < 8) {
throw new InvalidAlgorithmParameterException(
"Salt must be at least 8 bytes long");
}
salt = specSalt;
int specICount = ((PBEParameterSpec) params).getIterationCount();
if (specICount == 0) {
specICount = DEFAULT_COUNT;
} else if (specICount < 0) {
throw new InvalidAlgorithmParameterException(
"Iteration count must be a positive number");
}
iCount = specICount;
AlgorithmParameterSpec specParams =
((PBEParameterSpec) params).getParameterSpec();
if (specParams != null) {
if (specParams instanceof IvParameterSpec) {
ivSpec = (IvParameterSpec)specParams;
} else {
throw new InvalidAlgorithmParameterException(
"Wrong parameter type: IV expected");
}
} else if ((opmode == Cipher.ENCRYPT_MODE) ||
(opmode == Cipher.WRAP_MODE)) {
// generate random IV
byte[] ivBytes = new byte[blkSize];
random.nextBytes(ivBytes);
ivSpec = new IvParameterSpec(ivBytes);
} else {
throw new InvalidAlgorithmParameterException(
"Missing parameter type: IV expected");
}
}
}
SecretKeySpec cipherKey = null;
byte[] derivedKey = null;
byte[] passwdBytes = key.getEncoded();
char[] passwdChars = new char[passwdBytes.length];
for (int i=0; i<passwdChars.length; i++)
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
passwdChars = new char[passwdBytes.length];
for (int i = 0; i < passwdChars.length; i++)
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
PBEKeySpec pbeSpec =
new PBEKeySpec(passwdChars, salt, iCount, keyLength);
pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength);
// password char[] was cloned in PBEKeySpec constructor,
// so we can zero it out here
java.util.Arrays.fill(passwdChars, ' ');
java.util.Arrays.fill(passwdBytes, (byte)0x00);
} finally {
if (passwdChars != null) Arrays.fill(passwdChars, '\0');
if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
}
SecretKey s = null;
......@@ -280,8 +285,8 @@ abstract class PBES2Core extends CipherSpi {
ike.initCause(ikse);
throw ike;
}
derivedKey = s.getEncoded();
cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
byte[] derivedKey = s.getEncoded();
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
// initialize the underlying cipher
cipher.init(opmode, cipherKey, ivSpec, random);
......
......@@ -89,6 +89,8 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
}
// Convert the password from char[] to byte[]
byte[] passwdBytes = getPasswordBytes(this.passwd);
// remove local copy
if (passwd != null) Arrays.fill(passwd, '\0');
this.salt = keySpec.getSalt();
if (salt == null) {
......@@ -108,13 +110,15 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
}
try {
this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
} catch (NoSuchAlgorithmException nsae) {
// not gonna happen; re-throw just in case
InvalidKeySpecException ike = new InvalidKeySpecException();
ike.initCause(nsae);
throw ike;
} finally {
Arrays.fill(passwdBytes, (byte)0x00);
}
this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
}
private static byte[] deriveKey(final Mac prf, final byte[] password,
......@@ -240,8 +244,8 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
if (!(that.getFormat().equalsIgnoreCase("RAW")))
return false;
byte[] thatEncoded = that.getEncoded();
boolean ret = MessageDigest.isEqual(key, that.getEncoded());
java.util.Arrays.fill(thatEncoded, (byte)0x00);
boolean ret = MessageDigest.isEqual(key, thatEncoded);
Arrays.fill(thatEncoded, (byte)0x00);
return ret;
}
......@@ -266,7 +270,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
try {
synchronized (this) {
if (this.passwd != null) {
java.util.Arrays.fill(this.passwd, '0');
java.util.Arrays.fill(this.passwd, '\0');
this.passwd = null;
}
if (this.key != null) {
......
......@@ -108,72 +108,76 @@ abstract class PBMAC1Core extends HmacCore {
salt = pbeKey.getSalt(); // maybe null if unspecified
iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
} else if (key instanceof SecretKey) {
byte[] passwdBytes = key.getEncoded();
if ((passwdBytes == null) ||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
byte[] passwdBytes;
if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
(passwdBytes = key.getEncoded()) == null) {
throw new InvalidKeyException("Missing password");
}
passwdChars = new char[passwdBytes.length];
for (int i=0; i<passwdChars.length; i++) {
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
}
Arrays.fill(passwdBytes, (byte)0x00);
} else {
throw new InvalidKeyException("SecretKey of PBE type required");
}
if (params == null) {
// should not auto-generate default values since current
// javax.crypto.Mac api does not have any method for caller to
// retrieve the generated defaults.
if ((salt == null) || (iCount == 0)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec required for salt and iteration count");
}
} else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec type required");
} else {
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
// make sure the parameter values are consistent
if (salt != null) {
if (!Arrays.equals(salt, pbeParams.getSalt())) {
PBEKeySpec pbeSpec;
try {
if (params == null) {
// should not auto-generate default values since current
// javax.crypto.Mac api does not have any method for caller to
// retrieve the generated defaults.
if ((salt == null) || (iCount == 0)) {
throw new InvalidAlgorithmParameterException
("Inconsistent value of salt between key and params");
("PBEParameterSpec required for salt and iteration count");
}
} else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec type required");
} else {
salt = pbeParams.getSalt();
}
if (iCount != 0) {
if (iCount != pbeParams.getIterationCount()) {
throw new InvalidAlgorithmParameterException
("Different iteration count between key and params");
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
// make sure the parameter values are consistent
if (salt != null) {
if (!Arrays.equals(salt, pbeParams.getSalt())) {
throw new InvalidAlgorithmParameterException
("Inconsistent value of salt between key and params");
}
} else {
salt = pbeParams.getSalt();
}
if (iCount != 0) {
if (iCount != pbeParams.getIterationCount()) {
throw new InvalidAlgorithmParameterException
("Different iteration count between key and params");
}
} else {
iCount = pbeParams.getIterationCount();
}
} else {
iCount = pbeParams.getIterationCount();
}
}
// For security purpose, we need to enforce a minimum length
// for salt; just require the minimum salt length to be 8-byte
// which is what PKCS#5 recommends and openssl does.
if (salt.length < 8) {
throw new InvalidAlgorithmParameterException
("Salt must be at least 8 bytes long");
}
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
}
// For security purpose, we need to enforce a minimum length
// for salt; just require the minimum salt length to be 8-byte
// which is what PKCS#5 recommends and openssl does.
if (salt.length < 8) {
throw new InvalidAlgorithmParameterException
("Salt must be at least 8 bytes long");
}
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
}
PBEKeySpec pbeSpec =
new PBEKeySpec(passwdChars, salt, iCount, blockLength);
pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, blockLength);
// password char[] was cloned in PBEKeySpec constructor,
// so we can zero it out here
java.util.Arrays.fill(passwdChars, ' ');
} finally {
Arrays.fill(passwdChars, '\0');
}
SecretKey s = null;
SecretKey s;
PBKDF2Core kdf = getKDFImpl(kdfAlgo);
try {
s = kdf.engineGenerateSecret(pbeSpec);
} catch (InvalidKeySpecException ikse) {
InvalidKeyException ike =
new InvalidKeyException("Cannot construct PBE key");
......
......@@ -103,6 +103,7 @@ final class PKCS12PBECipherCore {
Arrays.fill(D, (byte)type);
concat(salt, I, 0, s);
concat(passwd, I, s, p);
Arrays.fill(passwd, (byte)0x00);
byte[] Ai;
byte[] B = new byte[v];
......@@ -265,87 +266,92 @@ final class PKCS12PBECipherCore {
salt = pbeKey.getSalt(); // maybe null if unspecified
iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
} else if (key instanceof SecretKey) {
byte[] passwdBytes = key.getEncoded();
if ((passwdBytes == null) ||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
byte[] passwdBytes;
if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
(passwdBytes = key.getEncoded()) == null) {
throw new InvalidKeyException("Missing password");
}
passwdChars = new char[passwdBytes.length];
for (int i=0; i<passwdChars.length; i++) {
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
}
Arrays.fill(passwdBytes, (byte)0x00);
} else {
throw new InvalidKeyException("SecretKey of PBE type required");
}
if (((opmode == Cipher.DECRYPT_MODE) ||
(opmode == Cipher.UNWRAP_MODE)) &&
((params == null) && ((salt == null) || (iCount == 0)))) {
throw new InvalidAlgorithmParameterException
("Parameters missing");
}
try {
if (((opmode == Cipher.DECRYPT_MODE) ||
(opmode == Cipher.UNWRAP_MODE)) &&
((params == null) && ((salt == null) || (iCount == 0)))) {
throw new InvalidAlgorithmParameterException
("Parameters missing");
}
if (params == null) {
// generate default for salt and iteration count if necessary
if (salt == null) {
salt = new byte[DEFAULT_SALT_LENGTH];
if (random != null) {
random.nextBytes(salt);
if (params == null) {
// generate default for salt and iteration count if necessary
if (salt == null) {
salt = new byte[DEFAULT_SALT_LENGTH];
if (random != null) {
random.nextBytes(salt);
} else {
SunJCE.getRandom().nextBytes(salt);
}
}
if (iCount == 0) iCount = DEFAULT_COUNT;
} else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec type required");
} else {
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
// make sure the parameter values are consistent
if (salt != null) {
if (!Arrays.equals(salt, pbeParams.getSalt())) {
throw new InvalidAlgorithmParameterException
("Inconsistent value of salt between key and params");
}
} else {
SunJCE.getRandom().nextBytes(salt);
salt = pbeParams.getSalt();
}
}
if (iCount == 0) iCount = DEFAULT_COUNT;
} else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec type required");
} else {
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
// make sure the parameter values are consistent
if (salt != null) {
if (!Arrays.equals(salt, pbeParams.getSalt())) {
throw new InvalidAlgorithmParameterException
("Inconsistent value of salt between key and params");
if (iCount != 0) {
if (iCount != pbeParams.getIterationCount()) {
throw new InvalidAlgorithmParameterException
("Different iteration count between key and params");
}
} else {
iCount = pbeParams.getIterationCount();
}
} else {
salt = pbeParams.getSalt();
}
if (iCount != 0) {
if (iCount != pbeParams.getIterationCount()) {
throw new InvalidAlgorithmParameterException
("Different iteration count between key and params");
}
} else {
iCount = pbeParams.getIterationCount();
// salt is recommended to be ideally as long as the output
// of the hash function. However, it may be too strict to
// force this; so instead, we'll just require the minimum
// salt length to be 8-byte which is what PKCS#5 recommends
// and openssl does.
if (salt.length < 8) {
throw new InvalidAlgorithmParameterException
("Salt must be at least 8 bytes long");
}
}
// salt is recommended to be ideally as long as the output
// of the hash function. However, it may be too strict to
// force this; so instead, we'll just require the minimum
// salt length to be 8-byte which is what PKCS#5 recommends
// and openssl does.
if (salt.length < 8) {
throw new InvalidAlgorithmParameterException
("Salt must be at least 8 bytes long");
}
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
}
byte[] derivedKey = derive(passwdChars, salt, iCount,
keySize, CIPHER_KEY);
SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
}
byte[] derivedKey = derive(passwdChars, salt, iCount,
keySize, CIPHER_KEY);
SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
} else {
byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
CIPHER_IV);
IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
} else {
byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
CIPHER_IV);
IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
// initialize the underlying cipher
cipher.init(opmode, cipherKey, ivSpec, random);
// initialize the underlying cipher
cipher.init(opmode, cipherKey, ivSpec, random);
}
} finally {
Arrays.fill(passwdChars, '\0');
}
}
......
......@@ -28,6 +28,7 @@ package sun.security.provider;
import java.security.MessageDigestSpi;
import java.security.DigestException;
import java.security.ProviderException;
import java.util.Arrays;
/**
* Common base message digest implementation for the Sun provider.
......@@ -151,6 +152,7 @@ abstract class DigestBase extends MessageDigestSpi implements Cloneable {
implReset();
bufOfs = 0;
bytesProcessed = 0;
Arrays.fill(buffer, (byte) 0x00);
}
// return the digest. See JCA doc.
......
......@@ -26,6 +26,7 @@
package sun.security.provider;
import java.security.*;
import java.util.Arrays;
import static sun.security.provider.ByteArrayAccess.*;
......@@ -90,7 +91,7 @@ public final class MD4 extends DigestBase {
super("MD4", 16, 64);
state = new int[4];
x = new int[16];
implReset();
resetHashes();
}
// clone this object
......@@ -106,6 +107,12 @@ public final class MD4 extends DigestBase {
*/
void implReset() {
// Load magic initialization constants.
resetHashes();
// clear out old data
Arrays.fill(x, 0);
}
private void resetHashes() {
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
......
......@@ -25,6 +25,8 @@
package sun.security.provider;
import java.util.Arrays;
import static sun.security.provider.ByteArrayAccess.*;
/**
......@@ -66,7 +68,7 @@ public final class MD5 extends DigestBase {
super("MD5", 16, 64);
state = new int[4];
x = new int[16];
implReset();
resetHashes();
}
// clone this object
......@@ -82,6 +84,12 @@ public final class MD5 extends DigestBase {
*/
void implReset() {
// Load magic initialization constants.
resetHashes();
// clear out old data
Arrays.fill(x, 0);
}
private void resetHashes() {
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
......
......@@ -25,6 +25,8 @@
package sun.security.provider;
import java.util.Arrays;
import static sun.security.provider.ByteArrayAccess.*;
/**
......@@ -59,7 +61,7 @@ public final class SHA extends DigestBase {
super("SHA-1", 20, 64);
state = new int[5];
W = new int[80];
implReset();
resetHashes();
}
/*
......@@ -76,6 +78,13 @@ public final class SHA extends DigestBase {
* Resets the buffers and hash value to start a new hash.
*/
void implReset() {
// Load magic initialization constants.
resetHashes();
// clear out old data
Arrays.fill(W, 0);
}
private void resetHashes() {
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
......
......@@ -25,6 +25,8 @@
package sun.security.provider;
import java.util.Arrays;
import static sun.security.provider.ByteArrayAccess.*;
/**
......@@ -80,13 +82,18 @@ abstract class SHA2 extends DigestBase {
this.initialHashes = initialHashes;
state = new int[8];
W = new int[64];
implReset();
resetHashes();
}
/**
* Resets the buffers and hash value to start a new hash.
*/
void implReset() {
resetHashes();
Arrays.fill(W, 0);
}
private void resetHashes() {
System.arraycopy(initialHashes, 0, state, 0, state.length);
}
......
......@@ -25,8 +25,7 @@
package sun.security.provider;
import java.security.*;
import java.math.BigInteger;
import java.util.Arrays;
import static sun.security.provider.ByteArrayAccess.*;
......@@ -98,10 +97,15 @@ abstract class SHA5 extends DigestBase {
this.initialHashes = initialHashes;
state = new long[8];
W = new long[80];
implReset();
resetHashes();
}
final void implReset() {
resetHashes();
Arrays.fill(W, 0L);
}
private void resetHashes() {
System.arraycopy(initialHashes, 0, state, 0, state.length);
}
......
......@@ -105,7 +105,7 @@ class MyPBEKey implements PBEKey {
this.salt = salt;
this.iCount = iCount;
}
public char[] getPassword() { return passwd; }
public char[] getPassword() { return passwd.clone(); }
public byte[] getSalt() { return salt; }
public int getIterationCount() { return iCount; }
public String getAlgorithm() { return "PBE"; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册