mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8189997: Enhance keystore mechanisms
8194259: keytool error: java.io.IOException: Invalid secret key format Reviewed-by: mullan, valeriep, rriggs, ahgross
This commit is contained in:
parent
3d7092e9a2
commit
8fb70c710a
7 changed files with 163 additions and 68 deletions
|
@ -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
|
||||
|
@ -943,8 +943,10 @@ public final class JceKeyStore extends KeyStoreSpi {
|
|||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.KeyFactory;
|
|||
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 java.security.spec.PKCS8EncodedKeySpec;
|
|||
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 @@ final class KeyProtector {
|
|||
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
|
||||
|
|
|
@ -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,8 @@
|
|||
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
import javax.crypto.*;
|
||||
|
@ -33,6 +35,16 @@ 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);
|
||||
|
@ -59,4 +71,87 @@ final class SealedObjectForKeyProtector extends SealedObject {
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue