< prev index next >
src/share/classes/com/sun/crypto/provider/JceKeyStore.java
Print this page
rev 12545 : 8181370: Better keystore handling
Reviewed-by: weijun, igerasim
*** 1,7 ****
/*
! * Copyright (c) 1998, 2016, 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. Oracle designates this
--- 1,7 ----
/*
! * 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 25,48 ****
--- 25,52 ----
package com.sun.crypto.provider;
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;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
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
* triple-DES, where the triple-DES encryption/decryption key is derived from
* the user's password.
*** 833,847 ****
--- 837,861 ----
entry.date = new Date(dis.readLong());
// read the sealed key
try {
ois = new ObjectInputStream(dis);
+ final ObjectInputStream ois2 = ois;
+ // Set a deserialization checker
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>)() -> {
+ 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
entries.put(alias, entry);
*** 898,903 ****
--- 912,947 ----
for (i=0; i<passwdBytes.length; i++)
passwdBytes[i] = 0;
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;
+ }
+ }
}
< prev index next >