changeset 13365:4d34e8d3d971

Merge
author aefimov
date Wed, 26 Sep 2018 15:31:48 +0100
parents 2cf0eb69a288 c76b8fd5fa12
children 8f2bdd3d7752
files .hgtags
diffstat 22 files changed, 736 insertions(+), 353 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Sep 17 15:06:15 2018 +0100
+++ b/.hgtags	Wed Sep 26 15:31:48 2018 +0100
@@ -937,3 +937,9 @@
 7556b6a2aa3266fb4a213c4fbbca2a403d4df306 jdk8u192-b08
 f47b81dbed2dd730d34a8dc3e3d14e2aa9f9c493 jdk8u192-b09
 621105274477152934059d58a116222f09d966a2 jdk8u192-b10
+38b4a5b97f38c467446f1767d148075ac98397d1 jdk8u181-b31
+d679861a9a1efc80e0671b1c6b870fcffbfb9d9c jdk8u181-b32
+078a06936ffe2db2a00e928f88c6e345a126985a jdk8u181-b33
+ecfdede1e6ddf37dcca415861ab031c18ec4b349 jdk8u181-b34
+ac943243eaf1cb3971b953d56527287ae3f8d223 jdk8u181-b35
+674963395b9f747e746af782f2f3ea7995385420 jdk8u181-b36
--- a/src/share/classes/com/sun/crypto/provider/CipherCore.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java	Wed Sep 26 15:31:48 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -673,7 +673,12 @@
             if (len == output.length) {
                 return output;
             } else {
-                return Arrays.copyOf(output, len);
+                byte[] copy = Arrays.copyOf(output, len);
+                if (decrypting) {
+                    // Zero out internal buffer which is no longer required
+                    Arrays.fill(output, (byte) 0x00);
+                }
+                return copy;
             }
         } catch (ShortBufferException e) {
             // should never happen
@@ -767,11 +772,14 @@
                         inputLen -= temp;
                         buffered = Math.addExact(buffered, temp);
                     }
-                    // process 'buffer'
+                    // process 'buffer'. When finished we can null out 'buffer'
+                    // Only necessary to null out if buffer holds data for encryption
                     if (decrypting) {
                          outLen = cipher.decrypt(buffer, 0, buffered, output, outputOffset);
                     } else {
                          outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset);
+                         //encrypt mode. Zero out internal (input) buffer
+                         Arrays.fill(buffer, (byte) 0x00);
                     }
                     outputOffset = Math.addExact(outputOffset, outLen);
                     buffered = 0;
@@ -846,7 +854,12 @@
             output = new byte[getOutputSizeByOperation(inputLen, true)];
             int len = doFinal(input, inputOffset, inputLen, output, 0);
             if (len < output.length) {
-                return Arrays.copyOf(output, len);
+                byte[] copy = Arrays.copyOf(output, len);
+                if (decrypting) {
+                    // Zero out internal (ouput) array
+                    Arrays.fill(output, (byte) 0x00);
+                }
+                return copy;
             } else {
                 return output;
             }
@@ -959,6 +972,11 @@
             finalOffset = 0;
             if (buffered != 0) {
                 System.arraycopy(buffer, 0, finalBuf, 0, buffered);
+                if (!decrypting) {
+                    // done with input buffer. We should zero out the
+                    // data if we're in encrypt mode.
+                    Arrays.fill(buffer, (byte) 0x00);
+                }
             }
             if (inputLen != 0) {
                 System.arraycopy(input, inputOffset, finalBuf,
@@ -1005,6 +1023,8 @@
             }
             // copy the result into user-supplied output buffer
             System.arraycopy(outWithPadding, 0, output, outputOffset, outLen);
+            // decrypt mode. Zero out output data that's not required
+            Arrays.fill(outWithPadding, (byte) 0x00);
         } else { // encrypting
             try {
                 outLen = finalNoPadding(finalBuf, finalOffset, output,
@@ -1012,6 +1032,10 @@
             } finally {
                 // reset after doFinal() for GCM encryption
                 requireReinit = (cipherMode == GCM_MODE);
+                if (finalBuf != input) {
+                    // done with internal finalBuf array. Copied to output
+                    Arrays.fill(finalBuf, (byte) 0x00);
+                }
             }
         }
 
--- a/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java	Wed Sep 26 15:31:48 2018 +0100
@@ -73,62 +73,69 @@
             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)) {
+
+        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
+                            ("PBEParameterSpec required for salt and iteration count");
+                }
+            } else if (!(params instanceof PBEParameterSpec)) {
                 throw new InvalidAlgorithmParameterException
-                    ("PBEParameterSpec required for salt and iteration count");
+                        ("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 {
+                    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 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 {
-                salt = pbeParams.getSalt();
+            // 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) {
-                if (iCount != pbeParams.getIterationCount()) {
-                    throw new InvalidAlgorithmParameterException
-                        ("Different iteration count between key and params");
-                }
-            } else {
-                iCount = pbeParams.getIterationCount();
+            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);
     }
--- a/src/share/classes/com/sun/crypto/provider/KeyProtector.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/KeyProtector.java	Wed Sep 26 15:31:48 2018 +0100
@@ -37,12 +37,15 @@
 import java.security.AlgorithmParameters;
 import java.security.spec.InvalidParameterSpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Arrays;
 
 import javax.crypto.Cipher;
 import javax.crypto.CipherSpi;
 import javax.crypto.SecretKey;
 import javax.crypto.SealedObject;
 import javax.crypto.spec.*;
+import javax.security.auth.DestroyFailedException;
+
 import sun.security.x509.AlgorithmId;
 import sun.security.util.ObjectIdentifier;
 
@@ -103,15 +106,20 @@
 
         // create PBE key from password
         PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
-        SecretKey sKey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES");
-        pbeKeySpec.clearPassword();
-
-        // encrypt private key
+        SecretKey sKey = null;
         PBEWithMD5AndTripleDESCipher cipher;
-        cipher = new PBEWithMD5AndTripleDESCipher();
-        cipher.engineInit(Cipher.ENCRYPT_MODE, sKey, pbeSpec, null);
+        try {
+            sKey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES");
+            // encrypt private key
+            cipher = new PBEWithMD5AndTripleDESCipher();
+            cipher.engineInit(Cipher.ENCRYPT_MODE, sKey, pbeSpec, null);
+        } finally {
+            pbeKeySpec.clearPassword();
+            if (sKey != null) sKey.destroy();
+        }
         byte[] plain = key.getEncoded();
         byte[] encrKey = cipher.engineDoFinal(plain, 0, plain.length);
+        Arrays.fill(plain, (byte)0x00);
 
         // wrap encrypted private key in EncryptedPrivateKeyInfo
         // (as defined in PKCS#8)
@@ -131,8 +139,8 @@
     Key recover(EncryptedPrivateKeyInfo encrInfo)
         throws UnrecoverableKeyException, NoSuchAlgorithmException
     {
-        byte[] plain;
-
+        byte[] plain = null;
+        SecretKey sKey = null;
         try {
             String encrAlg = encrInfo.getAlgorithm().getOID().toString();
             if (!encrAlg.equals(PBE_WITH_MD5_AND_DES3_CBC_OID)
@@ -160,8 +168,7 @@
 
                 // create PBE key from password
                 PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
-                SecretKey sKey =
-                    new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES");
+                sKey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES");
                 pbeKeySpec.clearPassword();
 
                 // decrypt private key
@@ -178,7 +185,6 @@
                 (new PrivateKeyInfo(plain).getAlgorithm().getOID()).getName();
             KeyFactory kFac = KeyFactory.getInstance(oidName);
             return kFac.generatePrivate(new PKCS8EncodedKeySpec(plain));
-
         } catch (NoSuchAlgorithmException ex) {
             // Note: this catch needed to be here because of the
             // later catch of GeneralSecurityException
@@ -187,6 +193,15 @@
             throw new UnrecoverableKeyException(ioe.getMessage());
         } catch (GeneralSecurityException gse) {
             throw new UnrecoverableKeyException(gse.getMessage());
+        } finally {
+            if (plain != null) Arrays.fill(plain, (byte)0x00);
+            if (sKey != null) {
+                try {
+                    sKey.destroy();
+                } catch (DestroyFailedException e) {
+                    //shouldn't happen
+                }
+            }
         }
     }
 
@@ -262,7 +277,7 @@
         // of <code>protectedKey</code>. If the two digest values are
         // different, throw an exception.
         md.update(passwdBytes);
-        java.util.Arrays.fill(passwdBytes, (byte)0x00);
+        Arrays.fill(passwdBytes, (byte)0x00);
         passwdBytes = null;
         md.update(plainKey);
         digest = md.digest();
@@ -291,17 +306,21 @@
 
         // create PBE key from password
         PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
-        SecretKey sKey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES");
-        pbeKeySpec.clearPassword();
+        SecretKey sKey = null;
+        Cipher cipher;
+        try {
+            sKey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES");
+            pbeKeySpec.clearPassword();
 
-        // seal key
-        Cipher cipher;
-
-        PBEWithMD5AndTripleDESCipher cipherSpi;
-        cipherSpi = new PBEWithMD5AndTripleDESCipher();
-        cipher = new CipherForKeyProtector(cipherSpi, SunJCE.getInstance(),
+            // seal key
+            PBEWithMD5AndTripleDESCipher cipherSpi;
+            cipherSpi = new PBEWithMD5AndTripleDESCipher();
+            cipher = new CipherForKeyProtector(cipherSpi, SunJCE.getInstance(),
                                            "PBEWithMD5AndTripleDES");
-        cipher.init(Cipher.ENCRYPT_MODE, sKey, pbeSpec);
+            cipher.init(Cipher.ENCRYPT_MODE, sKey, pbeSpec);
+        } finally {
+            if (sKey != null) sKey.destroy();
+        }
         return new SealedObjectForKeyProtector(key, cipher);
     }
 
@@ -309,12 +328,12 @@
      * Unseals the sealed key.
      */
     Key unseal(SealedObject so)
-        throws NoSuchAlgorithmException, UnrecoverableKeyException
-    {
+        throws NoSuchAlgorithmException, UnrecoverableKeyException {
+        SecretKey sKey = null;
         try {
             // create PBE key from password
             PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
-            SecretKey skey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES");
+            sKey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES");
             pbeKeySpec.clearPassword();
 
             SealedObjectForKeyProtector soForKeyProtector = null;
@@ -342,7 +361,7 @@
             Cipher cipher = new CipherForKeyProtector(cipherSpi,
                                                       SunJCE.getInstance(),
                                                       "PBEWithMD5AndTripleDES");
-            cipher.init(Cipher.DECRYPT_MODE, skey, params);
+            cipher.init(Cipher.DECRYPT_MODE, sKey, params);
             return soForKeyProtector.getKey(cipher);
         } catch (NoSuchAlgorithmException ex) {
             // Note: this catch needed to be here because of the
@@ -354,6 +373,14 @@
             throw new UnrecoverableKeyException(cnfe.getMessage());
         } catch (GeneralSecurityException gse) {
             throw new UnrecoverableKeyException(gse.getMessage());
+        } finally {
+            if (sKey != null) {
+                try {
+                    sKey.destroy();
+                } catch (DestroyFailedException e) {
+                    //shouldn't happen
+                }
+            }
         }
     }
 }
--- a/src/share/classes/com/sun/crypto/provider/PBEKey.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBEKey.java	Wed Sep 26 15:31:48 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -28,6 +28,7 @@
 import java.security.MessageDigest;
 import java.security.KeyRep;
 import java.security.spec.InvalidKeySpecException;
+import java.util.Arrays;
 import java.util.Locale;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.PBEKeySpec;
@@ -68,7 +69,7 @@
         this.key = new byte[passwd.length];
         for (int i=0; i<passwd.length; i++)
             this.key[i] = (byte) (passwd[i] & 0x7f);
-        java.util.Arrays.fill(passwd, ' ');
+        Arrays.fill(passwd, '\0');
         type = keytype;
     }
 
@@ -110,11 +111,23 @@
 
         byte[] thatEncoded = that.getEncoded();
         boolean ret = MessageDigest.isEqual(this.key, thatEncoded);
-        java.util.Arrays.fill(thatEncoded, (byte)0x00);
+        Arrays.fill(thatEncoded, (byte)0x00);
         return ret;
     }
 
     /**
+     * Clears the internal copy of the key.
+     *
+     */
+    @Override
+    public void destroy() {
+        if (key != null) {
+            Arrays.fill(key, (byte)0x00);
+            key = null;
+        }
+    }
+
+    /**
      * readObject is called to restore the state of this key from
      * a stream.
      */
--- a/src/share/classes/com/sun/crypto/provider/PBES1Core.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBES1Core.java	Wed Sep 26 15:31:48 2018 +0100
@@ -27,6 +27,7 @@
 
 import java.security.*;
 import java.security.spec.*;
+import java.util.Arrays;
 import javax.crypto.*;
 import javax.crypto.spec.*;
 
@@ -213,35 +214,43 @@
             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");
+        byte[] derivedKey;
+        byte[] passwdBytes = key.getEncoded();
+        try {
+            if ((passwdBytes == null) ||
+                    !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
+                throw new InvalidKeyException("Missing password");
             }
-            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");
+
+            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");
+                }
             }
-            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 @@
         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 @@
                 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 @@
             // 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 @@
                 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 @@
     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 @@
             result = doFinal(encodedKey, 0, encodedKey.length);
         } catch (BadPaddingException e) {
             // Should never happen
+        } finally {
+            if (encodedKey != null) Arrays.fill(encodedKey, (byte)0x00);
         }
 
         return result;
--- a/src/share/classes/com/sun/crypto/provider/PBES2Core.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBES2Core.java	Wed Sep 26 15:31:48 2018 +0100
@@ -27,6 +27,7 @@
 
 import java.security.*;
 import java.security.spec.*;
+import java.util.Arrays;
 import javax.crypto.*;
 import javax.crypto.spec.*;
 
@@ -173,101 +174,105 @@
                               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
+        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 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");
+            // 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");
+                }
             }
-            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");
-            }
-        }
 
-        // 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) ||
+            // 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;
+                    // 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;
 
-            AlgorithmParameterSpec specParams =
-                ((PBEParameterSpec) params).getParameterSpec();
-            if (specParams != null) {
-                if (specParams instanceof IvParameterSpec) {
-                    ivSpec = (IvParameterSpec)specParams;
+                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(
-                        "Wrong parameter type: IV expected");
+                            "Missing 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];
+            passwdChars = new char[passwdBytes.length];
+            for (int i = 0; i < passwdChars.length; i++)
+                passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
 
-        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 @@
             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);
--- a/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Wed Sep 26 15:31:48 2018 +0100
@@ -89,6 +89,8 @@
         }
         // 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 @@
         }
         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 @@
         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 @@
         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) {
--- a/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java	Wed Sep 26 15:31:48 2018 +0100
@@ -108,72 +108,76 @@
             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)) {
+
+        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
+                            ("PBEParameterSpec required for salt and iteration count");
+                }
+            } else if (!(params instanceof PBEParameterSpec)) {
                 throw new InvalidAlgorithmParameterException
-                    ("PBEParameterSpec required for salt and iteration count");
+                        ("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 {
+                    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 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 {
-                salt = pbeParams.getSalt();
+            // 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) {
-                if (iCount != pbeParams.getIterationCount()) {
-                    throw new InvalidAlgorithmParameterException
-                        ("Different iteration count between key and params");
-                }
-            } else {
-                iCount = pbeParams.getIterationCount();
+            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");
+
+            pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, blockLength);
+            // password char[] was cloned in PBEKeySpec constructor,
+            // so we can zero it out here
+        } finally {
+            Arrays.fill(passwdChars, '\0');
         }
 
-        PBEKeySpec 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, ' ');
-
-        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");
--- a/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Wed Sep 26 15:31:48 2018 +0100
@@ -103,6 +103,7 @@
             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 @@
             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) {
+                    if (iCount != pbeParams.getIterationCount()) {
+                        throw new InvalidAlgorithmParameterException
+                                ("Different iteration count between key and params");
+                    }
+                } else {
+                    iCount = pbeParams.getIterationCount();
                 }
             }
-            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");
-                }
+            // 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 (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
+                ((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
+
             } else {
-                salt = pbeParams.getSalt();
+                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);
             }
-            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");
-        }
-        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);
-
-        } 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);
+        } finally {
+           Arrays.fill(passwdChars, '\0');
         }
     }
 
--- a/src/share/classes/javax/crypto/spec/PBEKeySpec.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/javax/crypto/spec/PBEKeySpec.java	Wed Sep 26 15:31:48 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -26,6 +26,7 @@
 package javax.crypto.spec;
 
 import java.security.spec.KeySpec;
+import java.util.Arrays;
 
 /**
  * A user-chosen password that can be used with password-based encryption
@@ -174,9 +175,7 @@
      */
     public final void clearPassword() {
         if (password != null) {
-            for (int i = 0; i < password.length; i++) {
-                password[i] = ' ';
-            }
+            Arrays.fill(password, ' ');
             password = null;
         }
     }
--- a/src/share/classes/sun/print/RasterPrinterJob.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/print/RasterPrinterJob.java	Wed Sep 26 15:31:48 2018 +0100
@@ -844,17 +844,16 @@
    }
 
     protected PageFormat getPageFormatFromAttributes() {
-        if (attributes == null || attributes.isEmpty()) {
+        Pageable pageable = null;
+        if (attributes == null || attributes.isEmpty() ||
+            !((pageable = getPageable()) instanceof OpenBook)) {
             return null;
         }
 
         PageFormat newPf = attributeToPageFormat(
             getPrintService(), attributes);
         PageFormat oldPf = null;
-        Pageable pageable = getPageable();
-        if ((pageable != null) &&
-            (pageable instanceof OpenBook) &&
-            ((oldPf = pageable.getPageFormat(0)) != null)) {
+        if ((oldPf = pageable.getPageFormat(0)) != null) {
             // If orientation, media, imageable area attributes are not in
             // "attributes" set, then use respective values of the existing
             // page format "oldPf".
--- a/src/share/classes/sun/security/provider/DigestBase.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/security/provider/DigestBase.java	Wed Sep 26 15:31:48 2018 +0100
@@ -28,6 +28,7 @@
 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 @@
         implReset();
         bufOfs = 0;
         bytesProcessed = 0;
+        Arrays.fill(buffer, (byte) 0x00);
     }
 
     // return the digest. See JCA doc.
--- a/src/share/classes/sun/security/provider/JavaKeyStore.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/security/provider/JavaKeyStore.java	Wed Sep 26 15:31:48 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -132,18 +132,20 @@
             throw new UnrecoverableKeyException("Password must not be null");
         }
 
-        KeyProtector keyProtector = new KeyProtector(password);
+        byte[] passwordBytes = convertToBytes(password);
+        KeyProtector keyProtector = new KeyProtector(passwordBytes);
         byte[] encrBytes = ((KeyEntry)entry).protectedPrivKey;
         EncryptedPrivateKeyInfo encrInfo;
-        byte[] plain;
         try {
             encrInfo = new EncryptedPrivateKeyInfo(encrBytes);
+            return keyProtector.recover(encrInfo);
         } catch (IOException ioe) {
             throw new UnrecoverableKeyException("Private key not stored as "
                                                 + "PKCS #8 "
                                                 + "EncryptedPrivateKeyInfo");
+        } finally {
+            Arrays.fill(passwordBytes, (byte) 0x00);
         }
-        return keyProtector.recover(encrInfo);
     }
 
     /**
@@ -252,7 +254,8 @@
                                   Certificate[] chain)
         throws KeyStoreException
     {
-        KeyProtector keyProtector = null;
+        KeyProtector keyProtector;
+        byte[] passwordBytes = null;
 
         if (!(key instanceof java.security.PrivateKey)) {
             throw new KeyStoreException("Cannot store non-PrivateKeys");
@@ -263,7 +266,8 @@
                 entry.date = new Date();
 
                 // Protect the encoding of the key
-                keyProtector = new KeyProtector(password);
+                passwordBytes = convertToBytes(password);
+                keyProtector = new KeyProtector(passwordBytes);
                 entry.protectedPrivKey = keyProtector.protect(key);
 
                 // clone the chain
@@ -279,7 +283,8 @@
         } catch (NoSuchAlgorithmException nsae) {
             throw new KeyStoreException("Key protection algorithm not found");
         } finally {
-            keyProtector = null;
+            if (passwordBytes != null)
+                Arrays.fill(passwordBytes, (byte) 0x00);
         }
     }
 
@@ -793,18 +798,26 @@
     private MessageDigest getPreKeyedHash(char[] password)
         throws NoSuchAlgorithmException, UnsupportedEncodingException
     {
-        int i, j;
 
         MessageDigest md = MessageDigest.getInstance("SHA");
+        byte[] passwdBytes = convertToBytes(password);
+        md.update(passwdBytes);
+        Arrays.fill(passwdBytes, (byte) 0x00);
+        md.update("Mighty Aphrodite".getBytes("UTF8"));
+        return md;
+    }
+
+    /**
+     * Helper method to convert char[] to byte[]
+     */
+
+    private byte[] convertToBytes(char[] password) {
+        int i, j;
         byte[] passwdBytes = new byte[password.length * 2];
         for (i=0, j=0; i<password.length; i++) {
             passwdBytes[j++] = (byte)(password[i] >> 8);
             passwdBytes[j++] = (byte)password[i];
         }
-        md.update(passwdBytes);
-        for (i=0; i<passwdBytes.length; i++)
-            passwdBytes[i] = 0;
-        md.update("Mighty Aphrodite".getBytes("UTF8"));
-        return md;
+        return passwdBytes;
     }
 }
--- a/src/share/classes/sun/security/provider/KeyProtector.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/security/provider/KeyProtector.java	Wed Sep 26 15:31:48 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -119,28 +119,15 @@
     /**
      * Creates an instance of this class, and initializes it with the given
      * password.
-     *
-     * <p>The password is expected to be in printable ASCII.
-     * Normal rules for good password selection apply: at least
-     * seven characters, mixed case, with punctuation encouraged.
-     * Phrases or words which are easily guessed, for example by
-     * being found in dictionaries, are bad.
      */
-    public KeyProtector(char[] password)
+    public KeyProtector(byte[] passwordBytes)
         throws NoSuchAlgorithmException
     {
-        int i, j;
-
-        if (password == null) {
+        if (passwordBytes == null) {
            throw new IllegalArgumentException("password can't be null");
         }
         md = MessageDigest.getInstance(DIGEST_ALG);
-        // Convert password to byte array, so that it can be digested
-        passwdBytes = new byte[password.length * 2];
-        for (i=0, j=0; i<password.length; i++) {
-            passwdBytes[j++] = (byte)(password[i] >> 8);
-            passwdBytes[j++] = (byte)password[i];
-        }
+        this.passwdBytes = passwordBytes;
     }
 
     /**
--- a/src/share/classes/sun/security/provider/MD4.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/security/provider/MD4.java	Wed Sep 26 15:31:48 2018 +0100
@@ -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 @@
         super("MD4", 16, 64);
         state = new int[4];
         x = new int[16];
-        implReset();
+        resetHashes();
     }
 
     // clone this object
@@ -106,6 +107,12 @@
      */
     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;
--- a/src/share/classes/sun/security/provider/MD5.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/security/provider/MD5.java	Wed Sep 26 15:31:48 2018 +0100
@@ -25,6 +25,8 @@
 
 package sun.security.provider;
 
+import java.util.Arrays;
+
 import static sun.security.provider.ByteArrayAccess.*;
 
 /**
@@ -66,7 +68,7 @@
         super("MD5", 16, 64);
         state = new int[4];
         x = new int[16];
-        implReset();
+        resetHashes();
     }
 
     // clone this object
@@ -82,6 +84,12 @@
      */
     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;
--- a/src/share/classes/sun/security/provider/SHA.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/security/provider/SHA.java	Wed Sep 26 15:31:48 2018 +0100
@@ -25,6 +25,8 @@
 
 package sun.security.provider;
 
+import java.util.Arrays;
+
 import static sun.security.provider.ByteArrayAccess.*;
 
 /**
@@ -59,7 +61,7 @@
         super("SHA-1", 20, 64);
         state = new int[5];
         W = new int[80];
-        implReset();
+        resetHashes();
     }
 
     /*
@@ -76,6 +78,13 @@
      * 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;
--- a/src/share/classes/sun/security/provider/SHA2.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/security/provider/SHA2.java	Wed Sep 26 15:31:48 2018 +0100
@@ -25,6 +25,8 @@
 
 package sun.security.provider;
 
+import java.util.Arrays;
+
 import static sun.security.provider.ByteArrayAccess.*;
 
 /**
@@ -80,13 +82,18 @@
         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);
     }
 
--- a/src/share/classes/sun/security/provider/SHA5.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/src/share/classes/sun/security/provider/SHA5.java	Wed Sep 26 15:31:48 2018 +0100
@@ -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 @@
         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);
     }
 
--- a/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Cipher.java	Mon Sep 17 15:06:15 2018 +0100
+++ b/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Cipher.java	Wed Sep 26 15:31:48 2018 +0100
@@ -105,7 +105,7 @@
         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"; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/print/PageFormat/WrongPaperForBookPrintingTest.java	Wed Sep 26 15:31:48 2018 +0100
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 8201818
+   @summary Printing attributes break page size set via "java.awt.print.Book"
+            object
+   @run main/manual WrongPaperForBookPrintingTest
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.print.Book;
+import java.awt.print.PageFormat;
+import java.awt.print.Paper;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.Size2DSyntax;
+import javax.print.attribute.standard.Chromaticity;
+import javax.print.attribute.standard.MediaSize;
+import javax.print.attribute.standard.MediaSizeName;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.WindowConstants;
+
+public class WrongPaperForBookPrintingTest implements Printable {
+    private static final CountDownLatch testEndedSignal = new CountDownLatch(1);
+    private static final int testTimeout = 300000;
+    private static volatile String testFailureMsg;
+    private static volatile boolean testPassed;
+    private static volatile boolean testFinished;
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(() -> createAndShowTestDialog());
+
+        try {
+            if (!testEndedSignal.await(testTimeout, TimeUnit.MILLISECONDS)) {
+                throw new RuntimeException(String.format(
+                    "Test timeout '%d ms' elapsed.", testTimeout));
+            }
+            if (!testPassed) {
+                String failureMsg = testFailureMsg;
+                if ((failureMsg != null) && (!failureMsg.trim().isEmpty())) {
+                    throw new RuntimeException(failureMsg);
+                } else {
+                    throw new RuntimeException("Test failed.");
+                }
+            }
+        } catch (InterruptedException ie) {
+            throw new RuntimeException(ie);
+        } finally {
+            testFinished = true;
+        }
+    }
+
+    private static void doTest() {
+        PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
+        aset.add(Chromaticity.MONOCHROME);
+
+        MediaSize isoA5Size = MediaSize.getMediaSizeForName(MediaSizeName.ISO_A5);
+        float[] size = isoA5Size.getSize(Size2DSyntax.INCH);
+        Paper paper = new Paper();
+        paper.setSize(size[0] * 72.0, size[1] * 72.0);
+        paper.setImageableArea(0.0, 0.0, size[0] * 72.0, size[1] * 72.0);
+        PageFormat pf = new PageFormat();
+        pf.setPaper(paper);
+
+        Book pageable = new Book();
+        pageable.append(new WrongPaperForBookPrintingTest(), pf);
+
+        PrinterJob job = PrinterJob.getPrinterJob();
+        job.setPageable(pageable);
+        if (job.printDialog()) {
+            try {
+                job.print(aset);
+            } catch (PrinterException pe) {
+                throw new RuntimeException(pe);
+            }
+        }
+    }
+
+    private static void pass() {
+        testPassed = true;
+        testEndedSignal.countDown();
+    }
+
+    private static void fail(String failureMsg) {
+        testFailureMsg = failureMsg;
+        testPassed = false;
+        testEndedSignal.countDown();
+    }
+
+    private static String convertMillisToTimeStr(int millis) {
+        if (millis < 0) {
+            return "00:00:00";
+        }
+        int hours = millis / 3600000;
+        int minutes = (millis - hours * 3600000) / 60000;
+        int seconds = (millis - hours * 3600000 - minutes * 60000) / 1000;
+        return String.format("%02d:%02d:%02d", hours, minutes, seconds);
+    }
+
+    private static void createAndShowTestDialog() {
+        String description =
+            " To run this test it is required to have a virtual PDF\r\n" +
+            " printer or any other printer supporting A5 paper size.\r\n" +
+            "\r\n" +
+            " 1. Verify that NOT A5 paper size is set as default for the\r\n" +
+            " printer to be used.\r\n" +
+            " 2. Click on \"Start Test\" button.\r\n" +
+            " 3. In the shown print dialog select the printer and click\r\n" +
+            " on \"Print\" button.\r\n" +
+            " 4. Verify that a page with a drawn rectangle is printed on\r\n" +
+            " a paper of A5 size which is (5.8 x 8.3 in) or\r\n" +
+            " (148 x 210 mm).\r\n" +
+            "\r\n" +
+            " If the printed page size is correct, click on \"PASS\"\r\n" +
+            " button, otherwise click on \"FAIL\" button.";
+
+        final JDialog dialog = new JDialog();
+        dialog.setTitle("WrongPaperForBookPrintingTest");
+        dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+        dialog.addWindowListener(new WindowAdapter() {
+            @Override
+            public void windowClosing(WindowEvent e) {
+                dialog.dispose();
+                fail("Main dialog was closed.");
+            }
+        });
+
+        final JLabel testTimeoutLabel = new JLabel(String.format(
+            "Test timeout: %s", convertMillisToTimeStr(testTimeout)));
+        final long startTime = System.currentTimeMillis();
+        final Timer timer = new Timer(0, null);
+        timer.setDelay(1000);
+        timer.addActionListener((e) -> {
+            int leftTime = testTimeout - (int) (System.currentTimeMillis() - startTime);
+            if ((leftTime < 0) || testFinished) {
+                timer.stop();
+                dialog.dispose();
+            }
+            testTimeoutLabel.setText(String.format(
+                "Test timeout: %s", convertMillisToTimeStr(leftTime)));
+        });
+        timer.start();
+
+        JTextArea textArea = new JTextArea(description);
+        textArea.setEditable(false);
+
+        final JButton testButton = new JButton("Start Test");
+        final JButton passButton = new JButton("PASS");
+        final JButton failButton = new JButton("FAIL");
+        testButton.addActionListener((e) -> {
+            testButton.setEnabled(false);
+            new Thread(() -> {
+                try {
+                    doTest();
+
+                    SwingUtilities.invokeLater(() -> {
+                        passButton.setEnabled(true);
+                        failButton.setEnabled(true);
+                    });
+                } catch (Throwable t) {
+                    t.printStackTrace();
+                    dialog.dispose();
+                    fail("Exception occurred in a thread executing the test.");
+                }
+            }).start();
+        });
+        passButton.setEnabled(false);
+        passButton.addActionListener((e) -> {
+            dialog.dispose();
+            pass();
+        });
+        failButton.setEnabled(false);
+        failButton.addActionListener((e) -> {
+            dialog.dispose();
+            fail("Size of a printed page is wrong.");
+        });
+
+        JPanel mainPanel = new JPanel(new BorderLayout());
+        JPanel labelPanel = new JPanel(new FlowLayout());
+        labelPanel.add(testTimeoutLabel);
+        mainPanel.add(labelPanel, BorderLayout.NORTH);
+        mainPanel.add(textArea, BorderLayout.CENTER);
+        JPanel buttonPanel = new JPanel(new FlowLayout());
+        buttonPanel.add(testButton);
+        buttonPanel.add(passButton);
+        buttonPanel.add(failButton);
+        mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+        dialog.add(mainPanel);
+
+        dialog.pack();
+        dialog.setVisible(true);
+    }
+
+    @Override
+    public int print(Graphics g, PageFormat pf, int pageIndex)
+        throws PrinterException {
+        if (pageIndex == 0) {
+            g.setColor(Color.RED);
+            g.drawRect((int) pf.getImageableX(), (int) pf.getImageableY(),
+                (int) pf.getImageableWidth() - 1, (int) pf.getImageableHeight() - 1);
+            return Printable.PAGE_EXISTS;
+        } else {
+            return Printable.NO_SUCH_PAGE;
+        }
+    }
+}