# HG changeset patch # User igerasim # Date 1510701005 0 # Node ID 1de398ed4d75aff0ac8788c6b5c8e354d0873092 # Parent 88d3306d6ee8e2e9b8429f2fd630ac9e33d11629 8181370: Better keystore handling Reviewed-by: weijun, igerasim diff -r 88d3306d6ee8 -r 1de398ed4d75 src/share/classes/com/sun/crypto/provider/JceKeyStore.java --- a/src/share/classes/com/sun/crypto/provider/JceKeyStore.java Tue Nov 14 22:58:57 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/JceKeyStore.java Tue Nov 14 23:10:05 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 @@ -27,12 +27,14 @@ import java.io.*; import java.util.*; +import java.security.AccessController; import java.security.DigestInputStream; import java.security.DigestOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Key; import java.security.PrivateKey; +import java.security.PrivilegedAction; import java.security.KeyStoreSpi; import java.security.KeyStoreException; import java.security.UnrecoverableKeyException; @@ -41,6 +43,8 @@ import java.security.cert.CertificateException; import javax.crypto.SealedObject; +import sun.misc.ObjectInputFilter; + /** * This class provides the keystore implementation referred to as "jceks". * This implementation strongly protects the keystore private keys using @@ -835,11 +839,23 @@ // read the sealed key try { ois = new ObjectInputStream(dis); + final ObjectInputStream ois2 = ois; + // Set a deserialization checker + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + ObjectInputFilter.Config.setObjectInputFilter( + ois2, new DeserializationChecker()); + return null; + } + }); entry.sealedKey = (SealedObject)ois.readObject(); // NOTE: don't close ois here since we are still // using dis!!! } catch (ClassNotFoundException cnfe) { throw new IOException(cnfe.getMessage()); + } catch (InvalidClassException ice) { + throw new IOException("Invalid secret key format"); } // Add the entry to the list @@ -898,4 +914,34 @@ md.update("Mighty Aphrodite".getBytes("UTF8")); return md; } + + /* + * An ObjectInputFilter that checks the format of the secret key being + * deserialized. + */ + private static class DeserializationChecker implements ObjectInputFilter { + private static final int MAX_NESTED_DEPTH = 2; + + @Override + public ObjectInputFilter.Status + checkInput(ObjectInputFilter.FilterInfo info) { + + // First run a custom filter + long nestedDepth = info.depth(); + if ((nestedDepth == 1 && + info.serialClass() != SealedObjectForKeyProtector.class) || + nestedDepth > MAX_NESTED_DEPTH) { + return Status.REJECTED; + } + + // Next run the default filter, if available + ObjectInputFilter defaultFilter = + ObjectInputFilter.Config.getSerialFilter(); + if (defaultFilter != null) { + return defaultFilter.checkInput(info); + } + + return Status.UNDECIDED; + } + } }