8206189: sun/security/pkcs12/EmptyPassword.java fails with Sequence tag error
authorweijun
Thu, 12 Jul 2018 08:44:39 +0800
changeset 51063 038688fa32d0
parent 51062 53b0d5ad71db
child 51064 1a89ca728abd
8206189: sun/security/pkcs12/EmptyPassword.java fails with Sequence tag error Reviewed-by: xuelei
src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
--- a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Wed Jul 11 14:54:35 2018 -0700
+++ b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Thu Jul 12 08:44:39 2018 +0800
@@ -296,6 +296,9 @@
             } catch (Exception e) {
                 if (password.length == 0) {
                     // Retry using an empty password with a NUL terminator.
+                    if (debug != null) {
+                        debug.println("Retry with a NUL password");
+                    }
                     return f.tryOnce(new char[1]);
                 }
                 throw e;
@@ -376,7 +379,7 @@
 
        try {
             PBEParameterSpec pbeSpec;
-            int ic = 0;
+            int ic;
 
             if (algParams != null) {
                 try {
@@ -390,65 +393,69 @@
                 if (ic > MAX_ITERATION_COUNT) {
                     throw new IOException("PBE iteration count too large");
                 }
+            } else {
+                ic = 0;
             }
 
-            byte[] keyInfo = RetryWithZero.run(pass -> {
+            key = RetryWithZero.run(pass -> {
                 // Use JCE
                 SecretKey skey = getPBEKey(pass);
                 Cipher cipher = Cipher.getInstance(
                         mapPBEParamsToAlgorithm(algOid, algParams));
                 cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
-                return cipher.doFinal(encryptedKey);
+                byte[] keyInfo = cipher.doFinal(encryptedKey);
+                /*
+                 * Parse the key algorithm and then use a JCA key factory
+                 * to re-create the key.
+                 */
+                DerValue val = new DerValue(keyInfo);
+                DerInputStream in = val.toDerInputStream();
+                int i = in.getInteger();
+                DerValue[] value = in.getSequence(2);
+                AlgorithmId algId = new AlgorithmId(value[0].getOID());
+                String keyAlgo = algId.getName();
+
+                // decode private key
+                if (entry instanceof PrivateKeyEntry) {
+                    KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
+                    PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
+                    Key tmp = kfac.generatePrivate(kspec);
+
+                    if (debug != null) {
+                        debug.println("Retrieved a protected private key at alias" +
+                                " '" + alias + "' (" +
+                                new AlgorithmId(algOid).getName() +
+                                " iterations: " + ic + ")");
+                    }
+                    return tmp;
+                    // decode secret key
+                } else {
+                    byte[] keyBytes = in.getOctetString();
+                    SecretKeySpec secretKeySpec =
+                            new SecretKeySpec(keyBytes, keyAlgo);
+
+                    // Special handling required for PBE: needs a PBEKeySpec
+                    Key tmp;
+                    if (keyAlgo.startsWith("PBE")) {
+                        SecretKeyFactory sKeyFactory =
+                                SecretKeyFactory.getInstance(keyAlgo);
+                        KeySpec pbeKeySpec =
+                                sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class);
+                        tmp = sKeyFactory.generateSecret(pbeKeySpec);
+                    } else {
+                        tmp = secretKeySpec;
+                    }
+
+                    if (debug != null) {
+                        debug.println("Retrieved a protected secret key at alias " +
+                                "'" + alias + "' (" +
+                                new AlgorithmId(algOid).getName() +
+                                " iterations: " + ic + ")");
+                    }
+                    return tmp;
+                }
             }, password);
 
-            /*
-             * Parse the key algorithm and then use a JCA key factory
-             * to re-create the key.
-             */
-            DerValue val = new DerValue(keyInfo);
-            DerInputStream in = val.toDerInputStream();
-            int i = in.getInteger();
-            DerValue[] value = in.getSequence(2);
-            AlgorithmId algId = new AlgorithmId(value[0].getOID());
-            String keyAlgo = algId.getName();
-
-            // decode private key
-            if (entry instanceof PrivateKeyEntry) {
-                KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
-                PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
-                key = kfac.generatePrivate(kspec);
-
-                if (debug != null) {
-                    debug.println("Retrieved a protected private key at alias" +
-                        " '" + alias + "' (" +
-                        new AlgorithmId(algOid).getName() +
-                        " iterations: " + ic + ")");
-                }
-
-            // decode secret key
-            } else {
-                byte[] keyBytes = in.getOctetString();
-                SecretKeySpec secretKeySpec =
-                    new SecretKeySpec(keyBytes, keyAlgo);
-
-                // Special handling required for PBE: needs a PBEKeySpec
-                if (keyAlgo.startsWith("PBE")) {
-                    SecretKeyFactory sKeyFactory =
-                        SecretKeyFactory.getInstance(keyAlgo);
-                    KeySpec pbeKeySpec =
-                        sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class);
-                    key = sKeyFactory.generateSecret(pbeKeySpec);
-                } else {
-                    key = secretKeySpec;
-                }
-
-                if (debug != null) {
-                    debug.println("Retrieved a protected secret key at alias " +
-                        "'" + alias + "' (" +
-                        new AlgorithmId(algOid).getName() +
-                        " iterations: " + ic + ")");
-                }
-            }
         } catch (Exception e) {
             UnrecoverableKeyException uke =
                 new UnrecoverableKeyException("Get Key failed: " +
@@ -2019,7 +2026,6 @@
          * Spin over the ContentInfos.
          */
         for (int i = 0; i < count; i++) {
-            byte[] safeContentsData;
             ContentInfo safeContents;
             DerInputStream sci;
             byte[] eAlgId = null;
@@ -2027,14 +2033,13 @@
             sci = new DerInputStream(safeContentsArray[i].toByteArray());
             safeContents = new ContentInfo(sci);
             contentType = safeContents.getContentType();
-            safeContentsData = null;
             if (contentType.equals(ContentInfo.DATA_OID)) {
 
                 if (debug != null) {
                     debug.println("Loading PKCS#7 data");
                 }
 
-                safeContentsData = safeContents.getData();
+                loadSafeContents(new DerInputStream(safeContents.getData()));
             } else if (contentType.equals(ContentInfo.ENCRYPTED_DATA_OID)) {
                 if (password == null) {
 
@@ -2058,7 +2063,7 @@
                 if (seq[2].isConstructed())
                    newTag |= 0x20;
                 seq[2].resetTag(newTag);
-                safeContentsData = seq[2].getOctetString();
+                byte[] rawData = seq[2].getOctetString();
 
                 // parse Algorithm parameters
                 DerInputStream in = seq[1].toDerInputStream();
@@ -2089,14 +2094,14 @@
                         " iterations: " + ic + ")");
                 }
 
-                byte[] rawData = safeContentsData;
                 try {
-                    safeContentsData = RetryWithZero.run(pass -> {
+                    RetryWithZero.run(pass -> {
                         // Use JCE
                         SecretKey skey = getPBEKey(pass);
                         Cipher cipher = Cipher.getInstance(algOid.toString());
                         cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
-                        return cipher.doFinal(rawData);
+                        loadSafeContents(new DerInputStream(cipher.doFinal(rawData)));
+                        return null;
                     }, password);
                 } catch (Exception e) {
                     throw new IOException("keystore password was incorrect",
@@ -2107,8 +2112,6 @@
                 throw new IOException("public key protected PKCS12" +
                                         " not supported");
             }
-            DerInputStream sc = new DerInputStream(safeContentsData);
-            loadSafeContents(sc, password);
         }
 
         // The MacData is optional.
@@ -2242,7 +2245,7 @@
         else return null;
     }
 
-    private void loadSafeContents(DerInputStream stream, char[] password)
+    private void loadSafeContents(DerInputStream stream)
         throws IOException, NoSuchAlgorithmException, CertificateException
     {
         DerValue[] safeBags = stream.getSequence(2);