提交 cf5d112a 编写于 作者: I igerasim

8181692: Update storage implementations

Reviewed-by: weijun, igerasim
上级 81070e19
/* /*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -38,6 +38,7 @@ import java.security.NoSuchAlgorithmException; ...@@ -38,6 +38,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException;
import java.security.AlgorithmParameters; import java.security.AlgorithmParameters;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.Cipher; import javax.crypto.Cipher;
...@@ -74,6 +75,8 @@ final class KeyProtector { ...@@ -74,6 +75,8 @@ final class KeyProtector {
// keys in the keystore implementation that comes with JDK 1.2) // keys in the keystore implementation that comes with JDK 1.2)
private static final String KEY_PROTECTOR_OID = "1.3.6.1.4.1.42.2.17.1.1"; private static final String KEY_PROTECTOR_OID = "1.3.6.1.4.1.42.2.17.1.1";
private static final int MAX_ITERATION_COUNT = 5000000;
private static final int ITERATION_COUNT = 200000;
private static final int SALT_LEN = 20; // the salt length private static final int SALT_LEN = 20; // the salt length
private static final int DIGEST_LEN = 20; private static final int DIGEST_LEN = 20;
...@@ -100,7 +103,7 @@ final class KeyProtector { ...@@ -100,7 +103,7 @@ final class KeyProtector {
SunJCE.getRandom().nextBytes(salt); SunJCE.getRandom().nextBytes(salt);
// create PBE parameters from salt and iteration count // create PBE parameters from salt and iteration count
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20); PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
// create PBE key from password // create PBE key from password
PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password); PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
...@@ -155,6 +158,9 @@ final class KeyProtector { ...@@ -155,6 +158,9 @@ final class KeyProtector {
pbeParams.init(encodedParams); pbeParams.init(encodedParams);
PBEParameterSpec pbeSpec = PBEParameterSpec pbeSpec =
pbeParams.getParameterSpec(PBEParameterSpec.class); pbeParams.getParameterSpec(PBEParameterSpec.class);
if (pbeSpec.getIterationCount() > MAX_ITERATION_COUNT) {
throw new IOException("PBE iteration count too large");
}
// create PBE key from password // create PBE key from password
PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password); PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
...@@ -285,7 +291,7 @@ final class KeyProtector { ...@@ -285,7 +291,7 @@ final class KeyProtector {
SunJCE.getRandom().nextBytes(salt); SunJCE.getRandom().nextBytes(salt);
// create PBE parameters from salt and iteration count // create PBE parameters from salt and iteration count
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20); PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
// create PBE key from password // create PBE key from password
PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password); PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
...@@ -326,6 +332,15 @@ final class KeyProtector { ...@@ -326,6 +332,15 @@ final class KeyProtector {
throw new UnrecoverableKeyException("Cannot get " + throw new UnrecoverableKeyException("Cannot get " +
"algorithm parameters"); "algorithm parameters");
} }
PBEParameterSpec pbeSpec;
try {
pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
throw new IOException("Invalid PBE algorithm parameters");
}
if (pbeSpec.getIterationCount() > MAX_ITERATION_COUNT) {
throw new IOException("PBE iteration count too large");
}
PBEWithMD5AndTripleDESCipher cipherSpi; PBEWithMD5AndTripleDESCipher cipherSpi;
cipherSpi = new PBEWithMD5AndTripleDESCipher(); cipherSpi = new PBEWithMD5AndTripleDESCipher();
Cipher cipher = new CipherForKeyProtector(cipherSpi, Cipher cipher = new CipherForKeyProtector(cipherSpi,
......
...@@ -284,7 +284,7 @@ final class PBES1Core { ...@@ -284,7 +284,7 @@ final class PBES1Core {
for (i=0; i<2; i++) { for (i=0; i<2; i++) {
byte tmp = salt[i]; byte tmp = salt[i];
salt[i] = salt[3-i]; salt[i] = salt[3-i];
salt[3-1] = tmp; salt[3-i] = tmp;
} }
} }
......
/* /*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -46,11 +46,13 @@ import java.security.cert.CertificateFactory; ...@@ -46,11 +46,13 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec; import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*; import java.util.*;
import java.security.AlgorithmParameters; import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import javax.crypto.spec.PBEParameterSpec; import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
...@@ -136,6 +138,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -136,6 +138,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
"keystore.PKCS12.keyProtectionAlgorithm" "keystore.PKCS12.keyProtectionAlgorithm"
}; };
private static final int MAX_ITERATION_COUNT = 5000000;
private static final int PBE_ITERATION_COUNT = 50000; // default
private static final int MAC_ITERATION_COUNT = 100000; // default
private static final int SALT_LEN = 20;
// friendlyName, localKeyId, trustedKeyUsage // friendlyName, localKeyId, trustedKeyUsage
private static final String[] CORE_ATTRIBUTES = { private static final String[] CORE_ATTRIBUTES = {
"1.2.840.113549.1.9.20", "1.2.840.113549.1.9.20",
...@@ -181,8 +188,6 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -181,8 +188,6 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
private static ObjectIdentifier[] AnyUsage; private static ObjectIdentifier[] AnyUsage;
private int counter = 0; private int counter = 0;
private static final int iterationCount = 1024;
private static final int SALT_LEN = 20;
// private key count // private key count
// Note: This is a workaround to allow null localKeyID attribute // Note: This is a workaround to allow null localKeyID attribute
...@@ -316,6 +321,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -316,6 +321,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
byte[] encryptedKey; byte[] encryptedKey;
AlgorithmParameters algParams; AlgorithmParameters algParams;
ObjectIdentifier algOid; ObjectIdentifier algOid;
try { try {
// get the encrypted private key // get the encrypted private key
EncryptedPrivateKeyInfo encrInfo = EncryptedPrivateKeyInfo encrInfo =
...@@ -336,7 +342,24 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -336,7 +342,24 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
throw uke; throw uke;
} }
try { try {
PBEParameterSpec pbeSpec;
int ic = 0;
if (algParams != null) {
try {
pbeSpec =
algParams.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
throw new IOException("Invalid PBE algorithm parameters");
}
ic = pbeSpec.getIterationCount();
if (ic > MAX_ITERATION_COUNT) {
throw new IOException("PBE iteration count too large");
}
}
byte[] keyInfo; byte[] keyInfo;
while (true) { while (true) {
try { try {
...@@ -376,9 +399,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -376,9 +399,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
key = kfac.generatePrivate(kspec); key = kfac.generatePrivate(kspec);
if (debug != null) { if (debug != null) {
debug.println("Retrieved a protected private key (" + debug.println("Retrieved a protected private key at alias" +
key.getClass().getName() + ") at alias '" + alias + " '" + alias + "' (" +
"'"); new AlgorithmId(algOid).getName() +
" iterations: " + ic + ")");
} }
// decode secret key // decode secret key
...@@ -399,9 +423,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -399,9 +423,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
} }
if (debug != null) { if (debug != null) {
debug.println("Retrieved a protected secret key (" + debug.println("Retrieved a protected secret key at alias " +
key.getClass().getName() + ") at alias '" + alias + "'" + alias + "' (" +
"'"); new AlgorithmId(algOid).getName() +
" iterations: " + ic + ")");
} }
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -576,9 +601,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -576,9 +601,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
(key.getFormat().equals("PKCS8"))) { (key.getFormat().equals("PKCS8"))) {
if (debug != null) { if (debug != null) {
debug.println("Setting a protected private key (" + debug.println(
key.getClass().getName() + ") at alias '" + alias + "Setting a protected private key at alias '" +
"'"); alias + "'");
} }
// Encrypt the private key // Encrypt the private key
...@@ -624,9 +649,8 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -624,9 +649,8 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
encryptPrivateKey(pkcs8.toByteArray(), passwordProtection); encryptPrivateKey(pkcs8.toByteArray(), passwordProtection);
if (debug != null) { if (debug != null) {
debug.println("Setting a protected secret key (" + debug.println("Setting a protected secret key at alias '" +
key.getClass().getName() + ") at alias '" + alias + alias + "'");
"'");
} }
secretKeyCount++; secretKeyCount++;
entry = keyEntry; entry = keyEntry;
...@@ -744,19 +768,19 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -744,19 +768,19 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
/* /*
* Generate PBE Algorithm Parameters * Generate PBE Algorithm Parameters
*/ */
private AlgorithmParameters getAlgorithmParameters(String algorithm) private AlgorithmParameters getPBEAlgorithmParameters(String algorithm)
throws IOException throws IOException
{ {
AlgorithmParameters algParams = null; AlgorithmParameters algParams = null;
// create PBE parameters from salt and iteration count // create PBE parameters from salt and iteration count
PBEParameterSpec paramSpec = PBEParameterSpec paramSpec =
new PBEParameterSpec(getSalt(), iterationCount); new PBEParameterSpec(getSalt(), PBE_ITERATION_COUNT);
try { try {
algParams = AlgorithmParameters.getInstance(algorithm); algParams = AlgorithmParameters.getInstance(algorithm);
algParams.init(paramSpec); algParams.init(paramSpec);
} catch (Exception e) { } catch (Exception e) {
throw new IOException("getAlgorithmParameters failed: " + throw new IOException("getPBEAlgorithmParameters failed: " +
e.getMessage(), e); e.getMessage(), e);
} }
return algParams; return algParams;
...@@ -842,7 +866,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -842,7 +866,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
algParams = AlgorithmParameters.getInstance(algorithm); algParams = AlgorithmParameters.getInstance(algorithm);
algParams.init(algParamSpec); algParams.init(algParamSpec);
} else { } else {
algParams = getAlgorithmParameters(algorithm); algParams = getPBEAlgorithmParameters(algorithm);
} }
} else { } else {
// Check default key protection algorithm for PKCS12 keystores // Check default key protection algorithm for PKCS12 keystores
...@@ -862,7 +886,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -862,7 +886,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (algorithm == null || algorithm.isEmpty()) { if (algorithm == null || algorithm.isEmpty()) {
algorithm = "PBEWithSHA1AndDESede"; algorithm = "PBEWithSHA1AndDESede";
} }
algParams = getAlgorithmParameters(algorithm); algParams = getPBEAlgorithmParameters(algorithm);
} }
ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm); ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm);
...@@ -1170,7 +1194,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1170,7 +1194,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (debug != null) { if (debug != null) {
debug.println("Storing " + (privateKeyCount + secretKeyCount) + debug.println("Storing " + (privateKeyCount + secretKeyCount) +
" protected key(s) in a PKCS#7 data content-type"); " protected key(s) in a PKCS#7 data");
} }
byte[] safeContentData = createSafeContent(); byte[] safeContentData = createSafeContent();
...@@ -1183,7 +1207,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1183,7 +1207,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (debug != null) { if (debug != null) {
debug.println("Storing " + certificateCount + debug.println("Storing " + certificateCount +
" certificate(s) in a PKCS#7 encryptedData content-type"); " certificate(s) in a PKCS#7 encryptedData");
} }
byte[] encrData = createEncryptedData(password); byte[] encrData = createEncryptedData(password);
...@@ -1454,7 +1478,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1454,7 +1478,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// generate MAC (MAC key is generated within JCE) // generate MAC (MAC key is generated within JCE)
Mac m = Mac.getInstance("HmacPBESHA1"); Mac m = Mac.getInstance("HmacPBESHA1");
PBEParameterSpec params = PBEParameterSpec params =
new PBEParameterSpec(salt, iterationCount); new PBEParameterSpec(salt, MAC_ITERATION_COUNT);
SecretKey key = getPBEKey(passwd); SecretKey key = getPBEKey(passwd);
m.init(key, params); m.init(key, params);
m.update(data); m.update(data);
...@@ -1462,7 +1486,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1462,7 +1486,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// encode as MacData // encode as MacData
MacData macData = new MacData(algName, macResult, salt, MacData macData = new MacData(algName, macResult, salt,
iterationCount); MAC_ITERATION_COUNT);
DerOutputStream bytes = new DerOutputStream(); DerOutputStream bytes = new DerOutputStream();
bytes.write(macData.getEncoded()); bytes.write(macData.getEncoded());
mData = bytes.toByteArray(); mData = bytes.toByteArray();
...@@ -1839,7 +1863,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1839,7 +1863,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// create AlgorithmParameters // create AlgorithmParameters
AlgorithmParameters algParams = AlgorithmParameters algParams =
getAlgorithmParameters("PBEWithSHA1AndRC2_40"); getPBEAlgorithmParameters("PBEWithSHA1AndRC2_40");
DerOutputStream bytes = new DerOutputStream(); DerOutputStream bytes = new DerOutputStream();
AlgorithmId algId = AlgorithmId algId =
new AlgorithmId(pbeWithSHAAnd40BitRC2CBC_OID, algParams); new AlgorithmId(pbeWithSHAAnd40BitRC2CBC_OID, algParams);
...@@ -1959,7 +1983,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1959,7 +1983,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (contentType.equals((Object)ContentInfo.DATA_OID)) { if (contentType.equals((Object)ContentInfo.DATA_OID)) {
if (debug != null) { if (debug != null) {
debug.println("Loading PKCS#7 data content-type"); debug.println("Loading PKCS#7 data");
} }
safeContentsData = safeContents.getData(); safeContentsData = safeContents.getData();
...@@ -1968,15 +1992,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1968,15 +1992,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (debug != null) { if (debug != null) {
debug.println("Warning: skipping PKCS#7 encryptedData" + debug.println("Warning: skipping PKCS#7 encryptedData" +
" content-type - no password was supplied"); " - no password was supplied");
} }
continue; continue;
} }
if (debug != null) {
debug.println("Loading PKCS#7 encryptedData content-type");
}
DerInputStream edi = DerInputStream edi =
safeContents.getContent().toDerInputStream(); safeContents.getContent().toDerInputStream();
int edVersion = edi.getInteger(); int edVersion = edi.getInteger();
...@@ -1997,6 +2017,30 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -1997,6 +2017,30 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
ObjectIdentifier algOid = in.getOID(); ObjectIdentifier algOid = in.getOID();
AlgorithmParameters algParams = parseAlgParameters(algOid, in); AlgorithmParameters algParams = parseAlgParameters(algOid, in);
PBEParameterSpec pbeSpec;
int ic = 0;
if (algParams != null) {
try {
pbeSpec =
algParams.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
throw new IOException(
"Invalid PBE algorithm parameters");
}
ic = pbeSpec.getIterationCount();
if (ic > MAX_ITERATION_COUNT) {
throw new IOException("PBE iteration count too large");
}
}
if (debug != null) {
debug.println("Loading PKCS#7 encryptedData " +
"(" + new AlgorithmId(algOid).getName() +
" iterations: " + ic + ")");
}
while (true) { while (true) {
try { try {
// Use JCE // Use JCE
...@@ -2027,8 +2071,15 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -2027,8 +2071,15 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// The MacData is optional. // The MacData is optional.
if (password != null && s.available() > 0) { if (password != null && s.available() > 0) {
MacData macData = new MacData(s); MacData macData = new MacData(s);
try { int ic = macData.getIterations();
try {
if (ic > MAX_ITERATION_COUNT) {
throw new InvalidAlgorithmParameterException(
"MAC iteration count too large: " + ic);
}
String algName = String algName =
macData.getDigestAlgName().toUpperCase(Locale.ENGLISH); macData.getDigestAlgName().toUpperCase(Locale.ENGLISH);
...@@ -2038,8 +2089,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -2038,8 +2089,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// generate MAC (MAC key is created within JCE) // generate MAC (MAC key is created within JCE)
Mac m = Mac.getInstance("HmacPBE" + algName); Mac m = Mac.getInstance("HmacPBE" + algName);
PBEParameterSpec params = PBEParameterSpec params =
new PBEParameterSpec(macData.getSalt(), new PBEParameterSpec(macData.getSalt(), ic);
macData.getIterations());
SecretKey key = getPBEKey(password); SecretKey key = getPBEKey(password);
m.init(key, params); m.init(key, params);
m.update(authSafeData); m.update(authSafeData);
...@@ -2047,16 +2097,16 @@ public final class PKCS12KeyStore extends KeyStoreSpi { ...@@ -2047,16 +2097,16 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (debug != null) { if (debug != null) {
debug.println("Checking keystore integrity " + debug.println("Checking keystore integrity " +
"(MAC algorithm: " + m.getAlgorithm() + ")"); "(" + m.getAlgorithm() + " iterations: " + ic + ")");
} }
if (!MessageDigest.isEqual(macData.getDigest(), macResult)) { if (!MessageDigest.isEqual(macData.getDigest(), macResult)) {
throw new UnrecoverableKeyException("Failed PKCS12" + throw new UnrecoverableKeyException("Failed PKCS12" +
" integrity checking"); " integrity checking");
} }
} catch (Exception e) { } catch (Exception e) {
throw new IOException("Integrity check failed: " + e, e); throw new IOException("Integrity check failed: " + e, e);
} }
} }
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册