/*
* 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 sun.misc.ObjectInputFilter;
import sun.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 Security
property or a system property (when provided as latter, it shadows the former). If the result of this filter is UNDECIDED
, the system level filter defined by jdk.serialFilter will be consulted. The value of this property uses the same format of jdk.serialFilter. /**
* 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);
}
SealedObjectForKeyProtector(SealedObject so) {
super(so);
}
AlgorithmParameters getParameters() {
AlgorithmParameters params = null;
if (super.encodedParams != null) {
try {
params = AlgorithmParameters.getInstance("PBE", "SunJCE");
params.init(super.encodedParams);
} catch (NoSuchProviderException nspe) {
//eat.
} catch (NoSuchAlgorithmException nsae) {
//eat.
} catch (IOException ioe) {
//eat.
}
}
return params;
}
final Key getKey(Cipher c)
throws IOException, ClassNotFoundException, IllegalBlockSizeException,
BadPaddingException {
final ObjectInputStream ois = SharedSecrets.getJavaxCryptoSealedObjectAccess()
.getExtObjectInputStream(this, c);
try {
AccessController.doPrivileged(
new PrivilegedAction<Void>() {
@Override
public Void run() {
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;
}
}
} finally {
if (ois != null) {
ois.close();
}
}
}
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.
/**
* 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(
new PrivilegedAction<String>() {
@Override
public String run() {
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;
}
}
}