|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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, int maxLength) |
|
throws IOException, ClassNotFoundException, IllegalBlockSizeException, |
|
BadPaddingException { |
|
|
|
try (ObjectInputStream ois = SharedSecrets.getJavaxCryptoSealedObjectAccess() |
|
.getExtObjectInputStream(this, c)) { |
|
AccessController.doPrivileged( |
|
(PrivilegedAction<Void>) () -> { |
|
ObjectInputFilter.Config.setObjectInputFilter(ois, |
|
new DeserializationChecker(maxLength)); |
|
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; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static class DeserializationChecker implements ObjectInputFilter { |
|
|
|
private static final ObjectInputFilter OWN_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); |
|
} |
|
}); |
|
OWN_FILTER = prop == null |
|
? null |
|
: ObjectInputFilter.Config.createFilter(prop); |
|
} |
|
|
|
|
|
private final int maxLength; |
|
|
|
private DeserializationChecker(int maxLength) { |
|
this.maxLength = maxLength; |
|
} |
|
|
|
@Override |
|
public ObjectInputFilter.Status checkInput( |
|
ObjectInputFilter.FilterInfo info) { |
|
|
|
if (info.arrayLength() > maxLength) { |
|
return Status.REJECTED; |
|
} |
|
|
|
if (info.serialClass() == Object.class) { |
|
return Status.UNDECIDED; |
|
} |
|
|
|
if (OWN_FILTER != null) { |
|
Status result = OWN_FILTER.checkInput(info); |
|
if (result != Status.UNDECIDED) { |
|
return result; |
|
} |
|
} |
|
|
|
ObjectInputFilter defaultFilter = |
|
ObjectInputFilter.Config.getSerialFilter(); |
|
if (defaultFilter != null) { |
|
return defaultFilter.checkInput(info); |
|
} |
|
|
|
return Status.UNDECIDED; |
|
} |
|
} |
|
} |