This commit is contained in:
Yuri Nesterenko 2021-04-23 17:37:32 +03:00
commit 1abb26f6d3
41 changed files with 1225 additions and 568 deletions

View File

@ -674,3 +674,6 @@ d5977ee56509ceaa3d3c8e1aebbca76651358da4 jdk-15.0.2+6
465ac9b408cae3e98c4f4630d22e653e725187ae jdk-15.0.2-ga
c5dd3194553250c265948572b132aa99f146ede8 jdk-15.0.3+0
64fea704eac2eaff9e9e1d3f016100fe8cb135c6 jdk-15.0.3+1
131bf806395dbaf4f9082c3a6702e4d7cfaa0e2e jdk-15.0.3+2
1bb2833119c55064b250e9c9c887344bec92e33a jdk-15.0.3+3
1055f2102e6eca45b2e2c6c3ac8e784d205cfbe2 jdk-15.0.3-ga

View File

@ -1268,6 +1268,7 @@ class ClassHierarchyWalker {
Klass* find_witness_in(KlassDepChange& changes,
Klass* context_type,
bool participants_hide_witnesses);
bool witnessed_reabstraction_in_supers(Klass* k);
public:
Klass* find_witness_subtype(Klass* context_type, KlassDepChange* changes = NULL) {
assert(doing_subtype_search(), "must set up a subtype search");
@ -1342,7 +1343,6 @@ static bool count_find_witness_calls() {
#define count_find_witness_calls() (0)
#endif //PRODUCT
Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
Klass* context_type,
bool participants_hide_witnesses) {
@ -1380,15 +1380,20 @@ Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
}
}
if (is_witness(new_type) &&
!ignore_witness(new_type)) {
if (is_witness(new_type)) {
if (!ignore_witness(new_type)) {
return new_type;
}
} else if (!doing_subtype_search()) {
// No witness found, but is_witness() doesn't detect method re-abstraction in case of spot-checking.
if (witnessed_reabstraction_in_supers(new_type)) {
return new_type;
}
}
return NULL;
}
// Walk hierarchy under a context type, looking for unexpected types.
// Do not report participant types, and recursively walk beneath
// them only if participants_hide_witnesses is false.
@ -1507,6 +1512,32 @@ Klass* ClassHierarchyWalker::find_witness_anywhere(Klass* context_type,
#undef ADD_SUBCLASS_CHAIN
}
bool ClassHierarchyWalker::witnessed_reabstraction_in_supers(Klass* k) {
if (!k->is_instance_klass()) {
return false; // no methods to find in an array type
} else {
// Looking for a case when an abstract method is inherited into a concrete class.
if (Dependencies::is_concrete_klass(k) && !k->is_interface()) {
Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
if (m != NULL) {
return false; // no reabstraction possible: local method found
}
for (InstanceKlass* super = k->java_super(); super != NULL; super = super->java_super()) {
m = super->find_instance_method(_name, _signature, Klass::skip_private);
if (m != NULL) { // inherited method found
if (m->is_abstract() || m->is_overpass()) {
_found_methods[_num_participants] = m;
return true; // abstract method found
}
return false;
}
}
assert(false, "root method not found");
return true;
}
return false;
}
}
bool Dependencies::is_concrete_klass(Klass* k) {
if (k->is_abstract()) return false;
@ -1530,7 +1561,6 @@ bool Dependencies::is_concrete_method(Method* m, Klass * k) {
(m->is_overpass() && k != NULL && k -> is_abstract()) );
}
Klass* Dependencies::find_finalizable_subclass(Klass* k) {
if (k->is_interface()) return NULL;
if (k->has_finalizer()) return k;
@ -1543,7 +1573,6 @@ Klass* Dependencies::find_finalizable_subclass(Klass* k) {
return NULL;
}
bool Dependencies::is_concrete_klass(ciInstanceKlass* k) {
if (k->is_abstract()) return false;
// We could also return false if k does not yet appear to be
@ -1556,7 +1585,6 @@ bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) {
return k->has_finalizable_subclass();
}
// Any use of the contents (bytecodes) of a method must be
// marked by an "evol_method" dependency, if those contents
// can change. (Note: A method is always dependent on itself.)

View File

@ -463,6 +463,10 @@ C2V_VMENTRY_NULL(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, jobje
JVMCI_THROW_MSG_NULL(InternalError, err_msg("Effectively static method %s.%s should be handled in Java code", method->method_holder()->external_name(), method->external_name()));
}
if (method->is_abstract()) {
return NULL;
}
methodHandle ucm;
{
MutexLocker locker(Compile_lock);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2021, 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
@ -501,6 +501,9 @@ public class File
public File getParentFile() {
String p = this.getParent();
if (p == null) return null;
if (getClass() != File.class) {
p = fs.normalize(p);
}
return new File(p, this.prefixLength);
}
@ -573,6 +576,9 @@ public class File
*/
public File getAbsoluteFile() {
String absPath = getAbsolutePath();
if (getClass() != File.class) {
absPath = fs.normalize(absPath);
}
return new File(absPath, fs.prefixLength(absPath));
}
@ -644,6 +650,9 @@ public class File
*/
public File getCanonicalFile() throws IOException {
String canonPath = getCanonicalPath();
if (getClass() != File.class) {
canonPath = fs.normalize(canonPath);
}
return new File(canonPath, fs.prefixLength(canonPath));
}
@ -1126,6 +1135,26 @@ public class File
* the directory
*/
public String[] list() {
return normalizedList();
}
/**
* Returns an array of strings naming the files and directories in the
* directory denoted by this abstract pathname. The strings are
* ensured to represent normalized paths.
*
* @return An array of strings naming the files and directories in the
* directory denoted by this abstract pathname. The array will be
* empty if the directory is empty. Returns {@code null} if
* this abstract pathname does not denote a directory, or if an
* I/O error occurs.
*
* @throws SecurityException
* If a security manager exists and its {@link
* SecurityManager#checkRead(String)} method denies read access to
* the directory
*/
private final String[] normalizedList() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
@ -1133,7 +1162,15 @@ public class File
if (isInvalid()) {
return null;
}
return fs.list(this);
String[] s = fs.list(this);
if (s != null && getClass() != File.class) {
String[] normalized = new String[s.length];
for (int i = 0; i < s.length; i++) {
normalized[i] = fs.normalize(s[i]);
}
s = normalized;
}
return s;
}
/**
@ -1166,7 +1203,7 @@ public class File
* @see java.nio.file.Files#newDirectoryStream(Path,String)
*/
public String[] list(FilenameFilter filter) {
String names[] = list();
String names[] = normalizedList();
if ((names == null) || (filter == null)) {
return names;
}
@ -1218,7 +1255,7 @@ public class File
* @since 1.2
*/
public File[] listFiles() {
String[] ss = list();
String[] ss = normalizedList();
if (ss == null) return null;
int n = ss.length;
File[] fs = new File[n];
@ -1259,7 +1296,7 @@ public class File
* @see java.nio.file.Files#newDirectoryStream(Path,String)
*/
public File[] listFiles(FilenameFilter filter) {
String ss[] = list();
String ss[] = normalizedList();
if (ss == null) return null;
ArrayList<File> files = new ArrayList<>();
for (String s : ss)
@ -1297,7 +1334,7 @@ public class File
* @see java.nio.file.Files#newDirectoryStream(Path,java.nio.file.DirectoryStream.Filter)
*/
public File[] listFiles(FileFilter filter) {
String ss[] = list();
String ss[] = normalizedList();
if (ss == null) return null;
ArrayList<File> files = new ArrayList<>();
for (String s : ss) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2020, 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
@ -63,4 +63,8 @@ class CertPathHelperImpl extends CertPathHelper {
protected void implSetDateAndTime(X509CRLSelector sel, Date date, long skew) {
sel.setDateAndTime(date, skew);
}
protected boolean implIsJdkCA(TrustAnchor anchor) {
return anchor.isJdkCA();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2020, 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
@ -30,6 +30,7 @@ import java.security.PublicKey;
import javax.security.auth.x500.X500Principal;
import sun.security.util.AnchorCertificates;
import sun.security.x509.NameConstraintsExtension;
import sun.security.x509.X500Name;
@ -68,6 +69,12 @@ public class TrustAnchor {
private final X509Certificate trustedCert;
private byte[] ncBytes;
private NameConstraintsExtension nc;
private boolean jdkCA;
private boolean hasJdkCABeenChecked;
static {
CertPathHelperImpl.initialize();
}
/**
* Creates an instance of {@code TrustAnchor} with the specified
@ -330,4 +337,18 @@ public class TrustAnchor {
sb.append(" Name Constraints: " + nc.toString() + "\n");
return sb.toString();
}
/**
* Returns true if anchor is a JDK CA (a root CA that is included by
* default in the cacerts keystore).
*/
synchronized boolean isJdkCA() {
if (!hasJdkCABeenChecked) {
if (trustedCert != null) {
jdkCA = AnchorCertificates.contains(trustedCert);
}
hasJdkCABeenChecked = true;
}
return jdkCA;
}
}

View File

@ -29,7 +29,6 @@ import jdk.internal.access.SharedSecrets;
import jdk.internal.access.JavaUtilZipFileAccess;
import sun.security.action.GetPropertyAction;
import sun.security.util.ManifestEntryVerifier;
import sun.security.util.SignatureFileVerifier;
import java.io.ByteArrayInputStream;
import java.io.EOFException;

View File

@ -35,9 +35,11 @@ import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.security.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import sun.security.timestamp.TimestampToken;
@ -49,7 +51,9 @@ import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.util.HexDumpEncoder;
import sun.security.util.JarConstraintsParameters;
import sun.security.util.KeyUtil;
import sun.security.util.KnownOIDs;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
@ -63,16 +67,8 @@ import sun.security.util.SignatureUtil;
*/
public class SignerInfo implements DerEncoder {
// Digest and Signature restrictions
private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET =
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET =
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
DisabledAlgorithmConstraints.jarConstraints();
BigInteger version;
X500Name issuerName;
@ -87,6 +83,14 @@ public class SignerInfo implements DerEncoder {
PKCS9Attributes authenticatedAttributes;
PKCS9Attributes unauthenticatedAttributes;
/**
* A map containing the algorithms in this SignerInfo. This is used to
* avoid checking algorithms to see if they are disabled more than once.
* The key is the AlgorithmId of the algorithm, and the value is the name of
* the field or attribute.
*/
private Map<AlgorithmId, String> algorithms = new HashMap<>();
public SignerInfo(X500Name issuerName,
BigInteger serial,
AlgorithmId digestAlgorithmId,
@ -313,21 +317,15 @@ public class SignerInfo implements DerEncoder {
throws NoSuchAlgorithmException, SignatureException {
try {
Timestamp timestamp = getTimestamp();
ContentInfo content = block.getContentInfo();
if (data == null) {
data = content.getContentBytes();
}
Timestamp timestamp = null;
try {
timestamp = getTimestamp();
} catch (Exception ignore) {
}
ConstraintsParameters cparams =
new ConstraintsParameters(timestamp);
String digestAlgname = getDigestAlgorithmId().getName();
String digestAlgName = digestAlgorithmId.getName();
algorithms.put(digestAlgorithmId, "SignerInfo digestAlgorithm field");
byte[] dataSigned;
@ -353,20 +351,10 @@ public class SignerInfo implements DerEncoder {
if (messageDigest == null) // fail if there is no message digest
return null;
// check that digest algorithm is not restricted
try {
JAR_DISABLED_CHECK.permits(digestAlgname, cparams);
} catch (CertPathValidatorException e) {
throw new SignatureException(e.getMessage(), e);
}
MessageDigest md = MessageDigest.getInstance(digestAlgname);
MessageDigest md = MessageDigest.getInstance(digestAlgName);
byte[] computedMessageDigest = md.digest(data);
if (messageDigest.length != computedMessageDigest.length)
return null;
for (int i = 0; i < messageDigest.length; i++) {
if (messageDigest[i] != computedMessageDigest[i])
if (!MessageDigest.isEqual(messageDigest, computedMessageDigest)) {
return null;
}
@ -381,21 +369,23 @@ public class SignerInfo implements DerEncoder {
// put together digest algorithm and encryption algorithm
// to form signing algorithm
String encryptionAlgname =
String encryptionAlgName =
getDigestEncryptionAlgorithmId().getName();
// Workaround: sometimes the encryptionAlgname is actually
// a signature name
String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
if (tmp != null) encryptionAlgname = tmp;
String algname = AlgorithmId.makeSigAlg(
digestAlgname, encryptionAlgname);
String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgName);
if (tmp != null) encryptionAlgName = tmp;
String sigAlgName = AlgorithmId.makeSigAlg(
digestAlgName, encryptionAlgName);
// check that jar signature algorithm is not restricted
try {
JAR_DISABLED_CHECK.permits(algname, cparams);
} catch (CertPathValidatorException e) {
throw new SignatureException(e.getMessage(), e);
KnownOIDs oid = KnownOIDs.findMatch(sigAlgName);
if (oid != null) {
AlgorithmId sigAlgId =
new AlgorithmId(ObjectIdentifier.of(oid),
digestEncryptionAlgorithmId.getParameters());
algorithms.put(sigAlgId,
"SignerInfo digestEncryptionAlgorithm field");
}
X509Certificate cert = getCertificate(block);
@ -404,14 +394,6 @@ public class SignerInfo implements DerEncoder {
}
PublicKey key = cert.getPublicKey();
// check if the public key is restricted
if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
throw new SignatureException("Public key check failed. " +
"Disabled key used: " +
KeyUtil.getKeySize(key) + " bit " +
key.getAlgorithm());
}
if (cert.hasUnsupportedCriticalExtension()) {
throw new SignatureException("Certificate has unsupported "
+ "critical extension(s)");
@ -448,13 +430,13 @@ public class SignerInfo implements DerEncoder {
}
}
Signature sig = Signature.getInstance(algname);
Signature sig = Signature.getInstance(sigAlgName);
AlgorithmParameters ap =
digestEncryptionAlgorithmId.getParameters();
try {
SignatureUtil.initVerifyWithParam(sig, key,
SignatureUtil.getParamSpec(algname, ap));
SignatureUtil.getParamSpec(sigAlgName, ap));
} catch (ProviderException | InvalidAlgorithmParameterException |
InvalidKeyException e) {
throw new SignatureException(e.getMessage(), e);
@ -464,9 +446,8 @@ public class SignerInfo implements DerEncoder {
if (sig.verify(encryptedDigest)) {
return this;
}
} catch (IOException e) {
throw new SignatureException("IO error verifying signature:\n" +
e.getMessage());
} catch (IOException | CertificateException e) {
throw new SignatureException("Error verifying signature", e);
}
return null;
}
@ -564,6 +545,9 @@ public class SignerInfo implements DerEncoder {
// Extract the signer (the Timestamping Authority)
// while verifying the content
SignerInfo[] tsa = tsToken.verify(encTsTokenInfo);
if (tsa == null || tsa.length == 0) {
throw new SignatureException("Unable to verify timestamp");
}
// Expect only one signer
ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(tsToken);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@ -572,6 +556,7 @@ public class SignerInfo implements DerEncoder {
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
// Check that the signature timestamp applies to this signature
verifyTimestamp(tsTokenInfo);
algorithms.putAll(tsa[0].algorithms);
// Create a timestamp object
timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain);
return timestamp;
@ -584,18 +569,13 @@ public class SignerInfo implements DerEncoder {
*/
private void verifyTimestamp(TimestampToken token)
throws NoSuchAlgorithmException, SignatureException {
String digestAlgname = token.getHashAlgorithm().getName();
// check that algorithm is not restricted
if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, digestAlgname,
null)) {
throw new SignatureException("Timestamp token digest check failed. " +
"Disabled algorithm used: " + digestAlgname);
}
MessageDigest md =
MessageDigest.getInstance(digestAlgname);
AlgorithmId digestAlgId = token.getHashAlgorithm();
algorithms.put(digestAlgId, "TimestampToken digestAlgorithm field");
if (!Arrays.equals(token.getHashedMessage(),
MessageDigest md = MessageDigest.getInstance(digestAlgId.getName());
if (!MessageDigest.isEqual(token.getHashedMessage(),
md.digest(encryptedDigest))) {
throw new SignatureException("Signature timestamp (#" +
@ -636,4 +616,35 @@ public class SignerInfo implements DerEncoder {
}
return out;
}
/**
* Verify all of the algorithms in the array of SignerInfos against the
* constraints in the jdk.jar.disabledAlgorithms security property.
*
* @param infos array of SignerInfos
* @param params constraint parameters
* @param name the name of the signer's PKCS7 file
* @return a set of algorithms that passed the checks and are not disabled
*/
public static Set<String> verifyAlgorithms(SignerInfo[] infos,
JarConstraintsParameters params, String name) throws SignatureException {
Map<AlgorithmId, String> algorithms = new HashMap<>();
for (SignerInfo info : infos) {
algorithms.putAll(info.algorithms);
}
Set<String> enabledAlgorithms = new HashSet<>();
try {
for (Map.Entry<AlgorithmId, String> algorithm : algorithms.entrySet()) {
params.setExtendedExceptionMsg(name, algorithm.getValue());
AlgorithmId algId = algorithm.getKey();
JAR_DISABLED_CHECK.permits(algId.getName(),
algId.getParameters(), params);
enabledAlgorithms.add(algId.getName());
}
} catch (CertPathValidatorException e) {
throw new SignatureException(e);
}
return enabledAlgorithms;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2020, 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
@ -27,8 +27,6 @@ package sun.security.provider.certpath;
import java.security.AlgorithmConstraints;
import java.security.CryptoPrimitive;
import java.security.Timestamp;
import java.security.cert.CertPathValidator;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
@ -53,14 +51,13 @@ import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAPublicKeySpec;
import sun.security.util.AnchorCertificates;
import sun.security.util.ConstraintsParameters;
import sun.security.util.Debug;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.validator.Validator;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CRLImpl;
import sun.security.x509.AlgorithmId;
/**
* A {@code PKIXCertPathChecker} implementation to check whether a
@ -78,10 +75,10 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
private final AlgorithmConstraints constraints;
private final PublicKey trustedPubKey;
private final Date pkixdate;
private final Date date;
private PublicKey prevPubKey;
private final Timestamp jarTimestamp;
private final String variant;
private TrustAnchor anchor;
private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
@ -94,95 +91,70 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
CryptoPrimitive.KEY_AGREEMENT));
private static final DisabledAlgorithmConstraints
certPathDefaultConstraints = new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
// If there is no "cacerts" keyword, then disable anchor checking
private static final boolean publicCALimits =
certPathDefaultConstraints.checkProperty("jdkCA");
// If anchor checking enabled, this will be true if the trust anchor
// has a match in the cacerts file
private boolean trustedMatch = false;
certPathDefaultConstraints =
DisabledAlgorithmConstraints.certPathConstraints();
/**
* Create a new {@code AlgorithmChecker} with the given algorithm
* given {@code TrustAnchor} and {@code String} variant.
* Create a new {@code AlgorithmChecker} with the given
* {@code TrustAnchor} and {@code String} variant.
*
* @param anchor the trust anchor selected to validate the target
* certificate
* @param variant is the Validator variants of the operation. A null value
* @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
public AlgorithmChecker(TrustAnchor anchor, String variant) {
this(anchor, certPathDefaultConstraints, null, null, variant);
this(anchor, certPathDefaultConstraints, null, variant);
}
/**
* Create a new {@code AlgorithmChecker} with the given
* {@code AlgorithmConstraints}, {@code Timestamp}, and {@code String}
* variant.
* {@code AlgorithmConstraints} and {@code String} variant.
*
* Note that this constructor can initialize a variation of situations where
* the AlgorithmConstraints, Timestamp, or Variant maybe known.
* the AlgorithmConstraints or Variant maybe known.
*
* @param constraints the algorithm constraints (or null)
* @param jarTimestamp Timestamp passed for JAR timestamp constraint
* checking. Set to null if not applicable.
* @param variant is the Validator variants of the operation. A null value
* @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
public AlgorithmChecker(AlgorithmConstraints constraints,
Timestamp jarTimestamp, String variant) {
this(null, constraints, null, jarTimestamp, variant);
public AlgorithmChecker(AlgorithmConstraints constraints, String variant) {
this(null, constraints, null, variant);
}
/**
* Create a new {@code AlgorithmChecker} with the
* given {@code TrustAnchor}, {@code AlgorithmConstraints},
* {@code Timestamp}, and {@code String} variant.
* given {@code TrustAnchor}, {@code AlgorithmConstraints}, {@code Date},
* and {@code String} variant.
*
* @param anchor the trust anchor selected to validate the target
* certificate
* @param constraints the algorithm constraints (or null)
* @param pkixdate The date specified by the PKIXParameters date. If the
* PKIXParameters is null, the current date is used. This
* should be null when jar files are being checked.
* @param jarTimestamp Timestamp passed for JAR timestamp constraint
* checking. Set to null if not applicable.
* @param variant is the Validator variants of the operation. A null value
* @param date the date specified by the PKIXParameters date, or the
* JAR timestamp if jar files are being validated and the
* JAR is timestamped. May be null if no timestamp or
* PKIXParameter date is set.
* @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
public AlgorithmChecker(TrustAnchor anchor,
AlgorithmConstraints constraints, Date pkixdate,
Timestamp jarTimestamp, String variant) {
AlgorithmConstraints constraints, Date date, String variant) {
if (anchor != null) {
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
// Check for anchor certificate restrictions
trustedMatch = checkFingerprint(anchor.getTrustedCert());
if (trustedMatch && debug != null) {
debug.println("trustedMatch = true");
}
} else {
this.trustedPubKey = anchor.getCAPublicKey();
}
this.anchor = anchor;
} else {
this.trustedPubKey = null;
if (debug != null) {
debug.println("TrustAnchor is null, trustedMatch is false.");
}
}
this.prevPubKey = this.trustedPubKey;
this.constraints = (constraints == null ? certPathDefaultConstraints :
constraints);
// If we are checking jar files, set pkixdate the same as the timestamp
// for certificate checking
this.pkixdate = (jarTimestamp != null ? jarTimestamp.getTimestamp() :
pkixdate);
this.jarTimestamp = jarTimestamp;
this.date = date;
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
}
@ -194,24 +166,11 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
* certificate
* @param pkixdate Date the constraints are checked against. The value is
* either the PKIXParameters date or null for the current date.
* @param variant is the Validator variants of the operation. A null value
* @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
public AlgorithmChecker(TrustAnchor anchor, Date pkixdate, String variant) {
this(anchor, certPathDefaultConstraints, pkixdate, null, variant);
}
// Check this 'cert' for restrictions in the AnchorCertificates
// trusted certificates list
private static boolean checkFingerprint(X509Certificate cert) {
if (!publicCALimits) {
return false;
}
if (debug != null) {
debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName());
}
return AnchorCertificates.contains(cert);
this(anchor, certPathDefaultConstraints, pkixdate, variant);
}
@Override
@ -318,18 +277,19 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
}
ConstraintsParameters cp =
new ConstraintsParameters((X509Certificate)cert,
trustedMatch, pkixdate, jarTimestamp, variant);
new CertPathConstraintsParameters(x509Cert, variant,
anchor, date);
// Check against local constraints if it is DisabledAlgorithmConstraints
if (constraints instanceof DisabledAlgorithmConstraints) {
((DisabledAlgorithmConstraints)constraints).permits(currSigAlg, cp);
((DisabledAlgorithmConstraints)constraints).permits(currSigAlg,
currSigAlgParams, cp);
// DisabledAlgorithmsConstraints does not check primitives, so key
// additional key check.
} else {
// Perform the default constraints checking anyway.
certPathDefaultConstraints.permits(currSigAlg, cp);
certPathDefaultConstraints.permits(currSigAlg, currSigAlgParams, cp);
// Call locally set constraints to check key with primitives.
if (!constraints.permits(primitives, currPubKey)) {
throw new CertPathValidatorException(
@ -408,14 +368,10 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
// Don't bother to change the trustedPubKey.
if (anchor.getTrustedCert() != null) {
prevPubKey = anchor.getTrustedCert().getPublicKey();
// Check for anchor certificate restrictions
trustedMatch = checkFingerprint(anchor.getTrustedCert());
if (trustedMatch && debug != null) {
debug.println("trustedMatch = true");
}
} else {
prevPubKey = anchor.getCAPublicKey();
}
this.anchor = anchor;
}
}
@ -424,11 +380,12 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
*
* @param key the public key to verify the CRL signature
* @param crl the target CRL
* @param variant is the Validator variants of the operation. A null value
* @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
* @param anchor the trust anchor selected to validate the CRL issuer
*/
static void check(PublicKey key, X509CRL crl, String variant)
throws CertPathValidatorException {
static void check(PublicKey key, X509CRL crl, String variant,
TrustAnchor anchor) throws CertPathValidatorException {
X509CRLImpl x509CRLImpl = null;
try {
@ -438,7 +395,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
}
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
check(key, algorithmId, variant);
check(key, algorithmId, variant, anchor);
}
/**
@ -446,16 +403,16 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
*
* @param key the public key to verify the CRL signature
* @param algorithmId signature algorithm Algorithm ID
* @param variant is the Validator variants of the operation. A null value
* passed will set it to Validator.GENERIC.
* @param variant the Validator variant of the operation. A null
* value passed will set it to Validator.GENERIC.
* @param anchor the trust anchor selected to validate the public key
*/
static void check(PublicKey key, AlgorithmId algorithmId, String variant)
throws CertPathValidatorException {
String sigAlgName = algorithmId.getName();
AlgorithmParameters sigAlgParams = algorithmId.getParameters();
static void check(PublicKey key, AlgorithmId algorithmId, String variant,
TrustAnchor anchor) throws CertPathValidatorException {
certPathDefaultConstraints.permits(new ConstraintsParameters(
sigAlgName, sigAlgParams, key, variant));
certPathDefaultConstraints.permits(algorithmId.getName(),
algorithmId.getParameters(),
new CertPathConstraintsParameters(key, variant, anchor));
}
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2020, 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 sun.security.provider.certpath;
import java.security.Key;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Set;
import sun.security.util.ConstraintsParameters;
import sun.security.validator.Validator;
/**
* This class contains parameters for checking certificates against
* constraints specified in the jdk.certpath.disabledAlgorithms security
* property.
*/
class CertPathConstraintsParameters implements ConstraintsParameters {
// The public key of the certificate
private final Key key;
// The certificate's trust anchor which will be checked against the
// jdkCA constraint, if specified.
private final TrustAnchor anchor;
// The PKIXParameter validity date or the timestamp of the signed JAR
// file, if this chain is associated with a timestamped signed JAR.
private final Date date;
// The variant or usage of this certificate
private final String variant;
// The certificate being checked (may be null if a CRL or OCSPResponse is
// being checked)
private final X509Certificate cert;
public CertPathConstraintsParameters(X509Certificate cert,
String variant, TrustAnchor anchor, Date date) {
this(cert.getPublicKey(), variant, anchor, date, cert);
}
public CertPathConstraintsParameters(Key key, String variant,
TrustAnchor anchor) {
this(key, variant, anchor, null, null);
}
private CertPathConstraintsParameters(Key key, String variant,
TrustAnchor anchor, Date date, X509Certificate cert) {
this.key = key;
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
this.anchor = anchor;
this.date = date;
this.cert = cert;
}
@Override
public boolean anchorIsJdkCA() {
return CertPathHelper.isJdkCA(anchor);
}
@Override
public Set<Key> getKeys() {
return (key == null) ? Set.of() : Set.of(key);
}
@Override
public Date getDate() {
return date;
}
@Override
public String getVariant() {
return variant;
}
@Override
public String extendedExceptionMsg() {
return (cert == null ? "."
: " used with certificate: " +
cert.getSubjectX500Principal());
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[\n");
sb.append("\n Variant: ").append(variant);
if (anchor != null) {
sb.append("\n Anchor: ").append(anchor);
}
if (cert != null) {
sb.append("\n Cert Issuer: ")
.append(cert.getIssuerX500Principal());
sb.append("\n Cert Subject: ")
.append(cert.getSubjectX500Principal());
}
if (key != null) {
sb.append("\n Key: ").append(key.getAlgorithm());
}
if (date != null) {
sb.append("\n Date: ").append(date);
}
sb.append("\n]");
return sb.toString();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2020, 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
@ -28,13 +28,14 @@ package sun.security.provider.certpath;
import java.util.Date;
import java.util.Set;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509CRLSelector;
import sun.security.x509.GeneralNameInterface;
/**
* Helper class that allows access to Sun specific known-public methods in the
* Helper class that allows access to JDK specific known-public methods in the
* java.security.cert package. It relies on a subclass in the
* java.security.cert packages that is initialized before any of these methods
* are called (achieved via static initializers).
@ -59,6 +60,8 @@ public abstract class CertPathHelper {
protected abstract void implSetDateAndTime(X509CRLSelector sel, Date date, long skew);
protected abstract boolean implIsJdkCA(TrustAnchor anchor);
static void setPathToNames(X509CertSelector sel,
Set<GeneralNameInterface> names) {
instance.implSetPathToNames(sel, names);
@ -67,4 +70,8 @@ public abstract class CertPathHelper {
public static void setDateAndTime(X509CRLSelector sel, Date date, long skew) {
instance.implSetDateAndTime(sel, date, skew);
}
public static boolean isJdkCA(TrustAnchor anchor) {
return (anchor == null) ? false : instance.implIsJdkCA(anchor);
}
}

View File

@ -74,7 +74,7 @@ public class DistributionPointFetcher {
throws CertStoreException
{
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
reasonsMask, trustAnchors, validity, variant);
reasonsMask, trustAnchors, validity, variant, null);
}
/**
* Return the X509CRLs matching this selector. The selector must be
@ -91,8 +91,14 @@ public class DistributionPointFetcher {
Date validity)
throws CertStoreException
{
if (trustAnchors.isEmpty()) {
throw new CertStoreException(
"at least one TrustAnchor must be specified");
}
TrustAnchor anchor = trustAnchors.iterator().next();
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
reasonsMask, trustAnchors, validity, Validator.VAR_GENERIC);
reasonsMask, trustAnchors, validity,
Validator.VAR_PLUGIN_CODE_SIGNING, anchor);
}
/**
@ -108,7 +114,8 @@ public class DistributionPointFetcher {
boolean[] reasonsMask,
Set<TrustAnchor> trustAnchors,
Date validity,
String variant)
String variant,
TrustAnchor anchor)
throws CertStoreException
{
X509Certificate cert = selector.getCertificateChecking();
@ -137,7 +144,7 @@ public class DistributionPointFetcher {
DistributionPoint point = t.next();
Collection<X509CRL> crls = getCRLs(selector, certImpl,
point, reasonsMask, signFlag, prevKey, prevCert, provider,
certStores, trustAnchors, validity, variant);
certStores, trustAnchors, validity, variant, anchor);
results.addAll(crls);
}
if (debug != null) {
@ -162,7 +169,8 @@ public class DistributionPointFetcher {
X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
boolean signFlag, PublicKey prevKey, X509Certificate prevCert,
String provider, List<CertStore> certStores,
Set<TrustAnchor> trustAnchors, Date validity, String variant)
Set<TrustAnchor> trustAnchors, Date validity, String variant,
TrustAnchor anchor)
throws CertStoreException {
// check for full name
@ -225,7 +233,7 @@ public class DistributionPointFetcher {
selector.setIssuerNames(null);
if (selector.match(crl) && verifyCRL(certImpl, point, crl,
reasonsMask, signFlag, prevKey, prevCert, provider,
trustAnchors, certStores, validity, variant)) {
trustAnchors, certStores, validity, variant, anchor)) {
crls.add(crl);
}
} catch (IOException | CRLException e) {
@ -335,7 +343,8 @@ public class DistributionPointFetcher {
X509CRL crl, boolean[] reasonsMask, boolean signFlag,
PublicKey prevKey, X509Certificate prevCert, String provider,
Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
Date validity, String variant) throws CRLException, IOException {
Date validity, String variant, TrustAnchor anchor)
throws CRLException, IOException {
if (debug != null) {
debug.println("DistributionPointFetcher.verifyCRL: " +
@ -682,7 +691,7 @@ public class DistributionPointFetcher {
// check the crl signature algorithm
try {
AlgorithmChecker.check(prevKey, crl, variant);
AlgorithmChecker.check(prevKey, crl, variant, anchor);
} catch (CertPathValidatorException cpve) {
if (debug != null) {
debug.println("CRL signature algorithm check failed: " + cpve);

View File

@ -122,7 +122,8 @@ public final class OCSP {
throws IOException, CertPathValidatorException
{
return check(cert, issuerCert, responderURI, responderCert, date,
Collections.<Extension>emptyList(), Validator.VAR_GENERIC);
Collections.<Extension>emptyList(),
Validator.VAR_PLUGIN_CODE_SIGNING);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, 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
@ -462,6 +462,7 @@ public final class OCSPResponse {
}
// Check whether the signer cert returned by the responder is trusted
boolean signedByTrustedResponder = false;
if (signerCert != null) {
// Check if the response is signed by the issuing CA
if (signerCert.getSubjectX500Principal().equals(
@ -476,6 +477,7 @@ public final class OCSPResponse {
// Check if the response is signed by a trusted responder
} else if (signerCert.equals(responderCert)) {
signedByTrustedResponder = true;
if (debug != null) {
debug.println("OCSP response is signed by a Trusted " +
"Responder");
@ -566,7 +568,10 @@ public final class OCSPResponse {
if (signerCert != null) {
// Check algorithm constraints specified in security property
// "jdk.certpath.disabledAlgorithms".
AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId, variant);
AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId, variant,
signedByTrustedResponder
? new TrustAnchor(responderCert, null)
: issuerInfo.getAnchor());
if (!verifySignature(signerCert)) {
throw new CertPathValidatorException(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, 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
@ -33,6 +33,7 @@ import java.util.*;
import javax.security.auth.x500.X500Principal;
import sun.security.util.Debug;
import sun.security.validator.Validator;
/**
* Common utility methods and classes used by the PKIX CertPathValidator and
@ -87,7 +88,7 @@ class PKIX {
private Set<TrustAnchor> anchors;
private List<X509Certificate> certs;
private Timestamp timestamp;
private String variant;
private String variant = Validator.VAR_GENERIC;
ValidatorParams(CertPath cp, PKIXParameters params)
throws InvalidAlgorithmParameterException
@ -155,9 +156,17 @@ class PKIX {
}
Date date() {
if (!gotDate) {
// use timestamp if checking signed code that is
// timestamped, otherwise use date parameter
if (timestamp != null &&
(variant.equals(Validator.VAR_CODE_SIGNING) ||
variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING))) {
date = timestamp.getTimestamp();
} else {
date = params.getDate();
if (date == null)
date = new Date();
}
gotDate = true;
}
return date;
@ -198,10 +207,6 @@ class PKIX {
return params;
}
Timestamp timestamp() {
return timestamp;
}
String variant() {
return variant;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2020, 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
@ -34,7 +34,6 @@ import java.util.concurrent.atomic.AtomicLong;
import jdk.internal.event.X509ValidationEvent;
import jdk.internal.event.EventHelper;
import sun.security.provider.certpath.PKIX.ValidatorParams;
import sun.security.validator.Validator;
import sun.security.x509.X509CertImpl;
import sun.security.util.Debug;
@ -178,7 +177,7 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
// add standard checkers that we will be using
certPathCheckers.add(untrustedChecker);
certPathCheckers.add(new AlgorithmChecker(anchor, null, params.date(),
params.timestamp(), params.variant()));
params.variant()));
certPathCheckers.add(new KeyChecker(certPathLen,
params.targetCertConstraints()));
certPathCheckers.add(new ConstraintsChecker(certPathLen));
@ -195,19 +194,7 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
rootNode);
certPathCheckers.add(pc);
// the time that the certificate validity period should be
// checked against
Date timeToCheck = null;
// use timestamp if checking signed code that is timestamped, otherwise
// use date parameter from PKIXParameters
if ((params.variant() == Validator.VAR_CODE_SIGNING ||
params.variant() == Validator.VAR_PLUGIN_CODE_SIGNING) &&
params.timestamp() != null) {
timeToCheck = params.timestamp().getTimestamp();
} else {
timeToCheck = params.date();
}
BasicChecker bc = new BasicChecker(anchor, timeToCheck,
BasicChecker bc = new BasicChecker(anchor, params.date(),
params.sigProvider(), false);
certPathCheckers.add(bc);

View File

@ -580,7 +580,8 @@ class RevocationChecker extends PKIXRevocationChecker {
approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
sel, signFlag, prevKey, prevCert,
params.sigProvider(), certStores,
reasonsMask, anchors, null, params.variant()));
reasonsMask, anchors, null,
params.variant(), anchor));
}
} catch (CertStoreException e) {
if (e instanceof CertStoreTypeException) {
@ -854,7 +855,7 @@ class RevocationChecker extends PKIXRevocationChecker {
if (DistributionPointFetcher.verifyCRL(
certImpl, point, crl, reasonsMask, signFlag,
prevKey, null, params.sigProvider(), anchors,
certStores, params.date(), params.variant()))
certStores, params.date(), params.variant(), anchor))
{
results.add(crl);
}

View File

@ -1560,7 +1560,7 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
// A forward checker, need to check from trust to target
if (checkedLength >= 0) {
AlgorithmChecker checker =
new AlgorithmChecker(constraints, null,
new AlgorithmChecker(constraints,
(checkClientTrusted ? Validator.VAR_TLS_CLIENT :
Validator.VAR_TLS_SERVER));
checker.init(false);

View File

@ -838,8 +838,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
AlgorithmConstraints constraints, Certificate[] chain,
String variant) {
AlgorithmChecker checker =
new AlgorithmChecker(constraints, null, variant);
AlgorithmChecker checker = new AlgorithmChecker(constraints, variant);
try {
checker.init(false);
} catch (CertPathValidatorException cpve) {

View File

@ -36,6 +36,7 @@ import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
import jdk.internal.util.StaticProperty;
import sun.security.x509.X509CertImpl;
@ -48,9 +49,10 @@ public class AnchorCertificates {
private static final Debug debug = Debug.getInstance("certpath");
private static final String HASH = "SHA-256";
private static Set<String> certs = Collections.emptySet();
private static Set<X500Principal> certIssuers = Collections.emptySet();
static {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public Void run() {
File f = new File(StaticProperty.javaHome(),
@ -61,15 +63,16 @@ public class AnchorCertificates {
try (FileInputStream fis = new FileInputStream(f)) {
cacerts.load(fis, null);
certs = new HashSet<>();
certIssuers = new HashSet<>();
Enumeration<String> list = cacerts.aliases();
String alias;
while (list.hasMoreElements()) {
alias = list.nextElement();
String alias = list.nextElement();
// Check if this cert is labeled a trust anchor.
if (alias.contains(" [jdk")) {
X509Certificate cert = (X509Certificate) cacerts
.getCertificate(alias);
certs.add(X509CertImpl.getFingerprint(HASH, cert));
certIssuers.add(cert.getSubjectX500Principal());
}
}
}
@ -85,10 +88,10 @@ public class AnchorCertificates {
}
/**
* Checks if a certificate is a trust anchor.
* Checks if a certificate is a JDK trust anchor.
*
* @param cert the certificate to check
* @return true if the certificate is trusted.
* @return true if the certificate is a JDK trust anchor
*/
public static boolean contains(X509Certificate cert) {
String key = X509CertImpl.getFingerprint(HASH, cert);
@ -100,5 +103,15 @@ public class AnchorCertificates {
return result;
}
/**
* Checks if a JDK trust anchor is the issuer of a certificate.
*
* @param cert the certificate to check
* @return true if the certificate is issued by a trust anchor
*/
public static boolean issuerOf(X509Certificate cert) {
return certIssuers.contains(cert.getIssuerX500Principal());
}
private AnchorCertificates() {}
}

View File

@ -25,167 +25,42 @@
package sun.security.util;
import sun.security.validator.Validator;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Timestamp;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECKey;
import java.security.interfaces.XECKey;
import java.security.spec.NamedParameterSpec;
import java.util.Date;
import java.util.Set;
/**
* This class contains parameters for checking against constraints that extend
* past the publicly available parameters in java.security.AlgorithmConstraints.
*
* This is currently passed between PKIX, AlgorithmChecker,
* and DisabledAlgorithmConstraints.
* This interface contains parameters for checking against constraints that
* extend past the publicly available parameters in
* java.security.AlgorithmConstraints.
*/
public class ConstraintsParameters {
/*
* The below 3 values are used the same as the permit() methods
* published in java.security.AlgorithmConstraints.
public interface ConstraintsParameters {
/**
* Returns true if a certificate chains back to a trusted JDK root CA.
*/
// Algorithm string to be checked against constraints
private final String algorithm;
// AlgorithmParameters to the algorithm being checked
private final AlgorithmParameters algParams;
// Key being checked against constraints
private final Key key;
boolean anchorIsJdkCA();
/*
* New values that are checked against constraints that the current public
* API does not support.
/**
* Returns the set of keys that should be checked against the
* constraints, or an empty set if there are no keys to be checked.
*/
// A certificate being passed to check against constraints.
private final X509Certificate cert;
// This is true if the trust anchor in the certificate chain matches a cert
// in AnchorCertificates
private final boolean trustedMatch;
// PKIXParameter date
private final Date pkixDate;
// Timestamp of the signed JAR file
private final Timestamp jarTimestamp;
private final String variant;
// Named Curve
private final String[] curveStr;
private static final String[] EMPTYLIST = new String[0];
Set<Key> getKeys();
public ConstraintsParameters(X509Certificate c, boolean match,
Date pkixdate, Timestamp jarTime, String variant) {
cert = c;
trustedMatch = match;
pkixDate = pkixdate;
jarTimestamp = jarTime;
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
algorithm = null;
algParams = null;
key = null;
if (c != null) {
curveStr = getNamedCurveFromKey(c.getPublicKey());
} else {
curveStr = EMPTYLIST;
}
}
/**
* Returns the date that should be checked against the constraints, or
* null if not set.
*/
Date getDate();
public ConstraintsParameters(String algorithm, AlgorithmParameters params,
Key key, String variant) {
this.algorithm = algorithm;
algParams = params;
this.key = key;
curveStr = getNamedCurveFromKey(key);
cert = null;
trustedMatch = false;
pkixDate = null;
jarTimestamp = null;
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
}
public ConstraintsParameters(X509Certificate c) {
this(c, false, null, null,
Validator.VAR_GENERIC);
}
public ConstraintsParameters(Timestamp jarTime) {
this(null, false, null, jarTime, Validator.VAR_GENERIC);
}
public String getAlgorithm() {
return algorithm;
}
public AlgorithmParameters getAlgParams() {
return algParams;
}
public Key getKey() {
return key;
}
// Returns if the trust anchor has a match if anchor checking is enabled.
public boolean isTrustedMatch() {
return trustedMatch;
}
public X509Certificate getCertificate() {
return cert;
}
public Date getPKIXParamDate() {
return pkixDate;
}
public Timestamp getJARTimestamp() {
return jarTimestamp;
}
public String getVariant() {
return variant;
}
public String[] getNamedCurve() {
return curveStr;
}
public static String[] getNamedCurveFromKey(Key key) {
if (key instanceof ECKey) {
NamedCurve nc = CurveDB.lookup(((ECKey)key).getParams());
return (nc == null ? EMPTYLIST : nc.getNameAndAliases());
} else if (key instanceof XECKey) {
String[] s = {
((NamedParameterSpec)((XECKey)key).getParams()).getName()
};
return s;
} else {
return EMPTYLIST;
}
}
public String toString() {
StringBuilder s = new StringBuilder();
s.append("Cert: ");
if (cert != null) {
s.append(cert.toString());
s.append("\nSigAlgo: ");
s.append(cert.getSigAlgName());
} else {
s.append("None");
}
s.append("\nAlgParams: ");
if (getAlgParams() != null) {
getAlgParams().toString();
} else {
s.append("None");
}
s.append("\nNamedCurves: ");
for (String c : getNamedCurve()) {
s.append(c + " ");
}
s.append("\nVariant: " + getVariant());
return s.toString();
}
/**
* Returns the Validator variant.
*/
String getVariant();
/**
* Returns an extended message used in exceptions. See
* DisabledAlgorithmConstraints for usage.
*/
String extendedExceptionMsg();
}

View File

@ -27,12 +27,18 @@ package sun.security.util;
import sun.security.validator.Validator;
import java.security.CryptoPrimitive;
import java.security.AlgorithmParameters;
import java.security.CryptoPrimitive;
import java.security.Key;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECKey;
import java.security.interfaces.XECKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.NamedParameterSpec;
import java.security.spec.PSSParameterSpec;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@ -79,9 +85,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
private static final String PROPERTY_DISABLED_EC_CURVES =
"jdk.disabled.namedCurves";
private static class CertPathHolder {
static final DisabledAlgorithmConstraints CONSTRAINTS =
new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS);
}
private static class JarHolder {
static final DisabledAlgorithmConstraints CONSTRAINTS =
new DisabledAlgorithmConstraints(PROPERTY_JAR_DISABLED_ALGS);
}
private final List<String> disabledAlgorithms;
private final Constraints algorithmConstraints;
public static DisabledAlgorithmConstraints certPathConstraints() {
return CertPathHolder.CONSTRAINTS;
}
public static DisabledAlgorithmConstraints jarConstraints() {
return JarHolder.CONSTRAINTS;
}
/**
* Initialize algorithm constraints with the specified security property.
*
@ -122,7 +146,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
disabledAlgorithms.addAll(ecindex,
getAlgorithms(PROPERTY_DISABLED_EC_CURVES));
}
algorithmConstraints = new Constraints(disabledAlgorithms);
algorithmConstraints = new Constraints(propertyName, disabledAlgorithms);
}
/*
@ -172,32 +196,54 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return checkConstraints(primitives, algorithm, key, parameters);
}
public final void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
permits(cp.getAlgorithm(), cp);
public final void permits(String algorithm, AlgorithmParameters ap,
ConstraintsParameters cp) throws CertPathValidatorException {
permits(algorithm, cp);
if (ap != null) {
permits(ap, cp);
}
}
public final void permits(String algorithm, Key key,
AlgorithmParameters params, String variant)
private void permits(AlgorithmParameters ap, ConstraintsParameters cp)
throws CertPathValidatorException {
permits(algorithm, new ConstraintsParameters(algorithm, params, key,
(variant == null) ? Validator.VAR_GENERIC : variant));
switch (ap.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
case "RSASSA-PSS":
permitsPSSParams(ap, cp);
break;
default:
// unknown algorithm, just ignore
}
}
/*
* Check if a x509Certificate object is permitted. Check if all
* algorithms are allowed, certificate constraints, and the
* public key against key constraints.
*
* Uses new style permit() which throws exceptions.
*/
private void permitsPSSParams(AlgorithmParameters ap,
ConstraintsParameters cp) throws CertPathValidatorException {
try {
PSSParameterSpec pssParams =
ap.getParameterSpec(PSSParameterSpec.class);
String digestAlg = pssParams.getDigestAlgorithm();
permits(digestAlg, cp);
AlgorithmParameterSpec mgfParams = pssParams.getMGFParameters();
if (mgfParams instanceof MGF1ParameterSpec) {
String mgfDigestAlg =
((MGF1ParameterSpec)mgfParams).getDigestAlgorithm();
if (!mgfDigestAlg.equalsIgnoreCase(digestAlg)) {
permits(mgfDigestAlg, cp);
}
}
} catch (InvalidParameterSpecException ipse) {
// ignore
}
}
public final void permits(String algorithm, ConstraintsParameters cp)
throws CertPathValidatorException {
// Check if named curves in the ConstraintParameters are disabled.
if (cp.getNamedCurve() != null) {
for (String curve : cp.getNamedCurve()) {
// Check if named curves in the key are disabled.
for (Key key : cp.getKeys()) {
for (String curve : getNamedCurveFromKey(key)) {
if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed on disabled " +
@ -210,16 +256,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
algorithmConstraints.permits(algorithm, cp);
}
// Check if a string is contained inside the property
public boolean checkProperty(String param) {
param = param.toLowerCase(Locale.ENGLISH);
for (String block : disabledAlgorithms) {
if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
return true;
private static List<String> getNamedCurveFromKey(Key key) {
if (key instanceof ECKey) {
NamedCurve nc = CurveDB.lookup(((ECKey)key).getParams());
return (nc == null ? List.of()
: Arrays.asList(nc.getNameAndAliases()));
} else if (key instanceof XECKey) {
return List.of(
((NamedParameterSpec)((XECKey)key).getParams()).getName());
} else {
return List.of();
}
}
return false;
}
// Check algorithm constraints with key and algorithm
private boolean checkConstraints(Set<CryptoPrimitive> primitives,
@ -246,8 +294,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return false;
}
// If this is an elliptic curve, check disabled the named curve.
for (String curve : ConstraintsParameters.getNamedCurveFromKey(key)) {
// If this is an elliptic curve, check if it is disabled
for (String curve : getNamedCurveFromKey(key)) {
if (!permits(primitives, curve, null)) {
return false;
}
@ -284,7 +332,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
"denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
}
public Constraints(List<String> constraintArray) {
public Constraints(String propertyName, List<String> constraintArray) {
for (String constraintEntry : constraintArray) {
if (constraintEntry == null || constraintEntry.isEmpty()) {
continue;
@ -399,7 +447,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
}
}
// Get applicable constraints based off the signature algorithm
// Get applicable constraints based off the algorithm
private List<Constraint> getConstraints(String algorithm) {
return constraintsMap.get(algorithm.toUpperCase(Locale.ENGLISH));
}
@ -443,13 +491,12 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return true;
}
// Check if constraints permit this cert.
public void permits(String algorithm, ConstraintsParameters cp)
throws CertPathValidatorException {
X509Certificate cert = cp.getCertificate();
if (debug != null) {
debug.println("Constraints.permits(): " + cp.toString());
debug.println("Constraints.permits(): " + algorithm + ", "
+ cp.toString());
}
// Get all signature algorithms to check for constraints
@ -459,13 +506,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
algorithms.add(algorithm);
}
// Attempt to add the public key algorithm if cert provided
if (cert != null) {
algorithms.add(cert.getPublicKey().getAlgorithm());
}
if (cp.getKey() != null) {
algorithms.add(cp.getKey().getAlgorithm());
for (Key key : cp.getKeys()) {
algorithms.add(key.getAlgorithm());
}
// Check all applicable constraints
for (String alg : algorithms) {
List<Constraint> list = getConstraints(alg);
@ -556,7 +600,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* {@code next()} with the same {@code ConstraintsParameters}
* parameter passed if multiple constraints need to be checked.
*
* @param cp CertConstraintParameter containing certificate info
* @param cp ConstraintsParameter containing certificate info
* @throws CertPathValidatorException if constraint disallows.
*
*/
@ -605,14 +649,6 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
boolean next(Key key) {
return nextConstraint != null && nextConstraint.permits(key);
}
String extendedMsg(ConstraintsParameters cp) {
return (cp.getCertificate() == null ? "." :
" used with certificate: " +
cp.getCertificate().getSubjectX500Principal() +
(cp.getVariant() != Validator.VAR_GENERIC ?
". Usage was " + cp.getVariant() : "."));
}
}
/*
@ -636,14 +672,15 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
debug.println("jdkCAConstraints.permits(): " + algorithm);
}
// Check chain has a trust anchor in cacerts
if (cp.isTrustedMatch()) {
// Check if any certs chain back to at least one trust anchor in
// cacerts
if (cp.anchorIsJdkCA()) {
if (next(cp)) {
return;
}
throw new CertPathValidatorException(
"Algorithm constraints check failed on certificate " +
"anchor limits. " + algorithm + extendedMsg(cp),
"anchor limits. " + algorithm + cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
@ -708,15 +745,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
Date currentDate;
String errmsg;
if (cp.getJARTimestamp() != null) {
currentDate = cp.getJARTimestamp().getTimestamp();
errmsg = "JAR Timestamp date: ";
} else if (cp.getPKIXParamDate() != null) {
currentDate = cp.getPKIXParamDate();
errmsg = "PKIXParameter date: ";
if (cp.getDate() != null) {
currentDate = cp.getDate();
} else {
currentDate = new Date();
errmsg = "Current date: ";
}
if (!denyAfterDate.after(currentDate)) {
@ -726,8 +758,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
throw new CertPathValidatorException(
"denyAfter constraint check failed: " + algorithm +
" used with Constraint date: " +
dateFormat.format(denyAfterDate) + "; " + errmsg +
dateFormat.format(currentDate) + extendedMsg(cp),
dateFormat.format(denyAfterDate) + "; params date: " +
dateFormat.format(currentDate) + cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
@ -764,19 +796,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
@Override
public void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
String variant = cp.getVariant();
for (String usage : usages) {
String v = null;
if (usage.compareToIgnoreCase("TLSServer") == 0) {
v = Validator.VAR_TLS_SERVER;
} else if (usage.compareToIgnoreCase("TLSClient") == 0) {
v = Validator.VAR_TLS_CLIENT;
} else if (usage.compareToIgnoreCase("SignedJAR") == 0) {
v = Validator.VAR_PLUGIN_CODE_SIGNING;
boolean match = false;
switch (usage.toLowerCase()) {
case "tlsserver":
match = variant.equals(Validator.VAR_TLS_SERVER);
break;
case "tlsclient":
match = variant.equals(Validator.VAR_TLS_CLIENT);
break;
case "signedjar":
match =
variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING) ||
variant.equals(Validator.VAR_CODE_SIGNING) ||
variant.equals(Validator.VAR_TSA_SERVER);
break;
}
if (debug != null) {
debug.println("Checking if usage constraint \"" + v +
debug.println("Checking if usage constraint \"" + usage +
"\" matches \"" + cp.getVariant() + "\"");
if (Debug.isVerbose()) {
// Because usage checking can come from many places
@ -784,13 +824,13 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
(new Exception()).printStackTrace(debug.getPrintStream());
}
}
if (cp.getVariant().compareTo(v) == 0) {
if (match) {
if (next(cp)) {
return;
}
throw new CertPathValidatorException("Usage constraint " +
usage + " check failed: " + algorithm +
extendedMsg(cp),
cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
@ -843,33 +883,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
}
/*
* If we are passed a certificate, extract the public key and use it.
*
* Check if each constraint fails and check if there is a linked
* constraint Any permitted constraint will exit the linked list
* to allow the operation.
* For each key, check if each constraint fails and check if there is
* a linked constraint. Any permitted constraint will exit the linked
* list to allow the operation.
*/
@Override
public void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
Key key = null;
if (cp.getKey() != null) {
key = cp.getKey();
} else if (cp.getCertificate() != null) {
key = cp.getCertificate().getPublicKey();
}
if (key != null && !permitsImpl(key)) {
for (Key key : cp.getKeys()) {
if (!permitsImpl(key)) {
if (nextConstraint != null) {
nextConstraint.permits(cp);
return;
continue;
}
throw new CertPathValidatorException(
"Algorithm constraints check failed on keysize limits. " +
algorithm + " " + KeyUtil.getKeySize(key) + "bit key" +
extendedMsg(cp),
"Algorithm constraints check failed on keysize limits: " +
algorithm + " " + KeyUtil.getKeySize(key) + " bit key" +
cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
}
// Check if key constraint disable the specified key
@ -944,7 +978,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
throws CertPathValidatorException {
throw new CertPathValidatorException(
"Algorithm constraints check failed on disabled " +
"algorithm: " + algorithm + extendedMsg(cp),
"algorithm: " + algorithm + cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) 2020, 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 sun.security.util;
import java.security.CodeSigner;
import java.security.Key;
import java.security.Timestamp;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import sun.security.util.AnchorCertificates;
import sun.security.util.ConstraintsParameters;
import sun.security.validator.Validator;
/**
* This class contains parameters for checking signed JARs against
* constraints specified in the jdk.jar.disabledAlgorithms security
* property.
*/
public class JarConstraintsParameters implements ConstraintsParameters {
// true if chain is anchored by a JDK root CA
private boolean anchorIsJdkCA;
private boolean anchorIsJdkCASet;
// The timestamp of the signed JAR file, if timestamped
private Date timestamp;
// The keys of the signers
private final Set<Key> keys;
// The certs in the signers' chains that are issued by the trust anchor
private final Set<X509Certificate> certsIssuedByAnchor;
// The extended exception message
private String message;
/**
* Create a JarConstraintsParameters.
*
* @param signers the CodeSigners that signed the JAR
*/
public JarConstraintsParameters(CodeSigner[] signers) {
this.keys = new HashSet<>();
this.certsIssuedByAnchor = new HashSet<>();
Date latestTimestamp = null;
boolean skipTimestamp = false;
// Iterate over the signers and extract the keys, the latest
// timestamp, and the last certificate of each chain which can be
// used for checking if the signer's certificate chains back to a
// JDK root CA
for (CodeSigner signer : signers) {
init(signer.getSignerCertPath());
Timestamp timestamp = signer.getTimestamp();
if (timestamp == null) {
// this means one of the signers doesn't have a timestamp
// and the JAR should be treated as if it isn't timestamped
latestTimestamp = null;
skipTimestamp = true;
} else {
// add the key and last cert of TSA too
init(timestamp.getSignerCertPath());
if (!skipTimestamp) {
Date timestampDate = timestamp.getTimestamp();
if (latestTimestamp == null) {
latestTimestamp = timestampDate;
} else {
if (latestTimestamp.before(timestampDate)) {
latestTimestamp = timestampDate;
}
}
}
}
}
this.timestamp = latestTimestamp;
}
// extract last certificate and key from chain
private void init(CertPath cp) {
@SuppressWarnings("unchecked")
List<X509Certificate> chain =
(List<X509Certificate>)cp.getCertificates();
if (!chain.isEmpty()) {
this.certsIssuedByAnchor.add(chain.get(chain.size() - 1));
this.keys.add(chain.get(0).getPublicKey());
}
}
@Override
public String getVariant() {
return Validator.VAR_GENERIC;
}
/**
* Since loading the cacerts keystore can be an expensive operation,
* this is only performed if this method is called during a "jdkCA"
* constraints check of a disabled algorithm, and the result is cached.
*
* @return true if at least one of the certificates are issued by a
* JDK root CA
*/
@Override
public boolean anchorIsJdkCA() {
if (anchorIsJdkCASet) {
return anchorIsJdkCA;
}
for (X509Certificate cert : certsIssuedByAnchor) {
if (AnchorCertificates.issuerOf(cert)) {
anchorIsJdkCA = true;
break;
}
}
anchorIsJdkCASet = true;
return anchorIsJdkCA;
}
@Override
public Date getDate() {
return timestamp;
}
@Override
public Set<Key> getKeys() {
return keys;
}
/**
* Sets the extended error message. Note: this should be used
* carefully as it is specific to the attribute/entry/file being checked.
*
* @param file the name of the signature related file being verified
* @param target the attribute containing the algorithm that is being
* checked
*/
public void setExtendedExceptionMsg(String file, String target) {
message = " used" + (target != null ? " with " + target : "") +
" in " + file + " file.";
}
@Override
public String extendedExceptionMsg() {
return message;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[\n");
sb.append("\n Variant: ").append(getVariant());
sb.append("\n Certs Issued by Anchor:");
for (X509Certificate cert : certsIssuedByAnchor) {
sb.append("\n Cert Issuer: ")
.append(cert.getIssuerX500Principal());
sb.append("\n Cert Subject: ")
.append(cert.getSubjectX500Principal());
}
for (Key key : keys) {
sb.append("\n Key: ").append(key.getAlgorithm());
}
if (timestamp != null) {
sb.append("\n Timestamp: ").append(timestamp);
}
sb.append("\n]");
return sb.toString();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, 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
@ -27,13 +27,12 @@ package sun.security.util;
import java.security.*;
import java.io.*;
import java.security.CodeSigner;
import java.util.*;
import java.util.jar.*;
import java.util.Base64;
import sun.security.jca.Providers;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.util.JarConstraintsParameters;
/**
* This class is used to verify each entry in a jar file with its
@ -202,12 +201,29 @@ public class ManifestEntryVerifier {
throw new SecurityException("digest missing for " + name);
}
if (signers != null)
if (signers != null) {
return signers;
}
JarConstraintsParameters params =
getParams(verifiedSigners, sigFileSigners);
for (int i=0; i < digests.size(); i++) {
MessageDigest digest = digests.get(i);
if (params != null) {
try {
params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME,
name + " entry");
DisabledAlgorithmConstraints.jarConstraints()
.permits(digest.getAlgorithm(), params);
} catch (GeneralSecurityException e) {
if (debug != null) {
debug.println("Digest algorithm is restricted: " + e);
}
return null;
}
}
byte [] manHash = manifestHashes.get(i);
byte [] theHash = digest.digest();
@ -232,6 +248,38 @@ public class ManifestEntryVerifier {
return signers;
}
/**
* Get constraints parameters for JAR. The constraints should be
* checked against all code signers. Returns the parameters,
* or null if the signers for this entry have already been checked.
*/
private JarConstraintsParameters getParams(
Map<String, CodeSigner[]> verifiedSigners,
Map<String, CodeSigner[]> sigFileSigners) {
// verifiedSigners is usually preloaded with the Manifest's signers.
// If verifiedSigners contains the Manifest, then it will have all of
// the signers of the JAR. But if it doesn't then we need to fallback
// and check verifiedSigners to see if the signers of this entry have
// been checked already.
if (verifiedSigners.containsKey(JarFile.MANIFEST_NAME)) {
if (verifiedSigners.size() > 1) {
// this means we already checked it previously
return null;
} else {
return new JarConstraintsParameters(
verifiedSigners.get(JarFile.MANIFEST_NAME));
}
} else {
CodeSigner[] signers = sigFileSigners.get(name);
if (verifiedSigners.containsValue(signers)) {
return null;
} else {
return new JarConstraintsParameters(signers);
}
}
}
// for the toHex function
private static final char[] hexc =
{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};

View File

@ -32,7 +32,6 @@ import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.Timestamp;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
@ -45,6 +44,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarException;
import java.util.jar.JarFile;
@ -59,16 +59,6 @@ public class SignatureFileVerifier {
/* Are we debugging ? */
private static final Debug debug = Debug.getInstance("jar");
/**
* Holder class to delay initialization of DisabledAlgorithmConstraints
* until needed.
*/
private static class ConfigurationHolder {
static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
}
private ArrayList<CodeSigner[]> signerCache;
private static final String ATTR_DIGEST =
@ -97,13 +87,13 @@ public class SignatureFileVerifier {
/* for generating certpath objects */
private CertificateFactory certificateFactory = null;
/** Algorithms that have been checked if they are weak. */
private Map<String, Boolean> permittedAlgs= new HashMap<>();
/** TSA timestamp of signed jar. The newest timestamp is used. If there
* was no TSA timestamp used when signed, current time is used ("null").
/** Algorithms that have been previously checked against disabled
* constraints.
*/
private Timestamp timestamp = null;
private Map<String, Boolean> permittedAlgs = new HashMap<>();
/** ConstraintsParameters for checking disabled algorithms */
private JarConstraintsParameters params;
/**
* Create the named SignatureFileVerifier.
@ -297,32 +287,23 @@ public class SignatureFileVerifier {
name);
}
CodeSigner[] newSigners = getSigners(infos, block);
// make sure we have something to do all this work for...
if (newSigners == null)
if (newSigners == null) {
return;
}
/*
* Look for the latest timestamp in the signature block. If an entry
* has no timestamp, use current time (aka null).
*/
for (CodeSigner s: newSigners) {
if (debug != null) {
debug.println("Gathering timestamp for: " + s.toString());
}
if (s.getTimestamp() == null) {
timestamp = null;
break;
} else if (timestamp == null) {
timestamp = s.getTimestamp();
} else {
if (timestamp.getTimestamp().before(
s.getTimestamp().getTimestamp())) {
timestamp = s.getTimestamp();
}
}
// check if any of the algorithms used to verify the SignerInfos
// are disabled
params = new JarConstraintsParameters(newSigners);
Set<String> notDisabledAlgorithms =
SignerInfo.verifyAlgorithms(infos, params, name + " PKCS7");
// add the SignerInfo algorithms that are ok to the permittedAlgs map
// so they are not checked again
for (String algorithm : notDisabledAlgorithms) {
permittedAlgs.put(algorithm, Boolean.TRUE);
}
Iterator<Map.Entry<String,Attributes>> entries =
@ -373,13 +354,14 @@ public class SignatureFileVerifier {
* store the result. If the algorithm is in the map use that result.
* False is returned for weak algorithm, true for good algorithms.
*/
boolean permittedCheck(String key, String algorithm) {
private boolean permittedCheck(String key, String algorithm) {
Boolean permitted = permittedAlgs.get(algorithm);
if (permitted == null) {
try {
ConfigurationHolder.JAR_DISABLED_CHECK.permits(algorithm,
new ConstraintsParameters(timestamp));
} catch(GeneralSecurityException e) {
params.setExtendedExceptionMsg(name + ".SF", key + " attribute");
DisabledAlgorithmConstraints
.jarConstraints().permits(algorithm, params);
} catch (GeneralSecurityException e) {
permittedAlgs.put(algorithm, Boolean.FALSE);
permittedAlgs.put(key.toUpperCase(), Boolean.FALSE);
if (debug != null) {

View File

@ -224,7 +224,7 @@ public final class PKIXValidator extends Validator {
// add new algorithm constraints checker
if (constraints != null) {
pkixParameters.addCertPathChecker(
new AlgorithmChecker(constraints, null, variant));
new AlgorithmChecker(constraints, variant));
}
// attach it to the PKIXBuilderParameters.

View File

@ -167,7 +167,7 @@ public final class SimpleValidator extends Validator {
AlgorithmChecker appAlgChecker = null;
if (constraints != null) {
appAlgChecker = new AlgorithmChecker(anchor, constraints, null,
null, variant);
variant);
}
// verify top down, starting at the certificate issued by

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, 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
@ -88,6 +88,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
@SuppressWarnings("serial") // Not statically typed as Serializable
protected DerValue params;
private transient byte[] encodedParams;
/**
* Constructs an algorithm ID which will be initialized
@ -116,6 +117,18 @@ public class AlgorithmId implements Serializable, DerEncoder {
algid = oid;
algParams = algparams;
constructedFromDer = false;
if (algParams != null) {
try {
encodedParams = algParams.getEncoded();
} catch (IOException ioe) {
// It should be safe to ignore this.
// This exception can occur if AlgorithmParameters was not
// initialized (which should not occur), or if it was
// initialized with bogus parameters, which should have
// been detected when init was called.
assert false;
}
}
}
private AlgorithmId(ObjectIdentifier oid, DerValue params)
@ -123,6 +136,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
this.algid = oid;
this.params = params;
if (this.params != null) {
encodedParams = params.toByteArray();
decodeParams();
}
}
@ -141,7 +155,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
}
// Decode (parse) the parameters
algParams.init(params.toByteArray());
algParams.init(encodedParams.clone());
}
/**
@ -160,6 +174,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
*
* @exception IOException on encoding error.
*/
@Override
public void derEncode (OutputStream out) throws IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream();
@ -167,8 +182,8 @@ public class AlgorithmId implements Serializable, DerEncoder {
bytes.putOID(algid);
// Setup params from algParams since no DER encoding is given
if (constructedFromDer == false) {
if (algParams != null) {
params = new DerValue(algParams.getEncoded());
if (encodedParams != null) {
params = new DerValue(encodedParams);
} else {
params = null;
}
@ -256,7 +271,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
if (params != null) {
try {
AlgorithmId paramsId =
AlgorithmId.parse(new DerValue(params.toByteArray()));
AlgorithmId.parse(new DerValue(encodedParams));
String paramsName = paramsId.getName();
return makeSigAlg(paramsName, "EC");
} catch (IOException e) {
@ -284,6 +299,10 @@ public class AlgorithmId implements Serializable, DerEncoder {
* Returns the DER encoded parameter, which can then be
* used to initialize java.security.AlgorithmParameters.
*
* Note that this* method should always return a new array as it is called
* directly by the JDK implementation of X509Certificate.getSigAlgParams()
* and X509CRL.getSigAlgParams().
*
* Note: for ecdsa-with-SHA2 plus hash algorithm (Ex: SHA-256), this method
* returns null because {@link #getName()} has already returned the "full"
* signature algorithm (Ex: SHA256withECDSA).
@ -291,10 +310,10 @@ public class AlgorithmId implements Serializable, DerEncoder {
* @return DER encoded parameters, or null not present.
*/
public byte[] getEncodedParams() throws IOException {
return (params == null ||
return (encodedParams == null ||
algid.toString().equals(KnownOIDs.SpecifiedSHA2withECDSA.value()))
? null
: params.toByteArray();
: encodedParams.clone();
}
/**
@ -302,8 +321,8 @@ public class AlgorithmId implements Serializable, DerEncoder {
* with the same parameters.
*/
public boolean equals(AlgorithmId other) {
boolean paramsEqual = Objects.equals(other.params, params);
return (algid.equals((Object)other.algid) && paramsEqual);
return algid.equals((Object)other.algid) &&
Arrays.equals(encodedParams, other.encodedParams);
}
/**
@ -313,6 +332,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
*
* @param other preferably an AlgorithmId, else an ObjectIdentifier
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
@ -339,11 +359,11 @@ public class AlgorithmId implements Serializable, DerEncoder {
*
* @return a hashcode for this AlgorithmId.
*/
@Override
public int hashCode() {
StringBuilder sbuf = new StringBuilder();
sbuf.append(algid.toString());
sbuf.append(paramsToString());
return sbuf.toString().hashCode();
int hashCode = algid.hashCode();
hashCode = 31 * hashCode + Arrays.hashCode(encodedParams);
return hashCode;
}
/**
@ -351,10 +371,10 @@ public class AlgorithmId implements Serializable, DerEncoder {
* This may be redefined by subclasses which parse those parameters.
*/
protected String paramsToString() {
if (params == null) {
if (encodedParams == null) {
return "";
} else if (algParams != null) {
return algParams.toString();
return ", " + algParams.toString();
} else {
return ", params unparsed";
}
@ -363,6 +383,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
/**
* Returns a string describing the algorithm and its parameters.
*/
@Override
public String toString() {
return getName() + paramsToString();
}

View File

@ -1320,3 +1320,26 @@ jdk.io.permissionsUseCanonicalPath=false
# System value prevails. The default value of the property is "false".
#
#jdk.security.allowNonCaAnchor=true
#
# JNDI Object Factories Filter
#
# This filter is used by the JNDI runtime to control the set of object factory classes
# which will be allowed to instantiate objects from object references returned by
# naming/directory systems. The factory class named by the reference instance will be
# matched against this filter. The filter property supports pattern-based filter syntax
# with the same format as jdk.serialFilter.
#
# Each pattern is matched against the factory class name to allow or disallow it's
# instantiation. The access to a factory class is allowed unless the filter returns
# REJECTED.
#
# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes
# the security property value defined here. The default value of the property is "*".
#
# The default pattern value allows any object factory class specified by the reference
# instance to recreate the referenced object.
#jdk.jndi.object.factoriesFilter=*

View File

@ -219,9 +219,9 @@ final class ProcessImpl extends Process {
private static final char ESCAPE_VERIFICATION[][] = {
// We guarantee the only command file execution for implicit [cmd.exe] run.
// http://technet.microsoft.com/en-us/library/bb490954.aspx
{' ', '\t', '<', '>', '&', '|', '^'},
{' ', '\t', '<', '>'},
{' ', '\t', '<', '>'},
{' ', '\t', '\"', '<', '>', '&', '|', '^'},
{' ', '\t', '\"', '<', '>'},
{' ', '\t', '\"', '<', '>'},
{' ', '\t'}
};
@ -281,18 +281,27 @@ final class ProcessImpl extends Process {
}
/**
* Return the argument without quotes (1st and last) if present, else the arg.
* Return the argument without quotes (1st and last) if properly quoted, else the arg.
* A properly quoted string has first and last characters as quote and
* the last quote is not escaped.
* @param str a string
* @return the string without 1st and last quotes
* @return the string without quotes
*/
private static String unQuote(String str) {
int len = str.length();
return (len >= 2 && str.charAt(0) == DOUBLEQUOTE && str.charAt(len - 1) == DOUBLEQUOTE)
? str.substring(1, len - 1)
: str;
if (!str.startsWith("\"") || !str.endsWith("\"") || str.length() < 2)
return str; // no beginning or ending quote, or too short not quoted
if (str.endsWith("\\\"")) {
return str; // not properly quoted, treat as unquoted
}
// Strip leading and trailing quotes
return str.substring(1, str.length() - 1);
}
private static boolean needsEscaping(int verificationType, String arg) {
if (arg.isEmpty())
return true; // Empty string is to be quoted
// Switch off MS heuristic for internal ["].
// Please, use the explicit [cmd.exe] call
// if you need the internal ["].

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2020, 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
@ -233,6 +233,9 @@ final class Obj {
String[] codebases = getCodebases(attrs.get(JAVA_ATTRIBUTES[CODEBASE]));
try {
if ((attr = attrs.get(JAVA_ATTRIBUTES[SERIALIZED_DATA])) != null) {
if (!VersionHelper.isSerialDataAllowed()) {
throw new NamingException("Object deserialization is not allowed");
}
ClassLoader cl = helper.getURLClassLoader(codebases);
return deserializeObject((byte[])attr.get(), cl);
} else if ((attr = attrs.get(JAVA_ATTRIBUTES[REMOTE_LOC])) != null) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2020, 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
@ -43,21 +43,52 @@ public final class VersionHelper {
*/
private static final boolean trustURLCodebase;
/**
* Determines whether objects may be deserialized from the content of
* 'javaSerializedData' attribute.
*/
private static final boolean trustSerialData;
static {
// System property to control whether classes may be loaded from an
// arbitrary URL code base
PrivilegedAction<String> act =
() -> System.getProperty("com.sun.jndi.ldap.object.trustURLCodebase", "false");
String trust = AccessController.doPrivileged(act);
String trust = getPrivilegedProperty(
"com.sun.jndi.ldap.object.trustURLCodebase", "false");
trustURLCodebase = "true".equalsIgnoreCase(trust);
// System property to control whether classes is allowed to be loaded from
// 'javaSerializedData' attribute
String trustSerialDataSp = getPrivilegedProperty(
"com.sun.jndi.ldap.object.trustSerialData", "true");
trustSerialData = "true".equalsIgnoreCase(trustSerialDataSp);
}
private VersionHelper() { }
private static String getPrivilegedProperty(String propertyName, String defaultVal) {
PrivilegedAction<String> action = () -> System.getProperty(propertyName, defaultVal);
if (System.getSecurityManager() == null) {
return action.run();
} else {
return AccessController.doPrivileged(action);
}
}
private VersionHelper() {
}
static VersionHelper getVersionHelper() {
return helper;
}
/**
* Returns true if deserialization of objects from 'javaSerializedData'
* LDAP attribute is allowed.
*
* @return true if deserialization is allowed; false - otherwise
*/
public static boolean isSerialDataAllowed() {
return trustSerialData;
}
ClassLoader getURLClassLoader(String[] url) throws MalformedURLException {
ClassLoader parent = getContextClassLoader();
/*

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2020, 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.naming.internal;
import sun.security.util.SecurityProperties;
import javax.naming.Reference;
import java.io.ObjectInputFilter;
import java.io.ObjectInputFilter.FilterInfo;
import java.io.ObjectInputFilter.Status;
/**
* This class implements the filter that validates object factories classes instantiated
* during {@link Reference} lookups.
* There is one system-wide filter instance per VM that can be set via
* the {@code "jdk.jndi.object.factoriesFilter"} system property value, or via
* setting the property in the security properties file. The system property value supersedes
* the security property value. If none of the properties are specified the default
* "*" value is used.
* The filter is implemented as {@link ObjectInputFilter} with capabilities limited to the
* validation of a factory's class types only ({@linkplain FilterInfo#serialClass()}).
* Array length, number of object references, depth, and stream size filtering capabilities are
* not supported by the filter.
*/
public final class ObjectFactoriesFilter {
/**
* Checks if serial filter configured with {@code "jdk.jndi.object.factoriesFilter"}
* system property value allows instantiation of the specified objects factory class.
* If the filter result is not {@linkplain Status#REJECTED REJECTED}, the filter will
* allow the instantiation of objects factory class.
*
* @param factoryClass objects factory class
* @return true - if the factory is allowed to be instantiated; false - otherwise
*/
public static boolean canInstantiateObjectsFactory(Class<?> factoryClass) {
return checkInput(() -> factoryClass);
}
private static boolean checkInput(FactoryInfo factoryInfo) {
Status result = GLOBAL.checkInput(factoryInfo);
return result != Status.REJECTED;
}
// FilterInfo to check if objects factory class is allowed by the system-wide
// filter. Array length, number of object references, depth, and stream size
// capabilities are ignored.
@FunctionalInterface
private interface FactoryInfo extends FilterInfo {
@Override
default long arrayLength() {
return -1;
}
@Override
default long depth() {
return 1;
}
@Override
default long references() {
return 0;
}
@Override
default long streamBytes() {
return 0;
}
}
// Prevent instantiation of the factories filter class
private ObjectFactoriesFilter() {
throw new InternalError("Not instantiable");
}
// System property name that contains the patterns to filter object factory names
private static final String FACTORIES_FILTER_PROPNAME = "jdk.jndi.object.factoriesFilter";
// Default system property value that allows the load of any object factory classes
private static final String DEFAULT_SP_VALUE = "*";
// System wide object factories filter constructed from the system property
private static final ObjectInputFilter GLOBAL =
ObjectInputFilter.Config.createFilter(getFilterPropertyValue());
// Get security or system property value
private static String getFilterPropertyValue() {
String propVal = SecurityProperties.privilegedGetOverridable(FACTORIES_FILTER_PROPNAME);
return propVal != null ? propVal : DEFAULT_SP_VALUE;
}
}

View File

@ -96,6 +96,10 @@ public final class VersionHelper {
return loadClass(className, getContextClassLoader());
}
public Class<?> loadClassWithoutInit(String className) throws ClassNotFoundException {
return loadClass(className, false, getContextClassLoader());
}
/**
* @param className A non-null fully qualified class name.
* @param codebase A non-null, space-separated list of URL strings.
@ -118,10 +122,15 @@ public final class VersionHelper {
* This internal method is used with Thread Context Class Loader (TCCL),
* please don't expose this method as public.
*/
Class<?> loadClass(String className, boolean initialize, ClassLoader cl)
throws ClassNotFoundException {
Class<?> cls = Class.forName(className, initialize, cl);
return cls;
}
Class<?> loadClass(String className, ClassLoader cl)
throws ClassNotFoundException {
Class<?> cls = Class.forName(className, true, cl);
return cls;
return loadClass(className, true, cl);
}
/*

View File

@ -31,6 +31,8 @@ import java.security.PrivilegedAction;
import java.util.*;
import javax.naming.*;
import com.sun.naming.internal.ObjectFactoriesFilter;
import com.sun.naming.internal.VersionHelper;
import com.sun.naming.internal.ResourceManager;
import com.sun.naming.internal.FactoryEnumeration;
@ -147,7 +149,11 @@ public class NamingManager {
// Try to use current class loader
try {
clas = helper.loadClass(factoryName);
clas = helper.loadClassWithoutInit(factoryName);
// Validate factory's class with the objects factory serial filter
if (!ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) {
return null;
}
} catch (ClassNotFoundException e) {
// ignore and continue
// e.printStackTrace();
@ -160,6 +166,11 @@ public class NamingManager {
(codebase = ref.getFactoryClassLocation()) != null) {
try {
clas = helper.loadClass(factoryName, codebase);
// Validate factory's class with the objects factory serial filter
if (clas == null ||
!ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) {
return null;
}
} catch (ClassNotFoundException e) {
}
}

View File

@ -121,6 +121,7 @@ class Http2Connection {
static private final int MAX_CLIENT_STREAM_ID = Integer.MAX_VALUE; // 2147483647
static private final int MAX_SERVER_STREAM_ID = Integer.MAX_VALUE - 1; // 2147483646
static private final int BUFFER = 8; // added as an upper bound
/**
* Flag set when no more streams to be opened on this connection.
@ -1104,8 +1105,10 @@ class Http2Connection {
* and CONTINUATION frames from the list and return the List<Http2Frame>.
*/
private List<HeaderFrame> encodeHeaders(OutgoingHeaders<Stream<?>> frame) {
// max value of frame size is clamped by default frame size to avoid OOM
int bufferSize = Math.min(Math.max(getMaxSendFrameSize(), 1024), DEFAULT_FRAME_SIZE);
List<ByteBuffer> buffers = encodeHeadersImpl(
getMaxSendFrameSize(),
bufferSize,
frame.getAttachment().getRequestPseudoHeaders(),
frame.getUserHeaders(),
frame.getSystemHeaders());
@ -1128,9 +1131,9 @@ class Http2Connection {
// by the sendLock. / (see sendFrame())
// private final ByteBufferPool headerEncodingPool = new ByteBufferPool();
private ByteBuffer getHeaderBuffer(int maxFrameSize) {
ByteBuffer buf = ByteBuffer.allocate(maxFrameSize);
buf.limit(maxFrameSize);
private ByteBuffer getHeaderBuffer(int size) {
ByteBuffer buf = ByteBuffer.allocate(size);
buf.limit(size);
return buf;
}
@ -1145,8 +1148,8 @@ class Http2Connection {
* header field names MUST be converted to lowercase prior to their
* encoding in HTTP/2...
*/
private List<ByteBuffer> encodeHeadersImpl(int maxFrameSize, HttpHeaders... headers) {
ByteBuffer buffer = getHeaderBuffer(maxFrameSize);
private List<ByteBuffer> encodeHeadersImpl(int bufferSize, HttpHeaders... headers) {
ByteBuffer buffer = getHeaderBuffer(bufferSize);
List<ByteBuffer> buffers = new ArrayList<>();
for(HttpHeaders header : headers) {
for (Map.Entry<String, List<String>> e : header.map().entrySet()) {
@ -1157,7 +1160,7 @@ class Http2Connection {
while (!hpackOut.encode(buffer)) {
buffer.flip();
buffers.add(buffer);
buffer = getHeaderBuffer(maxFrameSize);
buffer = getHeaderBuffer(bufferSize);
}
}
}
@ -1167,6 +1170,7 @@ class Http2Connection {
return buffers;
}
private List<ByteBuffer> encodeHeaders(OutgoingHeaders<Stream<?>> oh, Stream<?> stream) {
oh.streamid(stream.streamid);
if (Log.headers()) {

View File

@ -115,6 +115,8 @@ public class MarkUnsafeAccessTest extends GraalCompilerTest {
testMappedByteBuffer(MappedByteBuffer::get);
}
// TODO Re-enable this test once JDK-8259360 got fixed.
/*
@Test
public void testCompiled() throws IOException {
Assume.assumeFalse("Crashes on AArch64 (GR-8351)", System.getProperty("os.arch").equalsIgnoreCase("aarch64"));
@ -136,6 +138,7 @@ public class MarkUnsafeAccessTest extends GraalCompilerTest {
}
});
}
*/
private static final int BLOCK_SIZE = 512;
private static final int BLOCK_COUNT = 16;

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2021, 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.
*
* 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.
*/
/*
* @test
* @bug 8259428
* @summary Verify X509Certificate.getSigAlgParams() returns new array each
* time it is called
* @modules java.base/sun.security.tools.keytool java.base/sun.security.x509
*/
import java.security.cert.X509Certificate;
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.X500Name;
public class GetSigAlgParams {
public static void main(String[] args) throws Exception {
CertAndKeyGen cakg = new CertAndKeyGen("RSASSA-PSS", "RSASSA-PSS");
cakg.generate(1024);
X509Certificate c = cakg.getSelfCertificate(new X500Name("CN=Me"), 100);
if (c.getSigAlgParams() == c.getSigAlgParams()) {
throw new Exception("Encoded params are the same byte array");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, 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
@ -48,7 +48,7 @@ import sun.security.util.DerValue;
public class PKCS8Test {
static final String FORMAT = "PKCS#8";
static final String EXPECTED_ALG_ID_CHRS = "DSA\n" +
static final String EXPECTED_ALG_ID_CHRS = "DSA, \n" +
"\tp: 02\n\tq: 03\n\tg: 04\n";
static final String ALGORITHM = "DSA";
@ -75,10 +75,10 @@ public class PKCS8Test {
PKCS8Key decodedKey = (PKCS8Key)PKCS8Key.parseKey(
new DerValue(encodedKey));
Assert.assertEquals(ALGORITHM, decodedKey.getAlgorithm());
Assert.assertEquals(FORMAT, decodedKey.getFormat());
Assert.assertEquals(EXPECTED_ALG_ID_CHRS,
decodedKey.getAlgorithmId().toString());
Assert.assertEquals(decodedKey.getAlgorithm(), ALGORITHM);
Assert.assertEquals(decodedKey.getFormat(), FORMAT);
Assert.assertEquals(decodedKey.getAlgorithmId().toString(),
EXPECTED_ALG_ID_CHRS);
byte[] encodedOutput = decodedKey.getEncoded();
Assert.assertTrue(Arrays.equals(encodedOutput, EXPECTED),

View File

@ -317,7 +317,7 @@ public class TimestampCheck {
sign("tsdisabled", "-digestalg", "MD5",
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
.shouldHaveExitValue(68)
.shouldContain("The timestamp is invalid. Without a valid timestamp")
.shouldContain("TSA certificate chain is invalid")
.shouldMatch("MD5.*-digestalg.*is disabled")
.shouldMatch("MD5.*-tsadigestalg.*is disabled")
.shouldMatch("MD5withRSA.*-sigalg.*is disabled");
@ -325,7 +325,6 @@ public class TimestampCheck {
signVerbose("tsdisabled", "unsigned.jar", "tsdisabled2.jar", "signer")
.shouldHaveExitValue(64)
.shouldContain("The timestamp is invalid. Without a valid timestamp")
.shouldContain("TSA certificate chain is invalid");
// Disabled timestamp is an error and jar treated unsigned
@ -637,7 +636,7 @@ public class TimestampCheck {
.shouldMatch("Timestamp signature algorithm: .*key.*(disabled)");
verify(file, "-J-Djava.security.debug=jar")
.shouldHaveExitValue(16)
.shouldMatch("SignatureException:.*disabled");
.shouldMatch("SignatureException:.*keysize");
// For 8171319: keytool should print out warnings when reading or
// generating cert/cert req using disabled algorithms.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2021, 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
@ -24,13 +24,17 @@
/*
* @test
* @author Gary Ellison
* @bug 4170635
* @bug 4170635 8258247
* @summary Verify equals()/hashCode() contract honored
* @modules java.base/sun.security.x509
* @modules java.base/sun.security.x509 java.base/sun.security.util
*/
import java.io.*;
import java.security.AlgorithmParameters;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PSSParameterSpec;
import sun.security.util.DerValue;
import sun.security.x509.*;
public class AlgorithmIdEqualsHashCode {
@ -41,7 +45,6 @@ public class AlgorithmIdEqualsHashCode {
AlgorithmId ai2 = AlgorithmId.get("DH");
AlgorithmId ai3 = AlgorithmId.get("DH");
// supposedly transitivity is broken
// System.out.println(ai1.equals(ai2));
// System.out.println(ai2.equals(ai3));
@ -57,5 +60,42 @@ public class AlgorithmIdEqualsHashCode {
else
throw new Exception("Failed equals()/hashCode() contract");
// check that AlgorithmIds with same name but different params
// are not equal
AlgorithmParameters algParams1 =
AlgorithmParameters.getInstance("RSASSA-PSS");
AlgorithmParameters algParams2 =
AlgorithmParameters.getInstance("RSASSA-PSS");
algParams1.init(new PSSParameterSpec("SHA-1", "MGF1",
MGF1ParameterSpec.SHA1, 20, PSSParameterSpec.TRAILER_FIELD_BC));
algParams2.init(new PSSParameterSpec("SHA-256", "MGF1",
MGF1ParameterSpec.SHA1, 20, PSSParameterSpec.TRAILER_FIELD_BC));
ai1 = new AlgorithmId(AlgorithmId.RSASSA_PSS_oid, algParams1);
ai2 = new AlgorithmId(AlgorithmId.RSASSA_PSS_oid, algParams2);
if (ai1.equals(ai2)) {
throw new Exception("Failed equals() contract");
} else {
System.out.println("PASSED equals() test");
}
// check that two AlgorithmIds created with the same parameters but
// one with DER encoded parameters and the other with
// AlgorithmParameters are equal
byte[] encoded = ai1.encode();
ai3 = AlgorithmId.parse(new DerValue(encoded));
if (!ai1.equals(ai3)) {
throw new Exception("Failed equals() contract");
} else {
System.out.println("PASSED equals() test");
}
// check that two AlgorithmIds created with different parameters but
// one with DER encoded parameters and the other with
// AlgorithmParameters are not equal
if (ai2.equals(ai3)) {
throw new Exception("Failed equals() contract");
} else {
System.out.println("PASSED equals() test");
}
}
}