# HG changeset patch # User vinnie # Date 1499272066 -3600 # Node ID 5984d1c9d03db1ac4eca481984440e273f27e68b # Parent a627f88bed3a89e9e938c29aef5862f492e3b291 8181692: Update storage implementations Reviewed-by: weijun, igerasim diff -r a627f88bed3a -r 5984d1c9d03d src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java --- a/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java Wed Jun 28 16:52:36 2017 +0100 +++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java Wed Jul 05 17:27:46 2017 +0100 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import java.security.NoSuchProviderException; import java.security.UnrecoverableKeyException; import java.security.AlgorithmParameters; +import java.security.spec.InvalidParameterSpecException; import java.security.spec.PKCS8EncodedKeySpec; import javax.crypto.Cipher; @@ -74,6 +75,8 @@ // 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 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 DIGEST_LEN = 20; @@ -100,7 +103,7 @@ SunJCE.getRandom().nextBytes(salt); // 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 PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password); @@ -155,6 +158,9 @@ pbeParams.init(encodedParams); PBEParameterSpec pbeSpec = pbeParams.getParameterSpec(PBEParameterSpec.class); + if (pbeSpec.getIterationCount() > MAX_ITERATION_COUNT) { + throw new IOException("PBE iteration count too large"); + } // create PBE key from password PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password); @@ -285,7 +291,7 @@ SunJCE.getRandom().nextBytes(salt); // 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 PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password); @@ -326,6 +332,15 @@ throw new UnrecoverableKeyException("Cannot get " + "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; cipherSpi = new PBEWithMD5AndTripleDESCipher(); Cipher cipher = new CipherForKeyProtector(cipherSpi, diff -r a627f88bed3a -r 5984d1c9d03d src/java.base/share/classes/com/sun/crypto/provider/PBES1Core.java --- a/src/java.base/share/classes/com/sun/crypto/provider/PBES1Core.java Wed Jun 28 16:52:36 2017 +0100 +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES1Core.java Wed Jul 05 17:27:46 2017 +0100 @@ -284,7 +284,7 @@ for (i=0; i<2; i++) { byte tmp = salt[i]; salt[i] = salt[3-i]; - salt[3-1] = tmp; + salt[3-i] = tmp; } } diff -r a627f88bed3a -r 5984d1c9d03d src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java --- a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Wed Jun 28 16:52:36 2017 +0100 +++ b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Wed Jul 05 17:27:46 2017 +0100 @@ -46,6 +46,7 @@ import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.util.*; @@ -147,6 +148,11 @@ "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 private static final String[] CORE_ATTRIBUTES = { "1.2.840.113549.1.9.20", @@ -192,8 +198,6 @@ private static ObjectIdentifier[] AnyUsage; private int counter = 0; - private static final int iterationCount = 1024; - private static final int SALT_LEN = 20; // private key count // Note: This is a workaround to allow null localKeyID attribute @@ -327,6 +331,7 @@ byte[] encryptedKey; AlgorithmParameters algParams; ObjectIdentifier algOid; + try { // get the encrypted private key EncryptedPrivateKeyInfo encrInfo = @@ -347,7 +352,24 @@ 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; while (true) { try { @@ -387,9 +409,10 @@ key = kfac.generatePrivate(kspec); if (debug != null) { - debug.println("Retrieved a protected private key (" + - key.getClass().getName() + ") at alias '" + alias + - "'"); + debug.println("Retrieved a protected private key at alias" + + " '" + alias + "' (" + + new AlgorithmId(algOid).getName() + + " iterations: " + ic + ")"); } // decode secret key @@ -410,9 +433,10 @@ } if (debug != null) { - debug.println("Retrieved a protected secret key (" + - key.getClass().getName() + ") at alias '" + alias + - "'"); + debug.println("Retrieved a protected secret key at alias " + + "'" + alias + "' (" + + new AlgorithmId(algOid).getName() + + " iterations: " + ic + ")"); } } } catch (Exception e) { @@ -590,9 +614,9 @@ (key.getFormat().equals("PKCS8"))) { if (debug != null) { - debug.println("Setting a protected private key (" + - key.getClass().getName() + ") at alias '" + alias + - "'"); + debug.println( + "Setting a protected private key at alias '" + + alias + "'"); } // Encrypt the private key @@ -638,9 +662,8 @@ encryptPrivateKey(pkcs8.toByteArray(), passwordProtection); if (debug != null) { - debug.println("Setting a protected secret key (" + - key.getClass().getName() + ") at alias '" + alias + - "'"); + debug.println("Setting a protected secret key at alias '" + + alias + "'"); } secretKeyCount++; entry = keyEntry; @@ -761,19 +784,19 @@ /* * Generate PBE Algorithm Parameters */ - private AlgorithmParameters getAlgorithmParameters(String algorithm) + private AlgorithmParameters getPBEAlgorithmParameters(String algorithm) throws IOException { AlgorithmParameters algParams = null; // create PBE parameters from salt and iteration count PBEParameterSpec paramSpec = - new PBEParameterSpec(getSalt(), iterationCount); + new PBEParameterSpec(getSalt(), PBE_ITERATION_COUNT); try { algParams = AlgorithmParameters.getInstance(algorithm); algParams.init(paramSpec); } catch (Exception e) { - throw new IOException("getAlgorithmParameters failed: " + + throw new IOException("getPBEAlgorithmParameters failed: " + e.getMessage(), e); } return algParams; @@ -859,7 +882,7 @@ algParams = AlgorithmParameters.getInstance(algorithm); algParams.init(algParamSpec); } else { - algParams = getAlgorithmParameters(algorithm); + algParams = getPBEAlgorithmParameters(algorithm); } } else { // Check default key protection algorithm for PKCS12 keystores @@ -879,7 +902,7 @@ if (algorithm == null || algorithm.isEmpty()) { algorithm = "PBEWithSHA1AndDESede"; } - algParams = getAlgorithmParameters(algorithm); + algParams = getPBEAlgorithmParameters(algorithm); } ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm); @@ -1194,7 +1217,7 @@ if (debug != null) { 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(); @@ -1207,7 +1230,7 @@ if (debug != null) { debug.println("Storing " + certificateCount + - " certificate(s) in a PKCS#7 encryptedData content-type"); + " certificate(s) in a PKCS#7 encryptedData"); } byte[] encrData = createEncryptedData(password); @@ -1478,7 +1501,7 @@ // generate MAC (MAC key is generated within JCE) Mac m = Mac.getInstance("HmacPBESHA1"); PBEParameterSpec params = - new PBEParameterSpec(salt, iterationCount); + new PBEParameterSpec(salt, MAC_ITERATION_COUNT); SecretKey key = getPBEKey(passwd); m.init(key, params); m.update(data); @@ -1486,7 +1509,7 @@ // encode as MacData MacData macData = new MacData(algName, macResult, salt, - iterationCount); + MAC_ITERATION_COUNT); DerOutputStream bytes = new DerOutputStream(); bytes.write(macData.getEncoded()); mData = bytes.toByteArray(); @@ -1878,7 +1901,7 @@ // create AlgorithmParameters AlgorithmParameters algParams = - getAlgorithmParameters("PBEWithSHA1AndRC2_40"); + getPBEAlgorithmParameters("PBEWithSHA1AndRC2_40"); DerOutputStream bytes = new DerOutputStream(); AlgorithmId algId = new AlgorithmId(pbeWithSHAAnd40BitRC2CBC_OID, algParams); @@ -1998,7 +2021,7 @@ if (contentType.equals(ContentInfo.DATA_OID)) { if (debug != null) { - debug.println("Loading PKCS#7 data content-type"); + debug.println("Loading PKCS#7 data"); } safeContentsData = safeContents.getData(); @@ -2007,15 +2030,11 @@ if (debug != null) { debug.println("Warning: skipping PKCS#7 encryptedData" + - " content-type - no password was supplied"); + " - no password was supplied"); } continue; } - if (debug != null) { - debug.println("Loading PKCS#7 encryptedData content-type"); - } - DerInputStream edi = safeContents.getContent().toDerInputStream(); int edVersion = edi.getInteger(); @@ -2036,6 +2055,30 @@ ObjectIdentifier algOid = in.getOID(); 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) { try { // Use JCE @@ -2066,8 +2109,15 @@ // The MacData is optional. if (password != null && s.available() > 0) { - MacData macData = new MacData(s); - try { + MacData macData = new MacData(s); + int ic = macData.getIterations(); + + try { + if (ic > MAX_ITERATION_COUNT) { + throw new InvalidAlgorithmParameterException( + "MAC iteration count too large: " + ic); + } + String algName = macData.getDigestAlgName().toUpperCase(Locale.ENGLISH); @@ -2077,8 +2127,7 @@ // generate MAC (MAC key is created within JCE) Mac m = Mac.getInstance("HmacPBE" + algName); PBEParameterSpec params = - new PBEParameterSpec(macData.getSalt(), - macData.getIterations()); + new PBEParameterSpec(macData.getSalt(), ic); SecretKey key = getPBEKey(password); m.init(key, params); m.update(authSafeData); @@ -2086,16 +2135,16 @@ if (debug != null) { debug.println("Checking keystore integrity " + - "(MAC algorithm: " + m.getAlgorithm() + ")"); + "(" + m.getAlgorithm() + " iterations: " + ic + ")"); } if (!MessageDigest.isEqual(macData.getDigest(), macResult)) { throw new UnrecoverableKeyException("Failed PKCS12" + " integrity checking"); } - } catch (Exception e) { + } catch (Exception e) { throw new IOException("Integrity check failed: " + e, e); - } + } } /*