8181370: Better keystore handling
authorvinnie
Wed, 28 Jun 2017 16:52:36 +0100
changeset 47416 a627f88bed3a
parent 47415 354a527f3246
child 47417 5984d1c9d03d
8181370: Better keystore handling Reviewed-by: weijun, igerasim
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<Void>)() -> {
+                                    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;
+        }
+    }
 }