mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
Merge
This commit is contained in:
commit
0278846eaa
91 changed files with 1073 additions and 416 deletions
|
@ -81,6 +81,12 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
private static final class SecretKeyEntry {
|
||||
Date date; // the creation date of this entry
|
||||
SealedObject sealedKey;
|
||||
|
||||
// Maximum possible length of sealedKey. Used to detect malicious
|
||||
// input data. This field is set to the file length of the keystore
|
||||
// at loading. It is useless when creating a new SecretKeyEntry
|
||||
// to be store in a keystore.
|
||||
int maxLength;
|
||||
}
|
||||
|
||||
// Trusted certificate
|
||||
|
@ -136,8 +142,8 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
}
|
||||
key = keyProtector.recover(encrInfo);
|
||||
} else {
|
||||
key =
|
||||
keyProtector.unseal(((SecretKeyEntry)entry).sealedKey);
|
||||
SecretKeyEntry ske = ((SecretKeyEntry)entry);
|
||||
key = keyProtector.unseal(ske.sealedKey, ske.maxLength);
|
||||
}
|
||||
|
||||
return key;
|
||||
|
@ -282,6 +288,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
|
||||
// seal and store the key
|
||||
entry.sealedKey = keyProtector.seal(key);
|
||||
entry.maxLength = Integer.MAX_VALUE;
|
||||
entries.put(alias.toLowerCase(Locale.ENGLISH), entry);
|
||||
}
|
||||
|
||||
|
@ -691,6 +698,10 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
if (stream == null)
|
||||
return;
|
||||
|
||||
byte[] allData = stream.readAllBytes();
|
||||
int fullLength = allData.length;
|
||||
|
||||
stream = new ByteArrayInputStream(allData);
|
||||
if (password != null) {
|
||||
md = getPreKeyedHash(password);
|
||||
dis = new DataInputStream(new DigestInputStream(stream, md));
|
||||
|
@ -829,10 +840,11 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<Void>)() -> {
|
||||
ois2.setObjectInputFilter(
|
||||
new DeserializationChecker());
|
||||
new DeserializationChecker(fullLength));
|
||||
return null;
|
||||
});
|
||||
entry.sealedKey = (SealedObject)ois.readObject();
|
||||
entry.maxLength = fullLength;
|
||||
// NOTE: don't close ois here since we are still
|
||||
// using dis!!!
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
|
@ -926,8 +938,17 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
* deserialized.
|
||||
*/
|
||||
private static class DeserializationChecker implements ObjectInputFilter {
|
||||
|
||||
private static final int MAX_NESTED_DEPTH = 2;
|
||||
|
||||
// Full length of keystore, anything inside a SecretKeyEntry should not
|
||||
// be bigger. Otherwise, must be illegal.
|
||||
private final int fullLength;
|
||||
|
||||
public DeserializationChecker(int fullLength) {
|
||||
this.fullLength = fullLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectInputFilter.Status
|
||||
checkInput(ObjectInputFilter.FilterInfo info) {
|
||||
|
@ -936,6 +957,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
long nestedDepth = info.depth();
|
||||
if ((nestedDepth == 1 &&
|
||||
info.serialClass() != SealedObjectForKeyProtector.class) ||
|
||||
info.arrayLength() > fullLength ||
|
||||
(nestedDepth > MAX_NESTED_DEPTH &&
|
||||
info.serialClass() != null &&
|
||||
info.serialClass() != Object.class)) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2019, 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
|
||||
|
@ -352,8 +352,11 @@ final class KeyProtector {
|
|||
|
||||
/**
|
||||
* Unseals the sealed key.
|
||||
*
|
||||
* @param maxLength Maximum possible length of so.
|
||||
* If bigger, must be illegal.
|
||||
*/
|
||||
Key unseal(SealedObject so)
|
||||
Key unseal(SealedObject so, int maxLength)
|
||||
throws NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||
SecretKey sKey = null;
|
||||
try {
|
||||
|
@ -389,7 +392,7 @@ final class KeyProtector {
|
|||
SunJCE.getInstance(),
|
||||
"PBEWithMD5AndTripleDES");
|
||||
cipher.init(Cipher.DECRYPT_MODE, sKey, params);
|
||||
return soForKeyProtector.getKey(cipher);
|
||||
return soForKeyProtector.getKey(cipher, maxLength);
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
// Note: this catch needed to be here because of the
|
||||
// later catch of GeneralSecurityException
|
||||
|
|
|
@ -73,7 +73,7 @@ final class SealedObjectForKeyProtector extends SealedObject {
|
|||
return params;
|
||||
}
|
||||
|
||||
final Key getKey(Cipher c)
|
||||
final Key getKey(Cipher c, int maxLength)
|
||||
throws IOException, ClassNotFoundException, IllegalBlockSizeException,
|
||||
BadPaddingException {
|
||||
|
||||
|
@ -81,7 +81,7 @@ final class SealedObjectForKeyProtector extends SealedObject {
|
|||
.getExtObjectInputStream(this, c)) {
|
||||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<Void>) () -> {
|
||||
ois.setObjectInputFilter(DeserializationChecker.ONE_FILTER);
|
||||
ois.setObjectInputFilter(new DeserializationChecker(maxLength));
|
||||
return null;
|
||||
});
|
||||
try {
|
||||
|
@ -109,7 +109,7 @@ final class SealedObjectForKeyProtector extends SealedObject {
|
|||
*/
|
||||
private static class DeserializationChecker implements ObjectInputFilter {
|
||||
|
||||
private static final ObjectInputFilter ONE_FILTER;
|
||||
private static final ObjectInputFilter OWN_FILTER;
|
||||
|
||||
static {
|
||||
String prop = AccessController.doPrivileged(
|
||||
|
@ -121,26 +121,32 @@ final class SealedObjectForKeyProtector extends SealedObject {
|
|||
return Security.getProperty(KEY_SERIAL_FILTER);
|
||||
}
|
||||
});
|
||||
ONE_FILTER = new DeserializationChecker(prop == null ? null
|
||||
: ObjectInputFilter.Config.createFilter(prop));
|
||||
OWN_FILTER = prop == null
|
||||
? null
|
||||
: ObjectInputFilter.Config.createFilter(prop);
|
||||
}
|
||||
|
||||
private final ObjectInputFilter base;
|
||||
// Maximum possible length of anything inside
|
||||
private final int maxLength;
|
||||
|
||||
private DeserializationChecker(ObjectInputFilter base) {
|
||||
this.base = base;
|
||||
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 (base != null) {
|
||||
Status result = base.checkInput(info);
|
||||
if (OWN_FILTER != null) {
|
||||
Status result = OWN_FILTER.checkInput(info);
|
||||
if (result != Status.UNDECIDED) {
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue