/* |
|
* 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 |
|
* 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 jdk.internal.misc.SharedSecrets; |
|
import java.io.*; |
|
import java.security.*; |
|
import javax.crypto.*; |
|
final class SealedObjectForKeyProtector extends SealedObject { |
|
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 java.io.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); |
|
} |
|
SealedObjectForKeyProtector(SealedObject so) { |
|
super(so); |
|
} |
|
AlgorithmParameters getParameters() { |
|
AlgorithmParameters params = null; |
|
if (super.encodedParams != null) { |
|
try { |
|
params = AlgorithmParameters.getInstance("PBE", |
|
SunJCE.getInstance()); |
|
params.init(super.encodedParams); |
|
} catch (NoSuchAlgorithmException nsae) { |
|
throw new RuntimeException( |
|
"SunJCE provider is not configured properly"); |
|
} catch (IOException io) { |
|
throw new RuntimeException("Parameter failure: "+ |
|
io.getMessage()); |
|
} |
|
} |
|
return params; |
|
} |
|
final Key getKey(Cipher c) |
|
throws IOException, ClassNotFoundException, IllegalBlockSizeException, |
|
BadPaddingException { |
|
try (ObjectInputStream ois = SharedSecrets.getJavaxCryptoSealedObjectAccess() |
|
.getExtObjectInputStream(this, c)) { |
|
AccessController.doPrivileged( |
|
(PrivilegedAction<Void>) () -> { |
|
ois.setObjectInputFilter(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; |
|
} |
|
} |
|
} |