Mercurial > hg > openjdk > jdk8u > jdk
changeset 12986:6cbe2e5989a8 jdk8u171-b06
8189997: Enhance keystore mechanisms
8194259: keytool error: java.io.IOException: Invalid secret key format
Reviewed-by: mullan, valeriep, rriggs, ahgross
author | igerasim |
---|---|
date | Tue, 06 Feb 2018 09:04:46 -0800 |
parents | 9a92e68141a0 |
children | d7176326208f |
files | src/share/classes/com/sun/crypto/provider/JceKeyStore.java src/share/classes/com/sun/crypto/provider/KeyProtector.java src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java src/share/classes/com/sun/crypto/provider/ai.java src/share/classes/javax/crypto/SealedObject.java src/share/classes/sun/misc/JavaxCryptoSealedObjectAccess.java src/share/classes/sun/misc/SharedSecrets.java src/share/lib/security/java.security-aix src/share/lib/security/java.security-linux src/share/lib/security/java.security-macosx src/share/lib/security/java.security-solaris src/share/lib/security/java.security-windows |
diffstat | 12 files changed, 275 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/JceKeyStore.java Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/classes/com/sun/crypto/provider/JceKeyStore.java Tue Feb 06 09:04:46 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -929,8 +929,10 @@ // First run a custom filter long nestedDepth = info.depth(); if ((nestedDepth == 1 && - info.serialClass() != SealedObjectForKeyProtector.class) || - nestedDepth > MAX_NESTED_DEPTH) { + info.serialClass() != SealedObjectForKeyProtector.class) || + (nestedDepth > MAX_NESTED_DEPTH && + info.serialClass() != null && + info.serialClass() != Object.class)) { return Status.REJECTED; }
--- a/src/share/classes/com/sun/crypto/provider/KeyProtector.java Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/classes/com/sun/crypto/provider/KeyProtector.java Tue Feb 06 09:04:46 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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,8 +26,6 @@ package com.sun.crypto.provider; import java.io.IOException; -import java.io.Serializable; -import java.security.Security; import java.security.Key; import java.security.PrivateKey; import java.security.Provider; @@ -35,7 +33,6 @@ import java.security.MessageDigest; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.UnrecoverableKeyException; import java.security.AlgorithmParameters; import java.security.spec.InvalidParameterSpecException; @@ -44,7 +41,6 @@ import javax.crypto.Cipher; import javax.crypto.CipherSpi; import javax.crypto.SecretKey; -import javax.crypto.IllegalBlockSizeException; import javax.crypto.SealedObject; import javax.crypto.spec.*; import sun.security.x509.AlgorithmId; @@ -347,7 +343,7 @@ SunJCE.getInstance(), "PBEWithMD5AndTripleDES"); cipher.init(Cipher.DECRYPT_MODE, skey, params); - return (Key)soForKeyProtector.getObject(cipher); + return soForKeyProtector.getKey(cipher); } catch (NoSuchAlgorithmException ex) { // Note: this catch needed to be here because of the // later catch of GeneralSecurityException
--- a/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java Tue Feb 06 09:04:46 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -25,6 +25,9 @@ package com.sun.crypto.provider; +import sun.misc.ObjectInputFilter; +import sun.misc.SharedSecrets; + import java.io.*; import java.security.*; import javax.crypto.*; @@ -33,6 +36,16 @@ static final long serialVersionUID = -3650226485480866989L; + /** + * The InputStreamFilter for a Key object inside this SealedObject. It can + * be either provided as a {@link Security} property or a system property + * (when provided as latter, it shadows the former). If the result of this + * filter is {@link sun.misc.ObjectInputFilter.Status.UNDECIDED}, the system + * level filter defined by jdk.serialFilter will be consulted. The value + * of this property uses the same format of jdk.serialFilter. + */ + private static final String KEY_SERIAL_FILTER = "jceks.key.serialFilter"; + SealedObjectForKeyProtector(Serializable object, Cipher c) throws IOException, IllegalBlockSizeException { super(object, c); @@ -59,4 +72,88 @@ } return params; } + + final Key getKey(Cipher c) + throws IOException, ClassNotFoundException, IllegalBlockSizeException, + BadPaddingException { + + try (ObjectInputStream ois = SharedSecrets.getJavaxCryptoSealedObjectAccess() + .getExtObjectInputStream(this, c)) { + AccessController.doPrivileged( + (PrivilegedAction<Void>) () -> { + ObjectInputFilter.Config.setObjectInputFilter(ois, + DeserializationChecker.ONE_FILTER); + return null; + }); + try { + @SuppressWarnings("unchecked") + Key t = (Key) ois.readObject(); + return t; + } catch (InvalidClassException ice) { + String msg = ice.getMessage(); + if (msg.contains("REJECTED")) { + throw new IOException("Rejected by the" + + " jceks.key.serialFilter or jdk.serialFilter" + + " property", ice); + } else { + throw ice; + } + } + } + } + + /** + * The filter for the content of a SealedObjectForKeyProtector. + * + * First, the jceks.key.serialFilter will be consulted. If the result + * is UNDECIDED, the system level jdk.serialFilter will be consulted. + */ + private static class DeserializationChecker implements ObjectInputFilter { + + private static final ObjectInputFilter ONE_FILTER; + + static { + String prop = AccessController.doPrivileged( + (PrivilegedAction<String>) () -> { + String tmp = System.getProperty(KEY_SERIAL_FILTER); + if (tmp != null) { + return tmp; + } else { + return Security.getProperty(KEY_SERIAL_FILTER); + } + }); + ONE_FILTER = new DeserializationChecker(prop == null ? null + : ObjectInputFilter.Config.createFilter(prop)); + } + + private final ObjectInputFilter base; + + private DeserializationChecker(ObjectInputFilter base) { + this.base = base; + } + + @Override + public ObjectInputFilter.Status checkInput( + ObjectInputFilter.FilterInfo info) { + + if (info.serialClass() == Object.class) { + return Status.UNDECIDED; + } + + if (base != null) { + Status result = base.checkInput(info); + if (result != Status.UNDECIDED) { + return result; + } + } + + ObjectInputFilter defaultFilter = + ObjectInputFilter.Config.getSerialFilter(); + if (defaultFilter != null) { + return defaultFilter.checkInput(info); + } + + return Status.UNDECIDED; + } + } }
--- a/src/share/classes/com/sun/crypto/provider/ai.java Mon Feb 05 00:15:08 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2001, 2007, 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 - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package com.sun.crypto.provider; - -import java.io.IOException; -import java.io.Serializable; -import java.io.ObjectStreamException; -import java.security.AlgorithmParameters; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.SealedObject; -import javax.crypto.spec.*; - -/** - * This class is introduced to workaround a problem in - * the SunJCE provider shipped in JCE 1.2.1: the class - * SealedObjectForKeyProtector was obfuscated due to a mistake. - * - * In order to retrieve secret keys in a JCEKS KeyStore written - * by the SunJCE provider in JCE 1.2.1, this class will be used. - * - * @author Valerie Peng - * - * - * @see JceKeyStore - */ - -final class ai extends javax.crypto.SealedObject { - - static final long serialVersionUID = -7051502576727967444L; - - ai(SealedObject so) { - super(so); - } - - Object readResolve() throws ObjectStreamException { - return new SealedObjectForKeyProtector(this); - } -}
--- a/src/share/classes/javax/crypto/SealedObject.java Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/classes/javax/crypto/SealedObject.java Tue Feb 06 09:04:46 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, 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 @@ -25,6 +25,8 @@ package javax.crypto; +import sun.misc.SharedSecrets; + import java.io.*; import java.security.AlgorithmParameters; import java.security.Key; @@ -287,17 +289,7 @@ throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException { - /* - * Unseal the object - */ - byte[] content = c.doFinal(this.encryptedContent); - - /* - * De-serialize it - */ - // creating a stream pipe-line, from b to a - ByteArrayInputStream b = new ByteArrayInputStream(content); - ObjectInput a = new extObjectInputStream(b); + ObjectInput a = getExtObjectInputStream(c); try { Object obj = a.readObject(); return obj; @@ -417,17 +409,7 @@ throw new RuntimeException(iape.getMessage()); } - /* - * Unseal the object - */ - byte[] content = c.doFinal(this.encryptedContent); - - /* - * De-serialize it - */ - // creating a stream pipe-line, from b to a - ByteArrayInputStream b = new ByteArrayInputStream(content); - ObjectInput a = new extObjectInputStream(b); + ObjectInput a = getExtObjectInputStream(c); try { Object obj = a.readObject(); return obj; @@ -450,6 +432,19 @@ if (encodedParams != null) encodedParams = encodedParams.clone(); } + + // This method is also called inside SealedObjectForKeyProtector.java. + private ObjectInputStream getExtObjectInputStream(Cipher c) + throws BadPaddingException, IllegalBlockSizeException, IOException { + + byte[] content = c.doFinal(this.encryptedContent); + ByteArrayInputStream b = new ByteArrayInputStream(content); + return new extObjectInputStream(b); + } + + static { + SharedSecrets.setJavaxCryptoSealedObjectAccess((obj,c) -> obj.getExtObjectInputStream(c)); + } } final class extObjectInputStream extends ObjectInputStream {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/misc/JavaxCryptoSealedObjectAccess.java Tue Feb 06 09:04:46 2018 -0800 @@ -0,0 +1,38 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package sun.misc; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.SealedObject; +import java.io.IOException; +import java.io.ObjectInputStream; + +public interface JavaxCryptoSealedObjectAccess { + ObjectInputStream getExtObjectInputStream( + SealedObject sealed, Cipher cipher) + throws BadPaddingException, IllegalBlockSizeException, IOException; +}
--- a/src/share/classes/sun/misc/SharedSecrets.java Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/classes/sun/misc/SharedSecrets.java Tue Feb 06 09:04:46 2018 -0800 @@ -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 @@ -25,7 +25,7 @@ package sun.misc; -import java.io.ObjectInputStream; +import javax.crypto.SealedObject; import java.util.jar.JarFile; import java.io.Console; import java.io.FileDescriptor; @@ -58,6 +58,7 @@ private static JavaUtilZipFileAccess javaUtilZipFileAccess; private static JavaAWTAccess javaAWTAccess; private static JavaOISAccess javaOISAccess; + private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -199,4 +200,15 @@ } return javaAWTAccess; } + + public static void setJavaxCryptoSealedObjectAccess(JavaxCryptoSealedObjectAccess jcsoa) { + javaxCryptoSealedObjectAccess = jcsoa; + } + + public static JavaxCryptoSealedObjectAccess getJavaxCryptoSealedObjectAccess() { + if (javaxCryptoSealedObjectAccess == null) { + unsafe.ensureClassInitialized(SealedObject.class); + } + return javaxCryptoSealedObjectAccess; + } }
--- a/src/share/lib/security/java.security-aix Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/lib/security/java.security-aix Tue Feb 06 09:04:46 2018 -0800 @@ -860,6 +860,9 @@ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -955,3 +958,20 @@ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
--- a/src/share/lib/security/java.security-linux Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/lib/security/java.security-linux Tue Feb 06 09:04:46 2018 -0800 @@ -861,6 +861,9 @@ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -961,3 +964,20 @@ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
--- a/src/share/lib/security/java.security-macosx Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/lib/security/java.security-macosx Tue Feb 06 09:04:46 2018 -0800 @@ -864,6 +864,9 @@ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -959,3 +962,20 @@ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
--- a/src/share/lib/security/java.security-solaris Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/lib/security/java.security-solaris Tue Feb 06 09:04:46 2018 -0800 @@ -863,6 +863,9 @@ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -958,3 +961,20 @@ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
--- a/src/share/lib/security/java.security-windows Mon Feb 05 00:15:08 2018 -0800 +++ b/src/share/lib/security/java.security-windows Tue Feb 06 09:04:46 2018 -0800 @@ -864,6 +864,9 @@ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -959,3 +962,20 @@ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*