mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8249906: Enhance opening JARs
Reviewed-by: weijun, rhalade, mschoene
This commit is contained in:
parent
17a741d6bc
commit
7232e3c704
24 changed files with 766 additions and 502 deletions
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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) {
|
protected void implSetDateAndTime(X509CRLSelector sel, Date date, long skew) {
|
||||||
sel.setDateAndTime(date, skew);
|
sel.setDateAndTime(date, skew);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean implIsJdkCA(TrustAnchor anchor) {
|
||||||
|
return anchor.isJdkCA();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 javax.security.auth.x500.X500Principal;
|
||||||
|
|
||||||
|
import sun.security.util.AnchorCertificates;
|
||||||
import sun.security.x509.NameConstraintsExtension;
|
import sun.security.x509.NameConstraintsExtension;
|
||||||
import sun.security.x509.X500Name;
|
import sun.security.x509.X500Name;
|
||||||
|
|
||||||
|
@ -68,6 +69,12 @@ public class TrustAnchor {
|
||||||
private final X509Certificate trustedCert;
|
private final X509Certificate trustedCert;
|
||||||
private byte[] ncBytes;
|
private byte[] ncBytes;
|
||||||
private NameConstraintsExtension nc;
|
private NameConstraintsExtension nc;
|
||||||
|
private boolean jdkCA;
|
||||||
|
private boolean hasJdkCABeenChecked;
|
||||||
|
|
||||||
|
static {
|
||||||
|
CertPathHelperImpl.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of {@code TrustAnchor} with the specified
|
* Creates an instance of {@code TrustAnchor} with the specified
|
||||||
|
@ -330,4 +337,18 @@ public class TrustAnchor {
|
||||||
sb.append(" Name Constraints: " + nc.toString() + "\n");
|
sb.append(" Name Constraints: " + nc.toString() + "\n");
|
||||||
return sb.toString();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.access.JavaUtilZipFileAccess;
|
import jdk.internal.access.JavaUtilZipFileAccess;
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
import sun.security.util.ManifestEntryVerifier;
|
import sun.security.util.ManifestEntryVerifier;
|
||||||
import sun.security.util.SignatureFileVerifier;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
|
|
|
@ -36,9 +36,11 @@ import java.security.cert.X509Certificate;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.spec.PSSParameterSpec;
|
import java.security.spec.PSSParameterSpec;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
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 java.util.Set;
|
||||||
|
|
||||||
import sun.security.provider.SHAKE256;
|
import sun.security.provider.SHAKE256;
|
||||||
|
@ -55,16 +57,8 @@ import sun.security.x509.KeyUsageExtension;
|
||||||
*/
|
*/
|
||||||
public class SignerInfo implements DerEncoder {
|
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 =
|
private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
|
||||||
new DisabledAlgorithmConstraints(
|
DisabledAlgorithmConstraints.jarConstraints();
|
||||||
DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
|
|
||||||
|
|
||||||
BigInteger version;
|
BigInteger version;
|
||||||
X500Name issuerName;
|
X500Name issuerName;
|
||||||
|
@ -79,6 +73,14 @@ public class SignerInfo implements DerEncoder {
|
||||||
PKCS9Attributes authenticatedAttributes;
|
PKCS9Attributes authenticatedAttributes;
|
||||||
PKCS9Attributes unauthenticatedAttributes;
|
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,
|
public SignerInfo(X500Name issuerName,
|
||||||
BigInteger serial,
|
BigInteger serial,
|
||||||
AlgorithmId digestAlgorithmId,
|
AlgorithmId digestAlgorithmId,
|
||||||
|
@ -329,20 +331,15 @@ public class SignerInfo implements DerEncoder {
|
||||||
throws NoSuchAlgorithmException, SignatureException {
|
throws NoSuchAlgorithmException, SignatureException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Timestamp timestamp = getTimestamp();
|
||||||
|
|
||||||
ContentInfo content = block.getContentInfo();
|
ContentInfo content = block.getContentInfo();
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
data = content.getContentBytes();
|
data = content.getContentBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
Timestamp timestamp = null;
|
String digestAlgName = digestAlgorithmId.getName();
|
||||||
try {
|
algorithms.put(digestAlgorithmId, "SignerInfo digestAlgorithm field");
|
||||||
timestamp = getTimestamp();
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstraintsParameters cparams =
|
|
||||||
new ConstraintsParameters(timestamp);
|
|
||||||
|
|
||||||
byte[] dataSigned;
|
byte[] dataSigned;
|
||||||
|
|
||||||
|
@ -368,19 +365,10 @@ public class SignerInfo implements DerEncoder {
|
||||||
if (messageDigest == null) // fail if there is no message digest
|
if (messageDigest == null) // fail if there is no message digest
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
String digestAlgname = digestAlgorithmId.getName();
|
|
||||||
|
|
||||||
// check that digest algorithm is not restricted
|
|
||||||
try {
|
|
||||||
JAR_DISABLED_CHECK.permits(digestAlgname, cparams);
|
|
||||||
} catch (CertPathValidatorException e) {
|
|
||||||
throw new SignatureException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] computedMessageDigest;
|
byte[] computedMessageDigest;
|
||||||
if (digestAlgname.equals("SHAKE256")
|
if (digestAlgName.equals("SHAKE256")
|
||||||
|| digestAlgname.equals("SHAKE256-LEN")) {
|
|| digestAlgName.equals("SHAKE256-LEN")) {
|
||||||
if (digestAlgname.equals("SHAKE256-LEN")) {
|
if (digestAlgName.equals("SHAKE256-LEN")) {
|
||||||
int v = new DerValue(digestAlgorithmId
|
int v = new DerValue(digestAlgorithmId
|
||||||
.getEncodedParams()).getInteger();
|
.getEncodedParams()).getInteger();
|
||||||
if (v != 512) {
|
if (v != 512) {
|
||||||
|
@ -392,15 +380,12 @@ public class SignerInfo implements DerEncoder {
|
||||||
md.update(data, 0, data.length);
|
md.update(data, 0, data.length);
|
||||||
computedMessageDigest = md.digest();
|
computedMessageDigest = md.digest();
|
||||||
} else {
|
} else {
|
||||||
MessageDigest md = MessageDigest.getInstance(digestAlgname);
|
MessageDigest md = MessageDigest.getInstance(digestAlgName);
|
||||||
computedMessageDigest = md.digest(data);
|
computedMessageDigest = md.digest(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageDigest.length != computedMessageDigest.length)
|
if (!MessageDigest.isEqual(messageDigest, computedMessageDigest)) {
|
||||||
return null;
|
return null;
|
||||||
for (int i = 0; i < messageDigest.length; i++) {
|
|
||||||
if (messageDigest[i] != computedMessageDigest[i])
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// message digest attribute matched
|
// message digest attribute matched
|
||||||
|
@ -414,16 +399,18 @@ public class SignerInfo implements DerEncoder {
|
||||||
|
|
||||||
// put together digest algorithm and encryption algorithm
|
// put together digest algorithm and encryption algorithm
|
||||||
// to form signing algorithm. See makeSigAlg for details.
|
// to form signing algorithm. See makeSigAlg for details.
|
||||||
String algname = makeSigAlg(
|
String sigAlgName = makeSigAlg(
|
||||||
digestAlgorithmId,
|
digestAlgorithmId,
|
||||||
digestEncryptionAlgorithmId,
|
digestEncryptionAlgorithmId,
|
||||||
authenticatedAttributes == null);
|
authenticatedAttributes == null);
|
||||||
|
|
||||||
// check that jar signature algorithm is not restricted
|
KnownOIDs oid = KnownOIDs.findMatch(sigAlgName);
|
||||||
try {
|
if (oid != null) {
|
||||||
JAR_DISABLED_CHECK.permits(algname, cparams);
|
AlgorithmId sigAlgId =
|
||||||
} catch (CertPathValidatorException e) {
|
new AlgorithmId(ObjectIdentifier.of(oid),
|
||||||
throw new SignatureException(e.getMessage(), e);
|
digestEncryptionAlgorithmId.getParameters());
|
||||||
|
algorithms.put(sigAlgId,
|
||||||
|
"SignerInfo digestEncryptionAlgorithm field");
|
||||||
}
|
}
|
||||||
|
|
||||||
X509Certificate cert = getCertificate(block);
|
X509Certificate cert = getCertificate(block);
|
||||||
|
@ -432,14 +419,6 @@ public class SignerInfo implements DerEncoder {
|
||||||
}
|
}
|
||||||
PublicKey key = cert.getPublicKey();
|
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()) {
|
if (cert.hasUnsupportedCriticalExtension()) {
|
||||||
throw new SignatureException("Certificate has unsupported "
|
throw new SignatureException("Certificate has unsupported "
|
||||||
+ "critical extension(s)");
|
+ "critical extension(s)");
|
||||||
|
@ -476,13 +455,13 @@ public class SignerInfo implements DerEncoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Signature sig = Signature.getInstance(algname);
|
Signature sig = Signature.getInstance(sigAlgName);
|
||||||
|
|
||||||
AlgorithmParameters ap =
|
AlgorithmParameters ap =
|
||||||
digestEncryptionAlgorithmId.getParameters();
|
digestEncryptionAlgorithmId.getParameters();
|
||||||
try {
|
try {
|
||||||
SignatureUtil.initVerifyWithParam(sig, key,
|
SignatureUtil.initVerifyWithParam(sig, key,
|
||||||
SignatureUtil.getParamSpec(algname, ap));
|
SignatureUtil.getParamSpec(sigAlgName, ap));
|
||||||
} catch (ProviderException | InvalidAlgorithmParameterException |
|
} catch (ProviderException | InvalidAlgorithmParameterException |
|
||||||
InvalidKeyException e) {
|
InvalidKeyException e) {
|
||||||
throw new SignatureException(e.getMessage(), e);
|
throw new SignatureException(e.getMessage(), e);
|
||||||
|
@ -492,9 +471,8 @@ public class SignerInfo implements DerEncoder {
|
||||||
if (sig.verify(encryptedDigest)) {
|
if (sig.verify(encryptedDigest)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException | CertificateException e) {
|
||||||
throw new SignatureException("IO error verifying signature:\n" +
|
throw new SignatureException("Error verifying signature", e);
|
||||||
e.getMessage());
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -654,6 +632,9 @@ public class SignerInfo implements DerEncoder {
|
||||||
// Extract the signer (the Timestamping Authority)
|
// Extract the signer (the Timestamping Authority)
|
||||||
// while verifying the content
|
// while verifying the content
|
||||||
SignerInfo[] tsa = tsToken.verify(encTsTokenInfo);
|
SignerInfo[] tsa = tsToken.verify(encTsTokenInfo);
|
||||||
|
if (tsa == null || tsa.length == 0) {
|
||||||
|
throw new SignatureException("Unable to verify timestamp");
|
||||||
|
}
|
||||||
// Expect only one signer
|
// Expect only one signer
|
||||||
ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(tsToken);
|
ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(tsToken);
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||||
|
@ -662,6 +643,7 @@ public class SignerInfo implements DerEncoder {
|
||||||
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
|
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
|
||||||
// Check that the signature timestamp applies to this signature
|
// Check that the signature timestamp applies to this signature
|
||||||
verifyTimestamp(tsTokenInfo);
|
verifyTimestamp(tsTokenInfo);
|
||||||
|
algorithms.putAll(tsa[0].algorithms);
|
||||||
// Create a timestamp object
|
// Create a timestamp object
|
||||||
timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain);
|
timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain);
|
||||||
return timestamp;
|
return timestamp;
|
||||||
|
@ -674,18 +656,13 @@ public class SignerInfo implements DerEncoder {
|
||||||
*/
|
*/
|
||||||
private void verifyTimestamp(TimestampToken token)
|
private void verifyTimestamp(TimestampToken token)
|
||||||
throws NoSuchAlgorithmException, SignatureException {
|
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 =
|
AlgorithmId digestAlgId = token.getHashAlgorithm();
|
||||||
MessageDigest.getInstance(digestAlgname);
|
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))) {
|
md.digest(encryptedDigest))) {
|
||||||
|
|
||||||
throw new SignatureException("Signature timestamp (#" +
|
throw new SignatureException("Signature timestamp (#" +
|
||||||
|
@ -726,4 +703,35 @@ public class SignerInfo implements DerEncoder {
|
||||||
}
|
}
|
||||||
return out;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.AlgorithmConstraints;
|
||||||
import java.security.CryptoPrimitive;
|
import java.security.CryptoPrimitive;
|
||||||
import java.security.Timestamp;
|
|
||||||
import java.security.cert.CertPathValidator;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -53,14 +51,13 @@ import java.security.interfaces.DSAParams;
|
||||||
import java.security.interfaces.DSAPublicKey;
|
import java.security.interfaces.DSAPublicKey;
|
||||||
import java.security.spec.DSAPublicKeySpec;
|
import java.security.spec.DSAPublicKeySpec;
|
||||||
|
|
||||||
import sun.security.util.AnchorCertificates;
|
|
||||||
import sun.security.util.ConstraintsParameters;
|
import sun.security.util.ConstraintsParameters;
|
||||||
import sun.security.util.Debug;
|
import sun.security.util.Debug;
|
||||||
import sun.security.util.DisabledAlgorithmConstraints;
|
import sun.security.util.DisabledAlgorithmConstraints;
|
||||||
import sun.security.validator.Validator;
|
import sun.security.validator.Validator;
|
||||||
|
import sun.security.x509.AlgorithmId;
|
||||||
import sun.security.x509.X509CertImpl;
|
import sun.security.x509.X509CertImpl;
|
||||||
import sun.security.x509.X509CRLImpl;
|
import sun.security.x509.X509CRLImpl;
|
||||||
import sun.security.x509.AlgorithmId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@code PKIXCertPathChecker} implementation to check whether a
|
* A {@code PKIXCertPathChecker} implementation to check whether a
|
||||||
|
@ -78,10 +75,10 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
|
||||||
|
|
||||||
private final AlgorithmConstraints constraints;
|
private final AlgorithmConstraints constraints;
|
||||||
private final PublicKey trustedPubKey;
|
private final PublicKey trustedPubKey;
|
||||||
private final Date pkixdate;
|
private final Date date;
|
||||||
private PublicKey prevPubKey;
|
private PublicKey prevPubKey;
|
||||||
private final Timestamp jarTimestamp;
|
|
||||||
private final String variant;
|
private final String variant;
|
||||||
|
private TrustAnchor anchor;
|
||||||
|
|
||||||
private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
|
private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
|
||||||
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
|
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
|
||||||
|
@ -94,95 +91,70 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
|
||||||
CryptoPrimitive.KEY_AGREEMENT));
|
CryptoPrimitive.KEY_AGREEMENT));
|
||||||
|
|
||||||
private static final DisabledAlgorithmConstraints
|
private static final DisabledAlgorithmConstraints
|
||||||
certPathDefaultConstraints = new DisabledAlgorithmConstraints(
|
certPathDefaultConstraints =
|
||||||
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
|
DisabledAlgorithmConstraints.certPathConstraints();
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@code AlgorithmChecker} with the given algorithm
|
* Create a new {@code AlgorithmChecker} with the given
|
||||||
* given {@code TrustAnchor} and {@code String} variant.
|
* {@code TrustAnchor} and {@code String} variant.
|
||||||
*
|
*
|
||||||
* @param anchor the trust anchor selected to validate the target
|
* @param anchor the trust anchor selected to validate the target
|
||||||
* certificate
|
* 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.
|
* passed will set it to Validator.GENERIC.
|
||||||
*/
|
*/
|
||||||
public AlgorithmChecker(TrustAnchor anchor, String variant) {
|
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
|
* Create a new {@code AlgorithmChecker} with the given
|
||||||
* {@code AlgorithmConstraints}, {@code Timestamp}, and {@code String}
|
* {@code AlgorithmConstraints} and {@code String} variant.
|
||||||
* variant.
|
|
||||||
*
|
*
|
||||||
* Note that this constructor can initialize a variation of situations where
|
* 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 constraints the algorithm constraints (or null)
|
||||||
* @param jarTimestamp Timestamp passed for JAR timestamp constraint
|
* @param variant the Validator variant of the operation. A null value
|
||||||
* checking. Set to null if not applicable.
|
|
||||||
* @param variant is the Validator variants of the operation. A null value
|
|
||||||
* passed will set it to Validator.GENERIC.
|
* passed will set it to Validator.GENERIC.
|
||||||
*/
|
*/
|
||||||
public AlgorithmChecker(AlgorithmConstraints constraints,
|
public AlgorithmChecker(AlgorithmConstraints constraints, String variant) {
|
||||||
Timestamp jarTimestamp, String variant) {
|
this(null, constraints, null, variant);
|
||||||
this(null, constraints, null, jarTimestamp, variant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@code AlgorithmChecker} with the
|
* Create a new {@code AlgorithmChecker} with the
|
||||||
* given {@code TrustAnchor}, {@code AlgorithmConstraints},
|
* given {@code TrustAnchor}, {@code AlgorithmConstraints}, {@code Date},
|
||||||
* {@code Timestamp}, and {@code String} variant.
|
* and {@code String} variant.
|
||||||
*
|
*
|
||||||
* @param anchor the trust anchor selected to validate the target
|
* @param anchor the trust anchor selected to validate the target
|
||||||
* certificate
|
* certificate
|
||||||
* @param constraints the algorithm constraints (or null)
|
* @param constraints the algorithm constraints (or null)
|
||||||
* @param pkixdate The date specified by the PKIXParameters date. If the
|
* @param date the date specified by the PKIXParameters date, or the
|
||||||
* PKIXParameters is null, the current date is used. This
|
* JAR timestamp if jar files are being validated and the
|
||||||
* should be null when jar files are being checked.
|
* JAR is timestamped. May be null if no timestamp or
|
||||||
* @param jarTimestamp Timestamp passed for JAR timestamp constraint
|
* PKIXParameter date is set.
|
||||||
* checking. Set to null if not applicable.
|
* @param variant the Validator variant of the operation. A null value
|
||||||
* @param variant is the Validator variants of the operation. A null value
|
|
||||||
* passed will set it to Validator.GENERIC.
|
* passed will set it to Validator.GENERIC.
|
||||||
*/
|
*/
|
||||||
public AlgorithmChecker(TrustAnchor anchor,
|
public AlgorithmChecker(TrustAnchor anchor,
|
||||||
AlgorithmConstraints constraints, Date pkixdate,
|
AlgorithmConstraints constraints, Date date, String variant) {
|
||||||
Timestamp jarTimestamp, String variant) {
|
|
||||||
|
|
||||||
if (anchor != null) {
|
if (anchor != null) {
|
||||||
if (anchor.getTrustedCert() != null) {
|
if (anchor.getTrustedCert() != null) {
|
||||||
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
|
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
|
||||||
// Check for anchor certificate restrictions
|
|
||||||
trustedMatch = checkFingerprint(anchor.getTrustedCert());
|
|
||||||
if (trustedMatch && debug != null) {
|
|
||||||
debug.println("trustedMatch = true");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.trustedPubKey = anchor.getCAPublicKey();
|
this.trustedPubKey = anchor.getCAPublicKey();
|
||||||
}
|
}
|
||||||
|
this.anchor = anchor;
|
||||||
} else {
|
} else {
|
||||||
this.trustedPubKey = null;
|
this.trustedPubKey = null;
|
||||||
if (debug != null) {
|
|
||||||
debug.println("TrustAnchor is null, trustedMatch is false.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.prevPubKey = this.trustedPubKey;
|
this.prevPubKey = this.trustedPubKey;
|
||||||
this.constraints = (constraints == null ? certPathDefaultConstraints :
|
this.constraints = (constraints == null ? certPathDefaultConstraints :
|
||||||
constraints);
|
constraints);
|
||||||
// If we are checking jar files, set pkixdate the same as the timestamp
|
this.date = date;
|
||||||
// for certificate checking
|
|
||||||
this.pkixdate = (jarTimestamp != null ? jarTimestamp.getTimestamp() :
|
|
||||||
pkixdate);
|
|
||||||
this.jarTimestamp = jarTimestamp;
|
|
||||||
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
|
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,24 +166,11 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
|
||||||
* certificate
|
* certificate
|
||||||
* @param pkixdate Date the constraints are checked against. The value is
|
* @param pkixdate Date the constraints are checked against. The value is
|
||||||
* either the PKIXParameters date or null for the current date.
|
* 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.
|
* passed will set it to Validator.GENERIC.
|
||||||
*/
|
*/
|
||||||
public AlgorithmChecker(TrustAnchor anchor, Date pkixdate, String variant) {
|
public AlgorithmChecker(TrustAnchor anchor, Date pkixdate, String variant) {
|
||||||
this(anchor, certPathDefaultConstraints, pkixdate, null, variant);
|
this(anchor, certPathDefaultConstraints, pkixdate, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -318,18 +277,19 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstraintsParameters cp =
|
ConstraintsParameters cp =
|
||||||
new ConstraintsParameters((X509Certificate)cert,
|
new CertPathConstraintsParameters(x509Cert, variant,
|
||||||
trustedMatch, pkixdate, jarTimestamp, variant);
|
anchor, date);
|
||||||
|
|
||||||
// Check against local constraints if it is DisabledAlgorithmConstraints
|
// Check against local constraints if it is DisabledAlgorithmConstraints
|
||||||
if (constraints instanceof DisabledAlgorithmConstraints) {
|
if (constraints instanceof DisabledAlgorithmConstraints) {
|
||||||
((DisabledAlgorithmConstraints)constraints).permits(currSigAlg, cp);
|
((DisabledAlgorithmConstraints)constraints).permits(currSigAlg,
|
||||||
|
currSigAlgParams, cp);
|
||||||
// DisabledAlgorithmsConstraints does not check primitives, so key
|
// DisabledAlgorithmsConstraints does not check primitives, so key
|
||||||
// additional key check.
|
// additional key check.
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Perform the default constraints checking anyway.
|
// Perform the default constraints checking anyway.
|
||||||
certPathDefaultConstraints.permits(currSigAlg, cp);
|
certPathDefaultConstraints.permits(currSigAlg, currSigAlgParams, cp);
|
||||||
// Call locally set constraints to check key with primitives.
|
// Call locally set constraints to check key with primitives.
|
||||||
if (!constraints.permits(primitives, currPubKey)) {
|
if (!constraints.permits(primitives, currPubKey)) {
|
||||||
throw new CertPathValidatorException(
|
throw new CertPathValidatorException(
|
||||||
|
@ -408,14 +368,10 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
|
||||||
// Don't bother to change the trustedPubKey.
|
// Don't bother to change the trustedPubKey.
|
||||||
if (anchor.getTrustedCert() != null) {
|
if (anchor.getTrustedCert() != null) {
|
||||||
prevPubKey = anchor.getTrustedCert().getPublicKey();
|
prevPubKey = anchor.getTrustedCert().getPublicKey();
|
||||||
// Check for anchor certificate restrictions
|
|
||||||
trustedMatch = checkFingerprint(anchor.getTrustedCert());
|
|
||||||
if (trustedMatch && debug != null) {
|
|
||||||
debug.println("trustedMatch = true");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
prevPubKey = anchor.getCAPublicKey();
|
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 key the public key to verify the CRL signature
|
||||||
* @param crl the target CRL
|
* @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.
|
* 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)
|
static void check(PublicKey key, X509CRL crl, String variant,
|
||||||
throws CertPathValidatorException {
|
TrustAnchor anchor) throws CertPathValidatorException {
|
||||||
|
|
||||||
X509CRLImpl x509CRLImpl = null;
|
X509CRLImpl x509CRLImpl = null;
|
||||||
try {
|
try {
|
||||||
|
@ -438,7 +395,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
|
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 key the public key to verify the CRL signature
|
||||||
* @param algorithmId signature algorithm Algorithm ID
|
* @param algorithmId signature algorithm Algorithm ID
|
||||||
* @param variant is the Validator variants of the operation. A null value
|
* @param variant the Validator variant of the operation. A null
|
||||||
* passed will set it to Validator.GENERIC.
|
* 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)
|
static void check(PublicKey key, AlgorithmId algorithmId, String variant,
|
||||||
throws CertPathValidatorException {
|
TrustAnchor anchor) throws CertPathValidatorException {
|
||||||
String sigAlgName = algorithmId.getName();
|
|
||||||
AlgorithmParameters sigAlgParams = algorithmId.getParameters();
|
|
||||||
|
|
||||||
certPathDefaultConstraints.permits(new ConstraintsParameters(
|
certPathDefaultConstraints.permits(algorithmId.getName(),
|
||||||
sigAlgName, sigAlgParams, key, variant));
|
algorithmId.getParameters(),
|
||||||
|
new CertPathConstraintsParameters(key, variant, anchor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.Date;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import java.security.cert.TrustAnchor;
|
||||||
import java.security.cert.X509CertSelector;
|
import java.security.cert.X509CertSelector;
|
||||||
import java.security.cert.X509CRLSelector;
|
import java.security.cert.X509CRLSelector;
|
||||||
|
|
||||||
import sun.security.x509.GeneralNameInterface;
|
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 package. It relies on a subclass in the
|
||||||
* java.security.cert packages that is initialized before any of these methods
|
* java.security.cert packages that is initialized before any of these methods
|
||||||
* are called (achieved via static initializers).
|
* 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 void implSetDateAndTime(X509CRLSelector sel, Date date, long skew);
|
||||||
|
|
||||||
|
protected abstract boolean implIsJdkCA(TrustAnchor anchor);
|
||||||
|
|
||||||
static void setPathToNames(X509CertSelector sel,
|
static void setPathToNames(X509CertSelector sel,
|
||||||
Set<GeneralNameInterface> names) {
|
Set<GeneralNameInterface> names) {
|
||||||
instance.implSetPathToNames(sel, names);
|
instance.implSetPathToNames(sel, names);
|
||||||
|
@ -67,4 +70,8 @@ public abstract class CertPathHelper {
|
||||||
public static void setDateAndTime(X509CRLSelector sel, Date date, long skew) {
|
public static void setDateAndTime(X509CRLSelector sel, Date date, long skew) {
|
||||||
instance.implSetDateAndTime(sel, date, skew);
|
instance.implSetDateAndTime(sel, date, skew);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isJdkCA(TrustAnchor anchor) {
|
||||||
|
return (anchor == null) ? false : instance.implIsJdkCA(anchor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class DistributionPointFetcher {
|
||||||
throws CertStoreException
|
throws CertStoreException
|
||||||
{
|
{
|
||||||
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
|
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
|
* Return the X509CRLs matching this selector. The selector must be
|
||||||
|
@ -91,8 +91,14 @@ public class DistributionPointFetcher {
|
||||||
Date validity)
|
Date validity)
|
||||||
throws CertStoreException
|
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,
|
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,
|
boolean[] reasonsMask,
|
||||||
Set<TrustAnchor> trustAnchors,
|
Set<TrustAnchor> trustAnchors,
|
||||||
Date validity,
|
Date validity,
|
||||||
String variant)
|
String variant,
|
||||||
|
TrustAnchor anchor)
|
||||||
throws CertStoreException
|
throws CertStoreException
|
||||||
{
|
{
|
||||||
X509Certificate cert = selector.getCertificateChecking();
|
X509Certificate cert = selector.getCertificateChecking();
|
||||||
|
@ -137,7 +144,7 @@ public class DistributionPointFetcher {
|
||||||
DistributionPoint point = t.next();
|
DistributionPoint point = t.next();
|
||||||
Collection<X509CRL> crls = getCRLs(selector, certImpl,
|
Collection<X509CRL> crls = getCRLs(selector, certImpl,
|
||||||
point, reasonsMask, signFlag, prevKey, prevCert, provider,
|
point, reasonsMask, signFlag, prevKey, prevCert, provider,
|
||||||
certStores, trustAnchors, validity, variant);
|
certStores, trustAnchors, validity, variant, anchor);
|
||||||
results.addAll(crls);
|
results.addAll(crls);
|
||||||
}
|
}
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
|
@ -162,7 +169,8 @@ public class DistributionPointFetcher {
|
||||||
X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
|
X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
|
||||||
boolean signFlag, PublicKey prevKey, X509Certificate prevCert,
|
boolean signFlag, PublicKey prevKey, X509Certificate prevCert,
|
||||||
String provider, List<CertStore> certStores,
|
String provider, List<CertStore> certStores,
|
||||||
Set<TrustAnchor> trustAnchors, Date validity, String variant)
|
Set<TrustAnchor> trustAnchors, Date validity, String variant,
|
||||||
|
TrustAnchor anchor)
|
||||||
throws CertStoreException {
|
throws CertStoreException {
|
||||||
|
|
||||||
// check for full name
|
// check for full name
|
||||||
|
@ -225,7 +233,7 @@ public class DistributionPointFetcher {
|
||||||
selector.setIssuerNames(null);
|
selector.setIssuerNames(null);
|
||||||
if (selector.match(crl) && verifyCRL(certImpl, point, crl,
|
if (selector.match(crl) && verifyCRL(certImpl, point, crl,
|
||||||
reasonsMask, signFlag, prevKey, prevCert, provider,
|
reasonsMask, signFlag, prevKey, prevCert, provider,
|
||||||
trustAnchors, certStores, validity, variant)) {
|
trustAnchors, certStores, validity, variant, anchor)) {
|
||||||
crls.add(crl);
|
crls.add(crl);
|
||||||
}
|
}
|
||||||
} catch (IOException | CRLException e) {
|
} catch (IOException | CRLException e) {
|
||||||
|
@ -335,7 +343,8 @@ public class DistributionPointFetcher {
|
||||||
X509CRL crl, boolean[] reasonsMask, boolean signFlag,
|
X509CRL crl, boolean[] reasonsMask, boolean signFlag,
|
||||||
PublicKey prevKey, X509Certificate prevCert, String provider,
|
PublicKey prevKey, X509Certificate prevCert, String provider,
|
||||||
Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
|
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) {
|
if (debug != null) {
|
||||||
debug.println("DistributionPointFetcher.verifyCRL: " +
|
debug.println("DistributionPointFetcher.verifyCRL: " +
|
||||||
|
@ -682,7 +691,7 @@ public class DistributionPointFetcher {
|
||||||
|
|
||||||
// check the crl signature algorithm
|
// check the crl signature algorithm
|
||||||
try {
|
try {
|
||||||
AlgorithmChecker.check(prevKey, crl, variant);
|
AlgorithmChecker.check(prevKey, crl, variant, anchor);
|
||||||
} catch (CertPathValidatorException cpve) {
|
} catch (CertPathValidatorException cpve) {
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
debug.println("CRL signature algorithm check failed: " + cpve);
|
debug.println("CRL signature algorithm check failed: " + cpve);
|
||||||
|
|
|
@ -123,7 +123,8 @@ public final class OCSP {
|
||||||
throws IOException, CertPathValidatorException
|
throws IOException, CertPathValidatorException
|
||||||
{
|
{
|
||||||
return check(cert, issuerCert, responderURI, responderCert, date,
|
return check(cert, issuerCert, responderURI, responderCert, date,
|
||||||
Collections.<Extension>emptyList(), Validator.VAR_GENERIC);
|
Collections.<Extension>emptyList(),
|
||||||
|
Validator.VAR_PLUGIN_CODE_SIGNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -566,7 +566,8 @@ public final class OCSPResponse {
|
||||||
if (signerCert != null) {
|
if (signerCert != null) {
|
||||||
// Check algorithm constraints specified in security property
|
// Check algorithm constraints specified in security property
|
||||||
// "jdk.certpath.disabledAlgorithms".
|
// "jdk.certpath.disabledAlgorithms".
|
||||||
AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId, variant);
|
AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId, variant,
|
||||||
|
issuerInfo.getAnchor());
|
||||||
|
|
||||||
if (!verifySignature(signerCert)) {
|
if (!verifySignature(signerCert)) {
|
||||||
throw new CertPathValidatorException(
|
throw new CertPathValidatorException(
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 javax.security.auth.x500.X500Principal;
|
||||||
|
|
||||||
import sun.security.util.Debug;
|
import sun.security.util.Debug;
|
||||||
|
import sun.security.validator.Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common utility methods and classes used by the PKIX CertPathValidator and
|
* Common utility methods and classes used by the PKIX CertPathValidator and
|
||||||
|
@ -87,7 +88,7 @@ class PKIX {
|
||||||
private Set<TrustAnchor> anchors;
|
private Set<TrustAnchor> anchors;
|
||||||
private List<X509Certificate> certs;
|
private List<X509Certificate> certs;
|
||||||
private Timestamp timestamp;
|
private Timestamp timestamp;
|
||||||
private String variant;
|
private String variant = Validator.VAR_GENERIC;
|
||||||
|
|
||||||
ValidatorParams(CertPath cp, PKIXParameters params)
|
ValidatorParams(CertPath cp, PKIXParameters params)
|
||||||
throws InvalidAlgorithmParameterException
|
throws InvalidAlgorithmParameterException
|
||||||
|
@ -155,9 +156,17 @@ class PKIX {
|
||||||
}
|
}
|
||||||
Date date() {
|
Date date() {
|
||||||
if (!gotDate) {
|
if (!gotDate) {
|
||||||
date = params.getDate();
|
// use timestamp if checking signed code that is
|
||||||
if (date == null)
|
// timestamped, otherwise use date parameter
|
||||||
date = new Date();
|
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;
|
gotDate = true;
|
||||||
}
|
}
|
||||||
return date;
|
return date;
|
||||||
|
@ -198,10 +207,6 @@ class PKIX {
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timestamp timestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
String variant() {
|
String variant() {
|
||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.X509ValidationEvent;
|
||||||
import jdk.internal.event.EventHelper;
|
import jdk.internal.event.EventHelper;
|
||||||
import sun.security.provider.certpath.PKIX.ValidatorParams;
|
import sun.security.provider.certpath.PKIX.ValidatorParams;
|
||||||
import sun.security.validator.Validator;
|
|
||||||
import sun.security.x509.X509CertImpl;
|
import sun.security.x509.X509CertImpl;
|
||||||
import sun.security.util.Debug;
|
import sun.security.util.Debug;
|
||||||
|
|
||||||
|
@ -178,7 +177,7 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
|
||||||
// add standard checkers that we will be using
|
// add standard checkers that we will be using
|
||||||
certPathCheckers.add(untrustedChecker);
|
certPathCheckers.add(untrustedChecker);
|
||||||
certPathCheckers.add(new AlgorithmChecker(anchor, null, params.date(),
|
certPathCheckers.add(new AlgorithmChecker(anchor, null, params.date(),
|
||||||
params.timestamp(), params.variant()));
|
params.variant()));
|
||||||
certPathCheckers.add(new KeyChecker(certPathLen,
|
certPathCheckers.add(new KeyChecker(certPathLen,
|
||||||
params.targetCertConstraints()));
|
params.targetCertConstraints()));
|
||||||
certPathCheckers.add(new ConstraintsChecker(certPathLen));
|
certPathCheckers.add(new ConstraintsChecker(certPathLen));
|
||||||
|
@ -195,19 +194,7 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
|
||||||
rootNode);
|
rootNode);
|
||||||
certPathCheckers.add(pc);
|
certPathCheckers.add(pc);
|
||||||
|
|
||||||
// the time that the certificate validity period should be
|
BasicChecker bc = new BasicChecker(anchor, params.date(),
|
||||||
// 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,
|
|
||||||
params.sigProvider(), false);
|
params.sigProvider(), false);
|
||||||
certPathCheckers.add(bc);
|
certPathCheckers.add(bc);
|
||||||
|
|
||||||
|
|
|
@ -585,7 +585,8 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||||
approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
|
approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
|
||||||
sel, signFlag, prevKey, prevCert,
|
sel, signFlag, prevKey, prevCert,
|
||||||
params.sigProvider(), certStores,
|
params.sigProvider(), certStores,
|
||||||
reasonsMask, anchors, null, params.variant()));
|
reasonsMask, anchors, null,
|
||||||
|
params.variant(), anchor));
|
||||||
}
|
}
|
||||||
} catch (CertStoreException e) {
|
} catch (CertStoreException e) {
|
||||||
if (e instanceof CertStoreTypeException) {
|
if (e instanceof CertStoreTypeException) {
|
||||||
|
@ -893,7 +894,7 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||||
if (DistributionPointFetcher.verifyCRL(
|
if (DistributionPointFetcher.verifyCRL(
|
||||||
certImpl, point, crl, reasonsMask, signFlag,
|
certImpl, point, crl, reasonsMask, signFlag,
|
||||||
prevKey, null, params.sigProvider(), anchors,
|
prevKey, null, params.sigProvider(), anchors,
|
||||||
certStores, params.date(), params.variant()))
|
certStores, params.date(), params.variant(), anchor))
|
||||||
{
|
{
|
||||||
results.add(crl);
|
results.add(crl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1558,7 +1558,7 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
|
||||||
// A forward checker, need to check from trust to target
|
// A forward checker, need to check from trust to target
|
||||||
if (checkedLength >= 0) {
|
if (checkedLength >= 0) {
|
||||||
AlgorithmChecker checker =
|
AlgorithmChecker checker =
|
||||||
new AlgorithmChecker(constraints, null,
|
new AlgorithmChecker(constraints,
|
||||||
(checkClientTrusted ? Validator.VAR_TLS_CLIENT :
|
(checkClientTrusted ? Validator.VAR_TLS_CLIENT :
|
||||||
Validator.VAR_TLS_SERVER));
|
Validator.VAR_TLS_SERVER));
|
||||||
checker.init(false);
|
checker.init(false);
|
||||||
|
|
|
@ -838,8 +838,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
|
||||||
AlgorithmConstraints constraints, Certificate[] chain,
|
AlgorithmConstraints constraints, Certificate[] chain,
|
||||||
String variant) {
|
String variant) {
|
||||||
|
|
||||||
AlgorithmChecker checker =
|
AlgorithmChecker checker = new AlgorithmChecker(constraints, variant);
|
||||||
new AlgorithmChecker(constraints, null, variant);
|
|
||||||
try {
|
try {
|
||||||
checker.init(false);
|
checker.init(false);
|
||||||
} catch (CertPathValidatorException cpve) {
|
} catch (CertPathValidatorException cpve) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ import java.util.Enumeration;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.security.auth.x500.X500Principal;
|
||||||
import sun.security.x509.X509CertImpl;
|
import sun.security.x509.X509CertImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,9 +48,10 @@ public class AnchorCertificates {
|
||||||
private static final Debug debug = Debug.getInstance("certpath");
|
private static final Debug debug = Debug.getInstance("certpath");
|
||||||
private static final String HASH = "SHA-256";
|
private static final String HASH = "SHA-256";
|
||||||
private static Set<String> certs = Collections.emptySet();
|
private static Set<String> certs = Collections.emptySet();
|
||||||
|
private static Set<X500Principal> certIssuers = Collections.emptySet();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||||
@Override
|
@Override
|
||||||
public Void run() {
|
public Void run() {
|
||||||
File f = new File(FilePaths.cacerts());
|
File f = new File(FilePaths.cacerts());
|
||||||
|
@ -59,15 +61,16 @@ public class AnchorCertificates {
|
||||||
try (FileInputStream fis = new FileInputStream(f)) {
|
try (FileInputStream fis = new FileInputStream(f)) {
|
||||||
cacerts.load(fis, null);
|
cacerts.load(fis, null);
|
||||||
certs = new HashSet<>();
|
certs = new HashSet<>();
|
||||||
|
certIssuers = new HashSet<>();
|
||||||
Enumeration<String> list = cacerts.aliases();
|
Enumeration<String> list = cacerts.aliases();
|
||||||
String alias;
|
|
||||||
while (list.hasMoreElements()) {
|
while (list.hasMoreElements()) {
|
||||||
alias = list.nextElement();
|
String alias = list.nextElement();
|
||||||
// Check if this cert is labeled a trust anchor.
|
// Check if this cert is labeled a trust anchor.
|
||||||
if (alias.contains(" [jdk")) {
|
if (alias.contains(" [jdk")) {
|
||||||
X509Certificate cert = (X509Certificate) cacerts
|
X509Certificate cert = (X509Certificate) cacerts
|
||||||
.getCertificate(alias);
|
.getCertificate(alias);
|
||||||
certs.add(X509CertImpl.getFingerprint(HASH, cert));
|
certs.add(X509CertImpl.getFingerprint(HASH, cert));
|
||||||
|
certIssuers.add(cert.getSubjectX500Principal());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,10 +86,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
|
* @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) {
|
public static boolean contains(X509Certificate cert) {
|
||||||
String key = X509CertImpl.getFingerprint(HASH, cert);
|
String key = X509CertImpl.getFingerprint(HASH, cert);
|
||||||
|
@ -98,5 +101,15 @@ public class AnchorCertificates {
|
||||||
return result;
|
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() {}
|
private AnchorCertificates() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,167 +25,42 @@
|
||||||
|
|
||||||
package sun.security.util;
|
package sun.security.util;
|
||||||
|
|
||||||
import sun.security.validator.Validator;
|
|
||||||
|
|
||||||
import java.security.AlgorithmParameters;
|
|
||||||
import java.security.Key;
|
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.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class contains parameters for checking against constraints that extend
|
* This interface contains parameters for checking against constraints that
|
||||||
* past the publicly available parameters in java.security.AlgorithmConstraints.
|
* extend past the publicly available parameters in
|
||||||
*
|
* java.security.AlgorithmConstraints.
|
||||||
* This is currently passed between PKIX, AlgorithmChecker,
|
|
||||||
* and DisabledAlgorithmConstraints.
|
|
||||||
*/
|
*/
|
||||||
public class ConstraintsParameters {
|
public interface ConstraintsParameters {
|
||||||
/*
|
|
||||||
* The below 3 values are used the same as the permit() methods
|
/**
|
||||||
* published in java.security.AlgorithmConstraints.
|
* Returns true if a certificate chains back to a trusted JDK root CA.
|
||||||
*/
|
*/
|
||||||
// Algorithm string to be checked against constraints
|
boolean anchorIsJdkCA();
|
||||||
private final String algorithm;
|
|
||||||
// AlgorithmParameters to the algorithm being checked
|
|
||||||
private final AlgorithmParameters algParams;
|
|
||||||
// Key being checked against constraints
|
|
||||||
private final Key key;
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* New values that are checked against constraints that the current public
|
* Returns the set of keys that should be checked against the
|
||||||
* API does not support.
|
* constraints, or an empty set if there are no keys to be checked.
|
||||||
*/
|
*/
|
||||||
// A certificate being passed to check against constraints.
|
Set<Key> getKeys();
|
||||||
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];
|
|
||||||
|
|
||||||
public ConstraintsParameters(X509Certificate c, boolean match,
|
/**
|
||||||
Date pkixdate, Timestamp jarTime, String variant) {
|
* Returns the date that should be checked against the constraints, or
|
||||||
cert = c;
|
* null if not set.
|
||||||
trustedMatch = match;
|
*/
|
||||||
pkixDate = pkixdate;
|
Date getDate();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConstraintsParameters(String algorithm, AlgorithmParameters params,
|
/**
|
||||||
Key key, String variant) {
|
* Returns the Validator variant.
|
||||||
this.algorithm = algorithm;
|
*/
|
||||||
algParams = params;
|
String getVariant();
|
||||||
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 an extended message used in exceptions. See
|
||||||
|
* DisabledAlgorithmConstraints for usage.
|
||||||
|
*/
|
||||||
|
String extendedExceptionMsg();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,12 +27,18 @@ package sun.security.util;
|
||||||
|
|
||||||
import sun.security.validator.Validator;
|
import sun.security.validator.Validator;
|
||||||
|
|
||||||
import java.security.CryptoPrimitive;
|
|
||||||
import java.security.AlgorithmParameters;
|
import java.security.AlgorithmParameters;
|
||||||
|
import java.security.CryptoPrimitive;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.cert.CertPathValidatorException;
|
import java.security.cert.CertPathValidatorException;
|
||||||
import java.security.cert.CertPathValidatorException.BasicReason;
|
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.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -79,9 +85,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
private static final String PROPERTY_DISABLED_EC_CURVES =
|
private static final String PROPERTY_DISABLED_EC_CURVES =
|
||||||
"jdk.disabled.namedCurves";
|
"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 List<String> disabledAlgorithms;
|
||||||
private final Constraints algorithmConstraints;
|
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.
|
* Initialize algorithm constraints with the specified security property.
|
||||||
*
|
*
|
||||||
|
@ -122,7 +146,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
disabledAlgorithms.addAll(ecindex,
|
disabledAlgorithms.addAll(ecindex,
|
||||||
getAlgorithms(PROPERTY_DISABLED_EC_CURVES));
|
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);
|
return checkConstraints(primitives, algorithm, key, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void permits(ConstraintsParameters cp)
|
public final void permits(String algorithm, AlgorithmParameters ap,
|
||||||
throws CertPathValidatorException {
|
ConstraintsParameters cp) throws CertPathValidatorException {
|
||||||
permits(cp.getAlgorithm(), cp);
|
|
||||||
|
permits(algorithm, cp);
|
||||||
|
if (ap != null) {
|
||||||
|
permits(ap, cp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void permits(String algorithm, Key key,
|
private void permits(AlgorithmParameters ap, ConstraintsParameters cp)
|
||||||
AlgorithmParameters params, String variant)
|
throws CertPathValidatorException {
|
||||||
throws CertPathValidatorException {
|
|
||||||
permits(algorithm, new ConstraintsParameters(algorithm, params, key,
|
switch (ap.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
|
||||||
(variant == null) ? Validator.VAR_GENERIC : variant));
|
case "RSASSA-PSS":
|
||||||
|
permitsPSSParams(ap, cp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// unknown algorithm, just ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
private void permitsPSSParams(AlgorithmParameters ap,
|
||||||
* Check if a x509Certificate object is permitted. Check if all
|
ConstraintsParameters cp) throws CertPathValidatorException {
|
||||||
* algorithms are allowed, certificate constraints, and the
|
|
||||||
* public key against key constraints.
|
try {
|
||||||
*
|
PSSParameterSpec pssParams =
|
||||||
* Uses new style permit() which throws exceptions.
|
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)
|
public final void permits(String algorithm, ConstraintsParameters cp)
|
||||||
throws CertPathValidatorException {
|
throws CertPathValidatorException {
|
||||||
|
|
||||||
// Check if named curves in the ConstraintParameters are disabled.
|
// Check if named curves in the key are disabled.
|
||||||
if (cp.getNamedCurve() != null) {
|
for (Key key : cp.getKeys()) {
|
||||||
for (String curve : cp.getNamedCurve()) {
|
for (String curve : getNamedCurveFromKey(key)) {
|
||||||
if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
|
if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
|
||||||
throw new CertPathValidatorException(
|
throw new CertPathValidatorException(
|
||||||
"Algorithm constraints check failed on disabled " +
|
"Algorithm constraints check failed on disabled " +
|
||||||
|
@ -210,15 +256,17 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
algorithmConstraints.permits(algorithm, cp);
|
algorithmConstraints.permits(algorithm, cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a string is contained inside the property
|
private static List<String> getNamedCurveFromKey(Key key) {
|
||||||
public boolean checkProperty(String param) {
|
if (key instanceof ECKey) {
|
||||||
param = param.toLowerCase(Locale.ENGLISH);
|
NamedCurve nc = CurveDB.lookup(((ECKey)key).getParams());
|
||||||
for (String block : disabledAlgorithms) {
|
return (nc == null ? List.of()
|
||||||
if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
|
: Arrays.asList(nc.getNameAndAliases()));
|
||||||
return true;
|
} 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
|
// Check algorithm constraints with key and algorithm
|
||||||
|
@ -246,8 +294,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is an elliptic curve, check disabled the named curve.
|
// If this is an elliptic curve, check if it is disabled
|
||||||
for (String curve : ConstraintsParameters.getNamedCurveFromKey(key)) {
|
for (String curve : getNamedCurveFromKey(key)) {
|
||||||
if (!permits(primitives, curve, null)) {
|
if (!permits(primitives, curve, null)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -284,7 +332,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
"denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
|
"denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Constraints(List<String> constraintArray) {
|
public Constraints(String propertyName, List<String> constraintArray) {
|
||||||
for (String constraintEntry : constraintArray) {
|
for (String constraintEntry : constraintArray) {
|
||||||
if (constraintEntry == null || constraintEntry.isEmpty()) {
|
if (constraintEntry == null || constraintEntry.isEmpty()) {
|
||||||
continue;
|
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) {
|
private List<Constraint> getConstraints(String algorithm) {
|
||||||
return constraintsMap.get(algorithm.toUpperCase(Locale.ENGLISH));
|
return constraintsMap.get(algorithm.toUpperCase(Locale.ENGLISH));
|
||||||
}
|
}
|
||||||
|
@ -443,13 +491,12 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if constraints permit this cert.
|
|
||||||
public void permits(String algorithm, ConstraintsParameters cp)
|
public void permits(String algorithm, ConstraintsParameters cp)
|
||||||
throws CertPathValidatorException {
|
throws CertPathValidatorException {
|
||||||
X509Certificate cert = cp.getCertificate();
|
|
||||||
|
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
debug.println("Constraints.permits(): " + cp.toString());
|
debug.println("Constraints.permits(): " + algorithm + ", "
|
||||||
|
+ cp.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all signature algorithms to check for constraints
|
// Get all signature algorithms to check for constraints
|
||||||
|
@ -459,13 +506,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
algorithms.add(algorithm);
|
algorithms.add(algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to add the public key algorithm if cert provided
|
for (Key key : cp.getKeys()) {
|
||||||
if (cert != null) {
|
algorithms.add(key.getAlgorithm());
|
||||||
algorithms.add(cert.getPublicKey().getAlgorithm());
|
|
||||||
}
|
|
||||||
if (cp.getKey() != null) {
|
|
||||||
algorithms.add(cp.getKey().getAlgorithm());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check all applicable constraints
|
// Check all applicable constraints
|
||||||
for (String alg : algorithms) {
|
for (String alg : algorithms) {
|
||||||
List<Constraint> list = getConstraints(alg);
|
List<Constraint> list = getConstraints(alg);
|
||||||
|
@ -556,7 +600,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
* {@code next()} with the same {@code ConstraintsParameters}
|
* {@code next()} with the same {@code ConstraintsParameters}
|
||||||
* parameter passed if multiple constraints need to be checked.
|
* 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.
|
* @throws CertPathValidatorException if constraint disallows.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -605,14 +649,6 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
boolean next(Key key) {
|
boolean next(Key key) {
|
||||||
return nextConstraint != null && nextConstraint.permits(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);
|
debug.println("jdkCAConstraints.permits(): " + algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check chain has a trust anchor in cacerts
|
// Check if any certs chain back to at least one trust anchor in
|
||||||
if (cp.isTrustedMatch()) {
|
// cacerts
|
||||||
|
if (cp.anchorIsJdkCA()) {
|
||||||
if (next(cp)) {
|
if (next(cp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new CertPathValidatorException(
|
throw new CertPathValidatorException(
|
||||||
"Algorithm constraints check failed on certificate " +
|
"Algorithm constraints check failed on certificate " +
|
||||||
"anchor limits. " + algorithm + extendedMsg(cp),
|
"anchor limits. " + algorithm + cp.extendedExceptionMsg(),
|
||||||
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -708,15 +745,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
Date currentDate;
|
Date currentDate;
|
||||||
String errmsg;
|
String errmsg;
|
||||||
|
|
||||||
if (cp.getJARTimestamp() != null) {
|
if (cp.getDate() != null) {
|
||||||
currentDate = cp.getJARTimestamp().getTimestamp();
|
currentDate = cp.getDate();
|
||||||
errmsg = "JAR Timestamp date: ";
|
|
||||||
} else if (cp.getPKIXParamDate() != null) {
|
|
||||||
currentDate = cp.getPKIXParamDate();
|
|
||||||
errmsg = "PKIXParameter date: ";
|
|
||||||
} else {
|
} else {
|
||||||
currentDate = new Date();
|
currentDate = new Date();
|
||||||
errmsg = "Current date: ";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!denyAfterDate.after(currentDate)) {
|
if (!denyAfterDate.after(currentDate)) {
|
||||||
|
@ -726,8 +758,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
throw new CertPathValidatorException(
|
throw new CertPathValidatorException(
|
||||||
"denyAfter constraint check failed: " + algorithm +
|
"denyAfter constraint check failed: " + algorithm +
|
||||||
" used with Constraint date: " +
|
" used with Constraint date: " +
|
||||||
dateFormat.format(denyAfterDate) + "; " + errmsg +
|
dateFormat.format(denyAfterDate) + "; params date: " +
|
||||||
dateFormat.format(currentDate) + extendedMsg(cp),
|
dateFormat.format(currentDate) + cp.extendedExceptionMsg(),
|
||||||
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,19 +796,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
@Override
|
@Override
|
||||||
public void permits(ConstraintsParameters cp)
|
public void permits(ConstraintsParameters cp)
|
||||||
throws CertPathValidatorException {
|
throws CertPathValidatorException {
|
||||||
|
String variant = cp.getVariant();
|
||||||
for (String usage : usages) {
|
for (String usage : usages) {
|
||||||
|
|
||||||
String v = null;
|
boolean match = false;
|
||||||
if (usage.compareToIgnoreCase("TLSServer") == 0) {
|
switch (usage.toLowerCase()) {
|
||||||
v = Validator.VAR_TLS_SERVER;
|
case "tlsserver":
|
||||||
} else if (usage.compareToIgnoreCase("TLSClient") == 0) {
|
match = variant.equals(Validator.VAR_TLS_SERVER);
|
||||||
v = Validator.VAR_TLS_CLIENT;
|
break;
|
||||||
} else if (usage.compareToIgnoreCase("SignedJAR") == 0) {
|
case "tlsclient":
|
||||||
v = Validator.VAR_PLUGIN_CODE_SIGNING;
|
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) {
|
if (debug != null) {
|
||||||
debug.println("Checking if usage constraint \"" + v +
|
debug.println("Checking if usage constraint \"" + usage +
|
||||||
"\" matches \"" + cp.getVariant() + "\"");
|
"\" matches \"" + cp.getVariant() + "\"");
|
||||||
if (Debug.isVerbose()) {
|
if (Debug.isVerbose()) {
|
||||||
// Because usage checking can come from many places
|
// Because usage checking can come from many places
|
||||||
|
@ -784,13 +824,13 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
(new Exception()).printStackTrace(debug.getPrintStream());
|
(new Exception()).printStackTrace(debug.getPrintStream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cp.getVariant().compareTo(v) == 0) {
|
if (match) {
|
||||||
if (next(cp)) {
|
if (next(cp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new CertPathValidatorException("Usage constraint " +
|
throw new CertPathValidatorException("Usage constraint " +
|
||||||
usage + " check failed: " + algorithm +
|
usage + " check failed: " + algorithm +
|
||||||
extendedMsg(cp),
|
cp.extendedExceptionMsg(),
|
||||||
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -843,31 +883,25 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are passed a certificate, extract the public key and use it.
|
* For each key, check if each constraint fails and check if there is
|
||||||
*
|
* a linked constraint. Any permitted constraint will exit the linked
|
||||||
* Check if each constraint fails and check if there is a linked
|
* list to allow the operation.
|
||||||
* constraint Any permitted constraint will exit the linked list
|
|
||||||
* to allow the operation.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void permits(ConstraintsParameters cp)
|
public void permits(ConstraintsParameters cp)
|
||||||
throws CertPathValidatorException {
|
throws CertPathValidatorException {
|
||||||
Key key = null;
|
for (Key key : cp.getKeys()) {
|
||||||
if (cp.getKey() != null) {
|
if (!permitsImpl(key)) {
|
||||||
key = cp.getKey();
|
if (nextConstraint != null) {
|
||||||
} else if (cp.getCertificate() != null) {
|
nextConstraint.permits(cp);
|
||||||
key = cp.getCertificate().getPublicKey();
|
continue;
|
||||||
}
|
}
|
||||||
if (key != null && !permitsImpl(key)) {
|
throw new CertPathValidatorException(
|
||||||
if (nextConstraint != null) {
|
"Algorithm constraints check failed on keysize limits: " +
|
||||||
nextConstraint.permits(cp);
|
algorithm + " " + KeyUtil.getKeySize(key) + " bit key" +
|
||||||
return;
|
cp.extendedExceptionMsg(),
|
||||||
}
|
|
||||||
throw new CertPathValidatorException(
|
|
||||||
"Algorithm constraints check failed on keysize limits. " +
|
|
||||||
algorithm + " " + KeyUtil.getKeySize(key) + "bit key" +
|
|
||||||
extendedMsg(cp),
|
|
||||||
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,7 +978,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||||
throws CertPathValidatorException {
|
throws CertPathValidatorException {
|
||||||
throw new CertPathValidatorException(
|
throw new CertPathValidatorException(
|
||||||
"Algorithm constraints check failed on disabled " +
|
"Algorithm constraints check failed on disabled " +
|
||||||
"algorithm: " + algorithm + extendedMsg(cp),
|
"algorithm: " + algorithm + cp.extendedExceptionMsg(),
|
||||||
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,13 +27,12 @@ package sun.security.util;
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.security.CodeSigner;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.jar.*;
|
import java.util.jar.*;
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
import sun.security.jca.Providers;
|
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
|
* 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);
|
throw new SecurityException("digest missing for " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signers != null)
|
if (signers != null) {
|
||||||
return signers;
|
return signers;
|
||||||
|
}
|
||||||
|
|
||||||
|
JarConstraintsParameters params =
|
||||||
|
getParams(verifiedSigners, sigFileSigners);
|
||||||
|
|
||||||
for (int i=0; i < digests.size(); i++) {
|
for (int i=0; i < digests.size(); i++) {
|
||||||
|
|
||||||
MessageDigest digest = digests.get(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 [] manHash = manifestHashes.get(i);
|
||||||
byte [] theHash = digest.digest();
|
byte [] theHash = digest.digest();
|
||||||
|
|
||||||
|
@ -231,4 +247,37 @@ public class ManifestEntryVerifier {
|
||||||
}
|
}
|
||||||
return signers;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.security.Timestamp;
|
|
||||||
import java.security.cert.CertPath;
|
import java.security.cert.CertPath;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
@ -47,6 +46,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.jar.Attributes;
|
import java.util.jar.Attributes;
|
||||||
import java.util.jar.JarException;
|
import java.util.jar.JarException;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
@ -61,16 +61,6 @@ public class SignatureFileVerifier {
|
||||||
/* Are we debugging ? */
|
/* Are we debugging ? */
|
||||||
private static final Debug debug = Debug.getInstance("jar");
|
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 ArrayList<CodeSigner[]> signerCache;
|
||||||
|
|
||||||
private static final String ATTR_DIGEST =
|
private static final String ATTR_DIGEST =
|
||||||
|
@ -99,13 +89,13 @@ public class SignatureFileVerifier {
|
||||||
/* for generating certpath objects */
|
/* for generating certpath objects */
|
||||||
private CertificateFactory certificateFactory = null;
|
private CertificateFactory certificateFactory = null;
|
||||||
|
|
||||||
/** Algorithms that have been checked if they are weak. */
|
/** Algorithms that have been previously checked against disabled
|
||||||
private Map<String, Boolean> permittedAlgs= new HashMap<>();
|
* constraints.
|
||||||
|
|
||||||
/** TSA timestamp of signed jar. The newest timestamp is used. If there
|
|
||||||
* was no TSA timestamp used when signed, current time is used ("null").
|
|
||||||
*/
|
*/
|
||||||
private Timestamp timestamp = null;
|
private Map<String, Boolean> permittedAlgs = new HashMap<>();
|
||||||
|
|
||||||
|
/** ConstraintsParameters for checking disabled algorithms */
|
||||||
|
private JarConstraintsParameters params;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the named SignatureFileVerifier.
|
* Create the named SignatureFileVerifier.
|
||||||
|
@ -320,32 +310,23 @@ public class SignatureFileVerifier {
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CodeSigner[] newSigners = getSigners(infos, block);
|
CodeSigner[] newSigners = getSigners(infos, block);
|
||||||
|
|
||||||
// make sure we have something to do all this work for...
|
// make sure we have something to do all this work for...
|
||||||
if (newSigners == null)
|
if (newSigners == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
// check if any of the algorithms used to verify the SignerInfos
|
||||||
* Look for the latest timestamp in the signature block. If an entry
|
// are disabled
|
||||||
* has no timestamp, use current time (aka null).
|
params = new JarConstraintsParameters(newSigners);
|
||||||
*/
|
Set<String> notDisabledAlgorithms =
|
||||||
for (CodeSigner s: newSigners) {
|
SignerInfo.verifyAlgorithms(infos, params, name + " PKCS7");
|
||||||
if (debug != null) {
|
|
||||||
debug.println("Gathering timestamp for: " + s.toString());
|
// add the SignerInfo algorithms that are ok to the permittedAlgs map
|
||||||
}
|
// so they are not checked again
|
||||||
if (s.getTimestamp() == null) {
|
for (String algorithm : notDisabledAlgorithms) {
|
||||||
timestamp = null;
|
permittedAlgs.put(algorithm, Boolean.TRUE);
|
||||||
break;
|
|
||||||
} else if (timestamp == null) {
|
|
||||||
timestamp = s.getTimestamp();
|
|
||||||
} else {
|
|
||||||
if (timestamp.getTimestamp().before(
|
|
||||||
s.getTimestamp().getTimestamp())) {
|
|
||||||
timestamp = s.getTimestamp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<Map.Entry<String,Attributes>> entries =
|
Iterator<Map.Entry<String,Attributes>> entries =
|
||||||
|
@ -396,13 +377,14 @@ public class SignatureFileVerifier {
|
||||||
* store the result. If the algorithm is in the map use that result.
|
* store the result. If the algorithm is in the map use that result.
|
||||||
* False is returned for weak algorithm, true for good algorithms.
|
* 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);
|
Boolean permitted = permittedAlgs.get(algorithm);
|
||||||
if (permitted == null) {
|
if (permitted == null) {
|
||||||
try {
|
try {
|
||||||
ConfigurationHolder.JAR_DISABLED_CHECK.permits(algorithm,
|
params.setExtendedExceptionMsg(name + ".SF", key + " attribute");
|
||||||
new ConstraintsParameters(timestamp));
|
DisabledAlgorithmConstraints
|
||||||
} catch(GeneralSecurityException e) {
|
.jarConstraints().permits(algorithm, params);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
permittedAlgs.put(algorithm, Boolean.FALSE);
|
permittedAlgs.put(algorithm, Boolean.FALSE);
|
||||||
permittedAlgs.put(key.toUpperCase(), Boolean.FALSE);
|
permittedAlgs.put(key.toUpperCase(), Boolean.FALSE);
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
|
|
|
@ -224,7 +224,7 @@ public final class PKIXValidator extends Validator {
|
||||||
// add new algorithm constraints checker
|
// add new algorithm constraints checker
|
||||||
if (constraints != null) {
|
if (constraints != null) {
|
||||||
pkixParameters.addCertPathChecker(
|
pkixParameters.addCertPathChecker(
|
||||||
new AlgorithmChecker(constraints, null, variant));
|
new AlgorithmChecker(constraints, variant));
|
||||||
}
|
}
|
||||||
|
|
||||||
// attach it to the PKIXBuilderParameters.
|
// attach it to the PKIXBuilderParameters.
|
||||||
|
|
|
@ -167,7 +167,7 @@ public final class SimpleValidator extends Validator {
|
||||||
AlgorithmChecker appAlgChecker = null;
|
AlgorithmChecker appAlgChecker = null;
|
||||||
if (constraints != null) {
|
if (constraints != null) {
|
||||||
appAlgChecker = new AlgorithmChecker(anchor, constraints, null,
|
appAlgChecker = new AlgorithmChecker(anchor, constraints, null,
|
||||||
null, variant);
|
variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify top down, starting at the certificate issued by
|
// verify top down, starting at the certificate issued by
|
||||||
|
|
|
@ -318,7 +318,7 @@ public class TimestampCheck {
|
||||||
sign("tsdisabled", "-digestalg", "MD5",
|
sign("tsdisabled", "-digestalg", "MD5",
|
||||||
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
|
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
|
||||||
.shouldHaveExitValue(68)
|
.shouldHaveExitValue(68)
|
||||||
.shouldContain("The timestamp is invalid. Without a valid timestamp")
|
.shouldContain("TSA certificate chain is invalid")
|
||||||
.shouldMatch("MD5.*-digestalg.*is disabled")
|
.shouldMatch("MD5.*-digestalg.*is disabled")
|
||||||
.shouldMatch("MD5.*-tsadigestalg.*is disabled")
|
.shouldMatch("MD5.*-tsadigestalg.*is disabled")
|
||||||
.shouldMatch("MD5withRSA.*-sigalg.*is disabled");
|
.shouldMatch("MD5withRSA.*-sigalg.*is disabled");
|
||||||
|
@ -326,7 +326,6 @@ public class TimestampCheck {
|
||||||
|
|
||||||
signVerbose("tsdisabled", "unsigned.jar", "tsdisabled2.jar", "signer")
|
signVerbose("tsdisabled", "unsigned.jar", "tsdisabled2.jar", "signer")
|
||||||
.shouldHaveExitValue(64)
|
.shouldHaveExitValue(64)
|
||||||
.shouldContain("The timestamp is invalid. Without a valid timestamp")
|
|
||||||
.shouldContain("TSA certificate chain is invalid");
|
.shouldContain("TSA certificate chain is invalid");
|
||||||
|
|
||||||
// Disabled timestamp is an error and jar treated unsigned
|
// Disabled timestamp is an error and jar treated unsigned
|
||||||
|
@ -658,7 +657,7 @@ public class TimestampCheck {
|
||||||
.shouldMatch("Timestamp signature algorithm: .*key.*(disabled)");
|
.shouldMatch("Timestamp signature algorithm: .*key.*(disabled)");
|
||||||
verify(file, "-J-Djava.security.debug=jar")
|
verify(file, "-J-Djava.security.debug=jar")
|
||||||
.shouldHaveExitValue(16)
|
.shouldHaveExitValue(16)
|
||||||
.shouldMatch("SignatureException:.*disabled");
|
.shouldMatch("SignatureException:.*keysize");
|
||||||
|
|
||||||
// For 8171319: keytool should print out warnings when reading or
|
// For 8171319: keytool should print out warnings when reading or
|
||||||
// generating cert/cert req using disabled algorithms.
|
// generating cert/cert req using disabled algorithms.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue