# HG changeset patch # User igerasim # Date 1511254311 0 # Node ID 0ba2494b89d252abf36ca7fcb70003b1f7647219 # Parent 58de21cbceaf8a5615fb812046ed161cb72a62a4 8181692: Update storage implementations Reviewed-by: weijun, igerasim diff -r 58de21cbceaf -r 0ba2494b89d2 src/share/classes/com/sun/crypto/provider/KeyProtector.java --- a/src/share/classes/com/sun/crypto/provider/KeyProtector.java Wed Oct 14 16:45:43 2015 +0100 +++ b/src/share/classes/com/sun/crypto/provider/KeyProtector.java Tue Nov 21 08:51:51 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, 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; @@ -102,7 +105,7 @@ SunJCE.RANDOM.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); @@ -157,6 +160,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); @@ -287,7 +293,7 @@ SunJCE.RANDOM.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); @@ -328,6 +334,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, PROV, diff -r 58de21cbceaf -r 0ba2494b89d2 src/share/classes/com/sun/crypto/provider/PBECipherCore.java --- a/src/share/classes/com/sun/crypto/provider/PBECipherCore.java Wed Oct 14 16:45:43 2015 +0100 +++ b/src/share/classes/com/sun/crypto/provider/PBECipherCore.java Tue Nov 21 08:51:51 2017 +0000 @@ -288,7 +288,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 58de21cbceaf -r 0ba2494b89d2 src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java --- a/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Wed Oct 14 16:45:43 2015 +0100 +++ b/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Tue Nov 21 08:51:51 2017 +0000 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -41,11 +41,13 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; +import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.util.*; import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; import javax.crypto.spec.PBEParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; @@ -129,6 +131,11 @@ public static final int VERSION_3 = 3; + 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", @@ -172,8 +179,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,7 +332,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 { @@ -366,9 +388,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 @@ -389,9 +412,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) { @@ -554,9 +578,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 @@ -602,9 +626,8 @@ encryptPrivateKey(pkcs8.toByteArray(), password); 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; @@ -722,19 +745,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; @@ -804,7 +827,7 @@ try { // create AlgorithmParameters AlgorithmParameters algParams = - getAlgorithmParameters("PBEWithSHA1AndDESede"); + getPBEAlgorithmParameters("PBEWithSHA1AndDESede"); // Use JCE SecretKey skey = getPBEKey(password); @@ -1082,7 +1105,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(); @@ -1095,7 +1118,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); @@ -1371,7 +1394,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); @@ -1379,7 +1402,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(); @@ -1756,7 +1779,7 @@ // create AlgorithmParameters AlgorithmParameters algParams = - getAlgorithmParameters("PBEWithSHA1AndRC2_40"); + getPBEAlgorithmParameters("PBEWithSHA1AndRC2_40"); DerOutputStream bytes = new DerOutputStream(); AlgorithmId algId = new AlgorithmId(pbeWithSHAAnd40BitRC2CBC_OID, algParams); @@ -1848,7 +1871,7 @@ if (contentType.equals((Object)ContentInfo.DATA_OID)) { if (debug != null) { - debug.println("Loading PKCS#7 data content-type"); + debug.println("Loading PKCS#7 data"); } authSafeData = authSafe.getData(); @@ -1885,7 +1908,7 @@ if (debug != null) { debug.println("Warning: skipping PKCS#7 encryptedData" + - " content-type - no password was supplied"); + " - no password was supplied"); } continue; } @@ -1909,6 +1932,30 @@ ObjectIdentifier algOid = in.getOID(); AlgorithmParameters algParams = parseAlgParameters(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 @@ -1939,8 +1986,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); @@ -1950,8 +2004,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); @@ -1959,16 +2012,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 SecurityException("Failed PKCS12" + " integrity checking"); } - } catch (Exception e) { + } catch (Exception e) { throw new IOException("Integrity check failed: " + e, e); - } + } } /*