# HG changeset patch # User vinnie # Date 1498665156 -3600 # Node ID a627f88bed3a89e9e938c29aef5862f492e3b291 # Parent 354a527f324688cf52b618d0d1edb819a5763dd2 8181370: Better keystore handling Reviewed-by: weijun, igerasim diff -r 354a527f3246 -r a627f88bed3a src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java --- a/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java Mon Jun 19 17:38:33 2017 -0400 +++ b/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java Wed Jun 28 16:52:36 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, 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; @@ -835,11 +837,21 @@ // read the sealed key try { ois = new ObjectInputStream(dis); + final ObjectInputStream ois2 = ois; + // Set a deserialization checker + AccessController.doPrivileged( + (PrivilegedAction)() -> { + ois2.setObjectInputFilter( + 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 @@ -916,4 +928,34 @@ return JCEKS_MAGIC == dataStream.readInt(); } + + /* + * 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; + } + } }