提交 088a356d 编写于 作者: A ascarpino

8176536: Improved algorithm constraints checking

Reviewed-by: mullan
上级 dd5a9e1f
/* /*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2017, 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
...@@ -37,6 +37,7 @@ import java.security.PublicKey; ...@@ -37,6 +37,7 @@ import java.security.PublicKey;
import java.security.Signature; import java.security.Signature;
import java.security.SignatureException; import java.security.SignatureException;
import java.security.Timestamp; import java.security.Timestamp;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.CertPath; import java.security.cert.CertPath;
...@@ -49,6 +50,7 @@ import java.util.Set; ...@@ -49,6 +50,7 @@ import java.util.Set;
import sun.misc.HexDumpEncoder; import sun.misc.HexDumpEncoder;
import sun.security.timestamp.TimestampToken; import sun.security.timestamp.TimestampToken;
import sun.security.util.ConstraintsParameters;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.util.DerEncoder; import sun.security.util.DerEncoder;
import sun.security.util.DerInputStream; import sun.security.util.DerInputStream;
...@@ -209,7 +211,7 @@ public class SignerInfo implements DerEncoder { ...@@ -209,7 +211,7 @@ public class SignerInfo implements DerEncoder {
/** /**
* DER encode this object onto an output stream. * DER encode this object onto an output stream.
* Implements the <code>DerEncoder</code> interface. * Implements the {@code DerEncoder} interface.
* *
* @param out * @param out
* the output stream on which to write the DER encoding. * the output stream on which to write the DER encoding.
...@@ -266,7 +268,7 @@ public class SignerInfo implements DerEncoder { ...@@ -266,7 +268,7 @@ public class SignerInfo implements DerEncoder {
if (userCert == null) if (userCert == null)
return null; return null;
ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>(); ArrayList<X509Certificate> certList = new ArrayList<>();
certList.add(userCert); certList.add(userCert);
X509Certificate[] pkcsCerts = block.getCertificates(); X509Certificate[] pkcsCerts = block.getCertificates();
...@@ -321,6 +323,8 @@ public class SignerInfo implements DerEncoder { ...@@ -321,6 +323,8 @@ public class SignerInfo implements DerEncoder {
data = content.getContentBytes(); data = content.getContentBytes();
} }
ConstraintsParameters cparams =
new ConstraintsParameters(timestamp);
String digestAlgname = getDigestAlgorithmId().getName(); String digestAlgname = getDigestAlgorithmId().getName();
byte[] dataSigned; byte[] dataSigned;
...@@ -347,11 +351,11 @@ public class SignerInfo implements DerEncoder { ...@@ -347,11 +351,11 @@ 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;
// check that algorithm is not restricted // check that digest algorithm is not restricted
if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, try {
digestAlgname, null)) { JAR_DISABLED_CHECK.permits(digestAlgname, cparams);
throw new SignatureException("Digest check failed. " + } catch (CertPathValidatorException e) {
"Disabled algorithm used: " + digestAlgname); throw new SignatureException(e.getMessage(), e);
} }
MessageDigest md = MessageDigest.getInstance(digestAlgname); MessageDigest md = MessageDigest.getInstance(digestAlgname);
...@@ -385,17 +389,18 @@ public class SignerInfo implements DerEncoder { ...@@ -385,17 +389,18 @@ public class SignerInfo implements DerEncoder {
String algname = AlgorithmId.makeSigAlg( String algname = AlgorithmId.makeSigAlg(
digestAlgname, encryptionAlgname); digestAlgname, encryptionAlgname);
// check that algorithm is not restricted // check that jar signature algorithm is not restricted
if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, algname, null)) { try {
throw new SignatureException("Signature check failed. " + JAR_DISABLED_CHECK.permits(algname, cparams);
"Disabled algorithm used: " + algname); } catch (CertPathValidatorException e) {
throw new SignatureException(e.getMessage(), e);
} }
X509Certificate cert = getCertificate(block); X509Certificate cert = getCertificate(block);
PublicKey key = cert.getPublicKey();
if (cert == null) { if (cert == null) {
return null; return null;
} }
PublicKey key = cert.getPublicKey();
// check if the public key is restricted // check if the public key is restricted
if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
...@@ -519,7 +524,7 @@ public class SignerInfo implements DerEncoder { ...@@ -519,7 +524,7 @@ public class SignerInfo implements DerEncoder {
* Extracts a timestamp from a PKCS7 SignerInfo. * Extracts a timestamp from a PKCS7 SignerInfo.
* *
* Examines the signer's unsigned attributes for a * Examines the signer's unsigned attributes for a
* <tt>signatureTimestampToken</tt> attribute. If present, * {@code signatureTimestampToken} attribute. If present,
* then it is parsed to extract the date and time at which the * then it is parsed to extract the date and time at which the
* timestamp was generated. * timestamp was generated.
* *
......
/* /*
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2017, 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,11 @@ package sun.security.provider.certpath; ...@@ -27,8 +27,11 @@ 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.Set; import java.util.Set;
import java.util.EnumSet; import java.util.EnumSet;
import java.math.BigInteger; import java.math.BigInteger;
...@@ -51,15 +54,16 @@ import java.security.interfaces.DSAPublicKey; ...@@ -51,15 +54,16 @@ import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAPublicKeySpec; import java.security.spec.DSAPublicKeySpec;
import sun.security.util.AnchorCertificates; import sun.security.util.AnchorCertificates;
import sun.security.util.CertConstraintParameters; 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.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CRLImpl; import sun.security.x509.X509CRLImpl;
import sun.security.x509.AlgorithmId; import sun.security.x509.AlgorithmId;
/** /**
* A <code>PKIXCertPathChecker</code> implementation to check whether a * A {@code PKIXCertPathChecker} implementation to check whether a
* specified certificate contains the required algorithm constraints. * specified certificate contains the required algorithm constraints.
* <p> * <p>
* Certificate fields such as the subject public key, the signature * Certificate fields such as the subject public key, the signature
...@@ -69,24 +73,27 @@ import sun.security.x509.AlgorithmId; ...@@ -69,24 +73,27 @@ import sun.security.x509.AlgorithmId;
* @see PKIXCertPathChecker * @see PKIXCertPathChecker
* @see PKIXParameters * @see PKIXParameters
*/ */
final public class AlgorithmChecker extends PKIXCertPathChecker { public final class AlgorithmChecker extends PKIXCertPathChecker {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private final AlgorithmConstraints constraints; private final AlgorithmConstraints constraints;
private final PublicKey trustedPubKey; private final PublicKey trustedPubKey;
private final Date pkixdate;
private PublicKey prevPubKey; private PublicKey prevPubKey;
private final Timestamp jarTimestamp;
private final String variant;
private final static 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));
private final static Set<CryptoPrimitive> KU_PRIMITIVE_SET = private static final Set<CryptoPrimitive> KU_PRIMITIVE_SET =
Collections.unmodifiableSet(EnumSet.of( Collections.unmodifiableSet(EnumSet.of(
CryptoPrimitive.SIGNATURE, CryptoPrimitive.SIGNATURE,
CryptoPrimitive.KEY_ENCAPSULATION, CryptoPrimitive.KEY_ENCAPSULATION,
CryptoPrimitive.PUBLIC_KEY_ENCRYPTION, CryptoPrimitive.PUBLIC_KEY_ENCRYPTION,
CryptoPrimitive.KEY_AGREEMENT)); CryptoPrimitive.KEY_AGREEMENT));
private final static DisabledAlgorithmConstraints private static final DisabledAlgorithmConstraints
certPathDefaultConstraints = new DisabledAlgorithmConstraints( certPathDefaultConstraints = new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
...@@ -99,64 +106,99 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { ...@@ -99,64 +106,99 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
private boolean trustedMatch = false; private boolean trustedMatch = false;
/** /**
* Create a new <code>AlgorithmChecker</code> with the algorithm * Create a new {@code AlgorithmChecker} with the given algorithm
* constraints specified in security property * given {@code TrustAnchor} and {@code String} variant.
* "jdk.certpath.disabledAlgorithms".
* *
* @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
* passed will set it to Validator.GENERIC.
*/ */
public AlgorithmChecker(TrustAnchor anchor) { public AlgorithmChecker(TrustAnchor anchor, String variant) {
this(anchor, certPathDefaultConstraints); this(anchor, certPathDefaultConstraints, null, null, variant);
} }
/** /**
* Create a new <code>AlgorithmChecker</code> with the * Create a new {@code AlgorithmChecker} with the given
* given {@code AlgorithmConstraints}. * {@code AlgorithmConstraints}, {@code Timestamp}, and {@code String}
* <p> * variant.
* Note that this constructor will be used to check a certification *
* path where the trust anchor is unknown, or a certificate list which may * Note that this constructor can initialize a variation of situations where
* contain the trust anchor. This constructor is used by SunJSSE. * the AlgorithmConstraints, Timestamp, 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
* 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.
*/ */
public AlgorithmChecker(AlgorithmConstraints constraints) { public AlgorithmChecker(AlgorithmConstraints constraints,
this.prevPubKey = null; Timestamp jarTimestamp, String variant) {
this.trustedPubKey = null; this(null, constraints, null, jarTimestamp, variant);
this.constraints = constraints;
} }
/** /**
* Create a new <code>AlgorithmChecker</code> with the * Create a new {@code AlgorithmChecker} with the
* given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>. * given {@code TrustAnchor}, {@code AlgorithmConstraints},
* {@code Timestamp}, 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
* @throws IllegalArgumentException if the <code>anchor</code> is null * PKIXParameters is null, the current date is used. This
* should be null when jar files are being checked.
* @param jarTimestamp Timestamp passed for JAR timestamp constraint
* checking. Set to null if not applicable.
* @param variant is the Validator variants of the operation. A null value
* passed will set it to Validator.GENERIC.
*/ */
public AlgorithmChecker(TrustAnchor anchor, public AlgorithmChecker(TrustAnchor anchor,
AlgorithmConstraints constraints) { AlgorithmConstraints constraints, Date pkixdate,
Timestamp jarTimestamp, String variant) {
if (anchor == null) { if (anchor != null) {
throw new IllegalArgumentException( if (anchor.getTrustedCert() != null) {
"The trust anchor cannot be null"); this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
} // Check for anchor certificate restrictions
trustedMatch = checkFingerprint(anchor.getTrustedCert());
if (anchor.getTrustedCert() != null) { if (trustedMatch && debug != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); debug.println("trustedMatch = true");
// Check for anchor certificate restrictions }
trustedMatch = checkFingerprint(anchor.getTrustedCert()); } else {
if (trustedMatch && debug != null) { this.trustedPubKey = anchor.getCAPublicKey();
debug.println("trustedMatch = true");
} }
} else { } else {
this.trustedPubKey = anchor.getCAPublicKey(); this.trustedPubKey = null;
if (debug != null) {
debug.println("TrustAnchor is null, trustedMatch is false.");
}
} }
this.prevPubKey = trustedPubKey; this.prevPubKey = this.trustedPubKey;
this.constraints = constraints; this.constraints = (constraints == null ? certPathDefaultConstraints :
constraints);
// If we are checking jar files, set pkixdate the same as the timestamp
// for certificate checking
this.pkixdate = (jarTimestamp != null ? jarTimestamp.getTimestamp() :
pkixdate);
this.jarTimestamp = jarTimestamp;
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
}
/**
* Create a new {@code AlgorithmChecker} with the given {@code TrustAnchor},
* {@code PKIXParameter} date, and {@code varient}
*
* @param anchor the trust anchor selected to validate the target
* certificate
* @param pkixdate Date the constraints are checked against. The value is
* either the PKIXParameters date or null for the current date.
* @param variant is the Validator variants of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
public AlgorithmChecker(TrustAnchor anchor, Date pkixdate, String variant) {
this(anchor, certPathDefaultConstraints, pkixdate, null, variant);
} }
// Check this 'cert' for restrictions in the AnchorCertificates // Check this 'cert' for restrictions in the AnchorCertificates
...@@ -217,6 +259,28 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { ...@@ -217,6 +259,28 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
null, null, -1, PKIXReason.INVALID_KEY_USAGE); null, null, -1, PKIXReason.INVALID_KEY_USAGE);
} }
X509CertImpl x509Cert;
AlgorithmId algorithmId;
try {
x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
} catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
}
AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
PublicKey currPubKey = cert.getPublicKey();
String currSigAlg = ((X509Certificate)cert).getSigAlgName();
// Check the signature algorithm and parameters against constraints.
if (!constraints.permits(SIGNATURE_PRIMITIVE_SET, currSigAlg,
currSigAlgParams)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed on signature " +
"algorithm: " + currSigAlg, null, null, -1,
BasicReason.ALGORITHM_CONSTRAINED);
}
// Assume all key usage bits are set if key usage is not present // Assume all key usage bits are set if key usage is not present
Set<CryptoPrimitive> primitives = KU_PRIMITIVE_SET; Set<CryptoPrimitive> primitives = KU_PRIMITIVE_SET;
...@@ -253,101 +317,74 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { ...@@ -253,101 +317,74 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
} }
} }
PublicKey currPubKey = cert.getPublicKey(); ConstraintsParameters cp =
new ConstraintsParameters((X509Certificate)cert,
trustedMatch, pkixdate, jarTimestamp, variant);
// Check against local constraints if it is DisabledAlgorithmConstraints
if (constraints instanceof DisabledAlgorithmConstraints) { if (constraints instanceof DisabledAlgorithmConstraints) {
// Check against DisabledAlgorithmConstraints certpath constraints. ((DisabledAlgorithmConstraints)constraints).permits(currSigAlg, cp);
// permits() will throw exception on failure. // DisabledAlgorithmsConstraints does not check primitives, so key
((DisabledAlgorithmConstraints)constraints).permits(primitives, // additional key check.
new CertConstraintParameters((X509Certificate)cert,
trustedMatch));
// If there is no previous key, set one and exit
if (prevPubKey == null) {
prevPubKey = currPubKey;
return;
}
}
X509CertImpl x509Cert;
AlgorithmId algorithmId;
try {
x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
} catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
}
AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); } else {
String currSigAlg = x509Cert.getSigAlgName(); // Perform the default constraints checking anyway.
certPathDefaultConstraints.permits(currSigAlg, cp);
// If 'constraints' is not of DisabledAlgorithmConstraints, check all // Call locally set constraints to check key with primitives.
// everything individually if (!constraints.permits(primitives, currPubKey)) {
if (!(constraints instanceof DisabledAlgorithmConstraints)) {
// Check the current signature algorithm
if (!constraints.permits(
SIGNATURE_PRIMITIVE_SET,
currSigAlg, currSigAlgParams)) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
"Algorithm constraints check failed on signature " + "Algorithm constraints check failed on key " +
"algorithm: " + currSigAlg, null, null, -1, currPubKey.getAlgorithm() + " with size of " +
BasicReason.ALGORITHM_CONSTRAINED); sun.security.util.KeyUtil.getKeySize(currPubKey) +
"bits",
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
} }
if (!constraints.permits(primitives, currPubKey)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed on keysize: " +
sun.security.util.KeyUtil.getKeySize(currPubKey),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
} }
// If there is no previous key, set one and exit
if (prevPubKey == null) {
prevPubKey = currPubKey;
return;
} }
// Check with previous cert for signature algorithm and public key // Check with previous cert for signature algorithm and public key
if (prevPubKey != null) { if (!constraints.permits(
if (!constraints.permits( SIGNATURE_PRIMITIVE_SET,
SIGNATURE_PRIMITIVE_SET, currSigAlg, prevPubKey, currSigAlgParams)) {
currSigAlg, prevPubKey, currSigAlgParams)) { throw new CertPathValidatorException(
throw new CertPathValidatorException(
"Algorithm constraints check failed on " + "Algorithm constraints check failed on " +
"signature algorithm: " + currSigAlg, "signature algorithm: " + currSigAlg,
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
} }
// Inherit key parameters from previous key // Inherit key parameters from previous key
if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) {
// Inherit DSA parameters from previous key // Inherit DSA parameters from previous key
if (!(prevPubKey instanceof DSAPublicKey)) { if (!(prevPubKey instanceof DSAPublicKey)) {
throw new CertPathValidatorException("Input key is not " + throw new CertPathValidatorException("Input key is not " +
"of a appropriate type for inheriting parameters"); "of a appropriate type for inheriting parameters");
} }
DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
if (params == null) { if (params == null) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
"Key parameters missing from public key."); "Key parameters missing from public key.");
} }
try { try {
BigInteger y = ((DSAPublicKey)currPubKey).getY(); BigInteger y = ((DSAPublicKey)currPubKey).getY();
KeyFactory kf = KeyFactory.getInstance("DSA"); KeyFactory kf = KeyFactory.getInstance("DSA");
DSAPublicKeySpec ks = new DSAPublicKeySpec(y, DSAPublicKeySpec ks = new DSAPublicKeySpec(y, params.getP(),
params.getP(), params.getQ(), params.getG());
params.getQ(), currPubKey = kf.generatePublic(ks);
params.getG()); } catch (GeneralSecurityException e) {
currPubKey = kf.generatePublic(ks); throw new CertPathValidatorException("Unable to generate " +
} catch (GeneralSecurityException e) {
throw new CertPathValidatorException("Unable to generate " +
"key with inherited parameters: " + e.getMessage(), e); "key with inherited parameters: " + e.getMessage(), e);
}
} }
} }
// reset the previous public key // reset the previous public key
prevPubKey = currPubKey; prevPubKey = currPubKey;
// check the extended key usage, ignore the check now
// List<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage();
// DO NOT remove any unresolved critical extensions
} }
/** /**
...@@ -387,8 +424,10 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { ...@@ -387,8 +424,10 @@ final public 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
* passed will set it to Validator.GENERIC.
*/ */
static void check(PublicKey key, X509CRL crl) static void check(PublicKey key, X509CRL crl, String variant)
throws CertPathValidatorException { throws CertPathValidatorException {
X509CRLImpl x509CRLImpl = null; X509CRLImpl x509CRLImpl = null;
...@@ -399,28 +438,24 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { ...@@ -399,28 +438,24 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
} }
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId(); AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
check(key, algorithmId); check(key, algorithmId, variant);
} }
/** /**
* Check the signature algorithm with the specified public key. * Check the signature algorithm with the specified public key.
* *
* @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 algorithmId signature algorithm Algorithm ID
* @param variant is the Validator variants of the operation. A null value
* passed will set it to Validator.GENERIC.
*/ */
static void check(PublicKey key, AlgorithmId algorithmId) static void check(PublicKey key, AlgorithmId algorithmId, String variant)
throws CertPathValidatorException { throws CertPathValidatorException {
String sigAlgName = algorithmId.getName(); String sigAlgName = algorithmId.getName();
AlgorithmParameters sigAlgParams = algorithmId.getParameters(); AlgorithmParameters sigAlgParams = algorithmId.getParameters();
if (!certPathDefaultConstraints.permits( certPathDefaultConstraints.permits(new ConstraintsParameters(
SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) { sigAlgName, sigAlgParams, key, variant));
throw new CertPathValidatorException(
"Algorithm constraints check failed on signature algorithm: " +
sigAlgName + " is disabled",
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
} }
} }
/* /*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2017, 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 javax.security.auth.x500.X500Principal; ...@@ -33,6 +33,7 @@ import javax.security.auth.x500.X500Principal;
import java.util.*; import java.util.*;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.validator.Validator;
import static sun.security.x509.PKIXExtensions.*; import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.*; import sun.security.x509.*;
...@@ -65,6 +66,20 @@ public class DistributionPointFetcher { ...@@ -65,6 +66,20 @@ public class DistributionPointFetcher {
* Return the X509CRLs matching this selector. The selector must be * Return the X509CRLs matching this selector. The selector must be
* an X509CRLSelector with certificateChecking set. * an X509CRLSelector with certificateChecking set.
*/ */
public static Collection<X509CRL> getCRLs(X509CRLSelector selector,
boolean signFlag, PublicKey prevKey, String provider,
List<CertStore> certStores, boolean[] reasonsMask,
Set<TrustAnchor> trustAnchors, Date validity, String variant)
throws CertStoreException
{
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
reasonsMask, trustAnchors, validity, variant);
}
/**
* Return the X509CRLs matching this selector. The selector must be
* an X509CRLSelector with certificateChecking set.
*/
// Called by com.sun.deploy.security.RevocationChecker
public static Collection<X509CRL> getCRLs(X509CRLSelector selector, public static Collection<X509CRL> getCRLs(X509CRLSelector selector,
boolean signFlag, boolean signFlag,
PublicKey prevKey, PublicKey prevKey,
...@@ -76,7 +91,7 @@ public class DistributionPointFetcher { ...@@ -76,7 +91,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); reasonsMask, trustAnchors, validity, Validator.VAR_GENERIC);
} }
/** /**
...@@ -91,7 +106,8 @@ public class DistributionPointFetcher { ...@@ -91,7 +106,8 @@ public class DistributionPointFetcher {
List<CertStore> certStores, List<CertStore> certStores,
boolean[] reasonsMask, boolean[] reasonsMask,
Set<TrustAnchor> trustAnchors, Set<TrustAnchor> trustAnchors,
Date validity) Date validity,
String variant)
throws CertStoreException throws CertStoreException
{ {
X509Certificate cert = selector.getCertificateChecking(); X509Certificate cert = selector.getCertificateChecking();
...@@ -120,7 +136,7 @@ public class DistributionPointFetcher { ...@@ -120,7 +136,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); certStores, trustAnchors, validity, variant);
results.addAll(crls); results.addAll(crls);
} }
if (debug != null) { if (debug != null) {
...@@ -145,7 +161,7 @@ public class DistributionPointFetcher { ...@@ -145,7 +161,7 @@ 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) Set<TrustAnchor> trustAnchors, Date validity, String variant)
throws CertStoreException { throws CertStoreException {
// check for full name // check for full name
...@@ -208,7 +224,7 @@ public class DistributionPointFetcher { ...@@ -208,7 +224,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)) { trustAnchors, certStores, validity, variant)) {
crls.add(crl); crls.add(crl);
} }
} catch (IOException | CRLException e) { } catch (IOException | CRLException e) {
...@@ -317,7 +333,7 @@ public class DistributionPointFetcher { ...@@ -317,7 +333,7 @@ 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) throws CRLException, IOException { Date validity, String variant) throws CRLException, IOException {
if (debug != null) { if (debug != null) {
debug.println("DistributionPointFetcher.verifyCRL: " + debug.println("DistributionPointFetcher.verifyCRL: " +
...@@ -443,7 +459,7 @@ public class DistributionPointFetcher { ...@@ -443,7 +459,7 @@ public class DistributionPointFetcher {
} }
if (indirectCRL) { if (indirectCRL) {
if (pointCrlIssuers.size() != 1) { if (pointCrlIssuers.size() != 1) {
// RFC 3280: there must be only 1 CRL issuer // RFC 5280: there must be only 1 CRL issuer
// name when relativeName is present // name when relativeName is present
if (debug != null) { if (debug != null) {
debug.println("must only be one CRL " + debug.println("must only be one CRL " +
...@@ -664,7 +680,7 @@ public class DistributionPointFetcher { ...@@ -664,7 +680,7 @@ public class DistributionPointFetcher {
// check the crl signature algorithm // check the crl signature algorithm
try { try {
AlgorithmChecker.check(prevKey, crl); AlgorithmChecker.check(prevKey, crl, variant);
} 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);
......
/* /*
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2017, 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
...@@ -35,6 +35,7 @@ import java.security.cert.CertPathValidatorException; ...@@ -35,6 +35,7 @@ import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.CRLReason; import java.security.cert.CRLReason;
import java.security.cert.Extension; import java.security.cert.Extension;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
...@@ -42,14 +43,14 @@ import java.util.Date; ...@@ -42,14 +43,14 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static sun.security.provider.certpath.OCSPResponse.*;
import sun.security.action.GetIntegerAction; import sun.security.action.GetIntegerAction;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.util.ObjectIdentifier; import sun.security.validator.Validator;
import sun.security.x509.AccessDescription; import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityInfoAccessExtension;
import sun.security.x509.GeneralName; import sun.security.x509.GeneralName;
import sun.security.x509.GeneralNameInterface; import sun.security.x509.GeneralNameInterface;
import sun.security.x509.PKIXExtensions;
import sun.security.x509.URIName; import sun.security.x509.URIName;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
...@@ -65,9 +66,6 @@ import sun.security.x509.X509CertImpl; ...@@ -65,9 +66,6 @@ import sun.security.x509.X509CertImpl;
*/ */
public final class OCSP { public final class OCSP {
static final ObjectIdentifier NONCE_EXTENSION_OID =
ObjectIdentifier.newInternal(new int[]{ 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private static final int DEFAULT_CONNECT_TIMEOUT = 15000; private static final int DEFAULT_CONNECT_TIMEOUT = 15000;
...@@ -97,42 +95,6 @@ public final class OCSP { ...@@ -97,42 +95,6 @@ public final class OCSP {
private OCSP() {} private OCSP() {}
/**
* Obtains the revocation status of a certificate using OCSP using the most
* common defaults. The OCSP responder URI is retrieved from the
* certificate's AIA extension. The OCSP responder certificate is assumed
* to be the issuer's certificate (or issued by the issuer CA).
*
* @param cert the certificate to be checked
* @param issuerCert the issuer certificate
* @return the RevocationStatus
* @throws IOException if there is an exception connecting to or
* communicating with the OCSP responder
* @throws CertPathValidatorException if an exception occurs while
* encoding the OCSP Request or validating the OCSP Response
*/
public static RevocationStatus check(X509Certificate cert,
X509Certificate issuerCert)
throws IOException, CertPathValidatorException {
CertId certId = null;
URI responderURI = null;
try {
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
responderURI = getResponderURI(certImpl);
if (responderURI == null) {
throw new CertPathValidatorException
("No OCSP Responder URI in certificate");
}
certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
} catch (CertificateException | IOException e) {
throw new CertPathValidatorException
("Exception while encoding OCSPRequest", e);
}
OCSPResponse ocspResponse = check(Collections.singletonList(certId),
responderURI, issuerCert, null, null,
Collections.<Extension>emptyList());
return (RevocationStatus)ocspResponse.getSingleResponse(certId);
}
/** /**
* Obtains the revocation status of a certificate using OCSP. * Obtains the revocation status of a certificate using OCSP.
...@@ -149,6 +111,8 @@ public final class OCSP { ...@@ -149,6 +111,8 @@ public final class OCSP {
* @throws CertPathValidatorException if an exception occurs while * @throws CertPathValidatorException if an exception occurs while
* encoding the OCSP Request or validating the OCSP Response * encoding the OCSP Request or validating the OCSP Response
*/ */
// Called by com.sun.deploy.security.TrustDecider
public static RevocationStatus check(X509Certificate cert, public static RevocationStatus check(X509Certificate cert,
X509Certificate issuerCert, X509Certificate issuerCert,
URI responderURI, URI responderURI,
...@@ -157,18 +121,27 @@ public final class OCSP { ...@@ -157,18 +121,27 @@ 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()); Collections.<Extension>emptyList(), Validator.VAR_GENERIC);
} }
// Called by com.sun.deploy.security.TrustDecider
public static RevocationStatus check(X509Certificate cert, public static RevocationStatus check(X509Certificate cert,
X509Certificate issuerCert, X509Certificate issuerCert, URI responderURI,
URI responderURI, X509Certificate responderCert, Date date, List<Extension> extensions,
X509Certificate responderCert, String variant)
Date date, List<Extension> extensions)
throws IOException, CertPathValidatorException throws IOException, CertPathValidatorException
{ {
CertId certId = null; return check(cert, responderURI, null, issuerCert, responderCert, date,
extensions, variant);
}
public static RevocationStatus check(X509Certificate cert,
URI responderURI, TrustAnchor anchor, X509Certificate issuerCert,
X509Certificate responderCert, Date date,
List<Extension> extensions, String variant)
throws IOException, CertPathValidatorException
{
CertId certId;
try { try {
X509CertImpl certImpl = X509CertImpl.toImpl(cert); X509CertImpl certImpl = X509CertImpl.toImpl(cert);
certId = new CertId(issuerCert, certImpl.getSerialNumberObject()); certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
...@@ -177,19 +150,23 @@ public final class OCSP { ...@@ -177,19 +150,23 @@ public final class OCSP {
("Exception while encoding OCSPRequest", e); ("Exception while encoding OCSPRequest", e);
} }
OCSPResponse ocspResponse = check(Collections.singletonList(certId), OCSPResponse ocspResponse = check(Collections.singletonList(certId),
responderURI, issuerCert, responderCert, date, extensions); responderURI, new OCSPResponse.IssuerInfo(anchor, issuerCert),
responderCert, date, extensions, variant);
return (RevocationStatus) ocspResponse.getSingleResponse(certId); return (RevocationStatus) ocspResponse.getSingleResponse(certId);
} }
/** /**
* Checks the revocation status of a list of certificates using OCSP. * Checks the revocation status of a list of certificates using OCSP.
* *
* @param certs the CertIds to be checked * @param certIds the CertIds to be checked
* @param responderURI the URI of the OCSP responder * @param responderURI the URI of the OCSP responder
* @param issuerCert the issuer's certificate * @param issuerInfo the issuer's certificate and/or subject and public key
* @param responderCert the OCSP responder's certificate * @param responderCert the OCSP responder's certificate
* @param date the time the validity of the OCSP responder's certificate * @param date the time the validity of the OCSP responder's certificate
* should be checked against. If null, the current time is used. * should be checked against. If null, the current time is used.
* @param extensions zero or more OCSP extensions to be included in the
* request. If no extensions are requested, an empty {@code List} must
* be used. A {@code null} value is not allowed.
* @return the OCSPResponse * @return the OCSPResponse
* @throws IOException if there is an exception connecting to or * @throws IOException if there is an exception connecting to or
* communicating with the OCSP responder * communicating with the OCSP responder
...@@ -197,24 +174,59 @@ public final class OCSP { ...@@ -197,24 +174,59 @@ public final class OCSP {
* encoding the OCSP Request or validating the OCSP Response * encoding the OCSP Request or validating the OCSP Response
*/ */
static OCSPResponse check(List<CertId> certIds, URI responderURI, static OCSPResponse check(List<CertId> certIds, URI responderURI,
X509Certificate issuerCert, OCSPResponse.IssuerInfo issuerInfo,
X509Certificate responderCert, Date date, X509Certificate responderCert, Date date,
List<Extension> extensions) List<Extension> extensions, String variant)
throws IOException, CertPathValidatorException throws IOException, CertPathValidatorException
{ {
byte[] bytes = null; byte[] nonce = null;
OCSPRequest request = null; for (Extension ext : extensions) {
if (ext.getId().equals(PKIXExtensions.OCSPNonce_Id.toString())) {
nonce = ext.getValue();
}
}
OCSPResponse ocspResponse = null;
try { try {
request = new OCSPRequest(certIds, extensions); byte[] response = getOCSPBytes(certIds, responderURI, extensions);
bytes = request.encodeBytes(); ocspResponse = new OCSPResponse(response);
// verify the response
ocspResponse.verify(certIds, issuerInfo, responderCert, date,
nonce, variant);
} catch (IOException ioe) { } catch (IOException ioe) {
throw new CertPathValidatorException throw new CertPathValidatorException(
("Exception while encoding OCSPRequest", ioe); "Unable to determine revocation status due to network error",
ioe, null, -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
} }
return ocspResponse;
}
/**
* Send an OCSP request, then read and return the OCSP response bytes.
*
* @param certIds the CertIds to be checked
* @param responderURI the URI of the OCSP responder
* @param extensions zero or more OCSP extensions to be included in the
* request. If no extensions are requested, an empty {@code List} must
* be used. A {@code null} value is not allowed.
*
* @return the OCSP response bytes
*
* @throws IOException if there is an exception connecting to or
* communicating with the OCSP responder
*/
public static byte[] getOCSPBytes(List<CertId> certIds, URI responderURI,
List<Extension> extensions) throws IOException {
OCSPRequest request = new OCSPRequest(certIds, extensions);
byte[] bytes = request.encodeBytes();
InputStream in = null; InputStream in = null;
OutputStream out = null; OutputStream out = null;
byte[] response = null; byte[] response = null;
try { try {
URL url = responderURI.toURL(); URL url = responderURI.toURL();
if (debug != null) { if (debug != null) {
...@@ -257,10 +269,6 @@ public final class OCSP { ...@@ -257,10 +269,6 @@ public final class OCSP {
} }
} }
response = Arrays.copyOf(response, total); response = Arrays.copyOf(response, total);
} catch (IOException ioe) {
throw new CertPathValidatorException(
"Unable to determine revocation status due to network error",
ioe, null, -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
} finally { } finally {
if (in != null) { if (in != null) {
try { try {
...@@ -277,20 +285,7 @@ public final class OCSP { ...@@ -277,20 +285,7 @@ public final class OCSP {
} }
} }
} }
return response;
OCSPResponse ocspResponse = null;
try {
ocspResponse = new OCSPResponse(response);
} catch (IOException ioe) {
// response decoding exception
throw new CertPathValidatorException(ioe);
}
// verify the response
ocspResponse.verify(certIds, issuerCert, responderCert, date,
request.getNonce());
return ocspResponse;
} }
/** /**
...@@ -322,7 +317,7 @@ public final class OCSP { ...@@ -322,7 +317,7 @@ public final class OCSP {
List<AccessDescription> descriptions = aia.getAccessDescriptions(); List<AccessDescription> descriptions = aia.getAccessDescriptions();
for (AccessDescription description : descriptions) { for (AccessDescription description : descriptions) {
if (description.getAccessMethod().equals((Object) if (description.getAccessMethod().equals(
AccessDescription.Ad_OCSP_Id)) { AccessDescription.Ad_OCSP_Id)) {
GeneralName generalName = description.getAccessLocation(); GeneralName generalName = description.getAccessLocation();
......
/* /*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2017, 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
...@@ -32,10 +32,11 @@ import java.util.List; ...@@ -32,10 +32,11 @@ import java.util.List;
import sun.misc.HexDumpEncoder; import sun.misc.HexDumpEncoder;
import sun.security.util.*; import sun.security.util.*;
import sun.security.x509.PKIXExtensions;
/** /**
* This class can be used to generate an OCSP request and send it over * This class can be used to generate an OCSP request and send it over
* an outputstream. Currently we do not support signing requests * an output stream. Currently we do not support signing requests.
* The OCSP Request is specified in RFC 2560 and * The OCSP Request is specified in RFC 2560 and
* the ASN.1 definition is as follows: * the ASN.1 definition is as follows:
* <pre> * <pre>
...@@ -118,7 +119,8 @@ class OCSPRequest { ...@@ -118,7 +119,8 @@ class OCSPRequest {
DerOutputStream extOut = new DerOutputStream(); DerOutputStream extOut = new DerOutputStream();
for (Extension ext : extensions) { for (Extension ext : extensions) {
ext.encode(extOut); ext.encode(extOut);
if (ext.getId().equals(OCSP.NONCE_EXTENSION_OID.toString())) { if (ext.getId().equals(
PKIXExtensions.OCSPNonce_Id.toString())) {
nonce = ext.getValue(); nonce = ext.getValue();
} }
} }
......
/* /*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2017, 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
...@@ -41,6 +41,7 @@ import java.util.Date; ...@@ -41,6 +41,7 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import sun.misc.HexDumpEncoder; import sun.misc.HexDumpEncoder;
...@@ -129,7 +130,7 @@ public final class OCSPResponse { ...@@ -129,7 +130,7 @@ public final class OCSPResponse {
SIG_REQUIRED, // Must sign the request SIG_REQUIRED, // Must sign the request
UNAUTHORIZED // Request unauthorized UNAUTHORIZED // Request unauthorized
}; };
private static ResponseStatus[] rsvalues = ResponseStatus.values(); private static final ResponseStatus[] rsvalues = ResponseStatus.values();
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private static final boolean dump = debug != null && Debug.isOn("ocsp"); private static final boolean dump = debug != null && Debug.isOn("ocsp");
...@@ -173,7 +174,7 @@ public final class OCSPResponse { ...@@ -173,7 +174,7 @@ public final class OCSPResponse {
} }
// an array of all of the CRLReasons (used in SingleResponse) // an array of all of the CRLReasons (used in SingleResponse)
private static CRLReason[] values = CRLReason.values(); private static final CRLReason[] values = CRLReason.values();
private final ResponseStatus responseStatus; private final ResponseStatus responseStatus;
private final Map<CertId, SingleResponse> singleResponseMap; private final Map<CertId, SingleResponse> singleResponseMap;
...@@ -183,13 +184,16 @@ public final class OCSPResponse { ...@@ -183,13 +184,16 @@ public final class OCSPResponse {
private final byte[] responseNonce; private final byte[] responseNonce;
private List<X509CertImpl> certs; private List<X509CertImpl> certs;
private X509CertImpl signerCert = null; private X509CertImpl signerCert = null;
private X500Principal responderName = null; private final ResponderId respId;
private KeyIdentifier responderKeyId = null; private Date producedAtDate = null;
private final Map<String, java.security.cert.Extension> responseExtensions;
/* /*
* Create an OCSP response from its ASN.1 DER encoding. * Create an OCSP response from its ASN.1 DER encoding.
*
* @param bytes The DER-encoded bytes for an OCSP response
*/ */
OCSPResponse(byte[] bytes) throws IOException { public OCSPResponse(byte[] bytes) throws IOException {
if (dump) { if (dump) {
HexDumpEncoder hexEnc = new HexDumpEncoder(); HexDumpEncoder hexEnc = new HexDumpEncoder();
debug.println("OCSPResponse bytes...\n\n" + debug.println("OCSPResponse bytes...\n\n" +
...@@ -221,6 +225,8 @@ public final class OCSPResponse { ...@@ -221,6 +225,8 @@ public final class OCSPResponse {
signature = null; signature = null;
tbsResponseData = null; tbsResponseData = null;
responseNonce = null; responseNonce = null;
responseExtensions = Collections.emptyMap();
respId = null;
return; return;
} }
...@@ -289,27 +295,15 @@ public final class OCSPResponse { ...@@ -289,27 +295,15 @@ public final class OCSPResponse {
} }
// responderID // responderID
short tag = (byte)(seq.tag & 0x1f); respId = new ResponderId(seq.toByteArray());
if (tag == NAME_TAG) { if (debug != null) {
responderName = new X500Principal(seq.getData().toByteArray()); debug.println("Responder ID: " + respId);
if (debug != null) {
debug.println("Responder's name: " + responderName);
}
} else if (tag == KEY_TAG) {
responderKeyId = new KeyIdentifier(seq.getData().getOctetString());
if (debug != null) {
debug.println("Responder's key ID: " +
Debug.toString(responderKeyId.getIdentifier()));
}
} else {
throw new IOException("Bad encoding in responderID element of " +
"OCSP response: expected ASN.1 context specific tag 0 or 1");
} }
// producedAt // producedAt
seq = seqDerIn.getDerValue(); seq = seqDerIn.getDerValue();
producedAtDate = seq.getGeneralizedTime();
if (debug != null) { if (debug != null) {
Date producedAtDate = seq.getGeneralizedTime();
debug.println("OCSP response produced at: " + producedAtDate); debug.println("OCSP response produced at: " + producedAtDate);
} }
...@@ -320,37 +314,29 @@ public final class OCSPResponse { ...@@ -320,37 +314,29 @@ public final class OCSPResponse {
debug.println("OCSP number of SingleResponses: " debug.println("OCSP number of SingleResponses: "
+ singleResponseDer.length); + singleResponseDer.length);
} }
for (int i = 0; i < singleResponseDer.length; i++) { for (DerValue srDer : singleResponseDer) {
SingleResponse singleResponse = SingleResponse singleResponse = new SingleResponse(srDer);
new SingleResponse(singleResponseDer[i]);
singleResponseMap.put(singleResponse.getCertId(), singleResponse); singleResponseMap.put(singleResponse.getCertId(), singleResponse);
} }
// responseExtensions // responseExtensions
byte[] nonce = null; Map<String, java.security.cert.Extension> tmpExtMap = new HashMap<>();
if (seqDerIn.available() > 0) { if (seqDerIn.available() > 0) {
seq = seqDerIn.getDerValue(); seq = seqDerIn.getDerValue();
if (seq.isContextSpecific((byte)1)) { if (seq.isContextSpecific((byte)1)) {
DerValue[] responseExtDer = seq.data.getSequence(3); tmpExtMap = parseExtensions(seq);
for (int i = 0; i < responseExtDer.length; i++) {
Extension ext = new Extension(responseExtDer[i]);
if (debug != null) {
debug.println("OCSP extension: " + ext);
}
// Only the NONCE extension is recognized
if (ext.getExtensionId().equals((Object)
OCSP.NONCE_EXTENSION_OID))
{
nonce = ext.getExtensionValue();
} else if (ext.isCritical()) {
throw new IOException(
"Unsupported OCSP critical extension: " +
ext.getExtensionId());
}
}
} }
} }
responseNonce = nonce; responseExtensions = tmpExtMap;
// Attach the nonce value if found in the extension map
Extension nonceExt = (Extension)tmpExtMap.get(
PKIXExtensions.OCSPNonce_Id.toString());
responseNonce = (nonceExt != null) ?
nonceExt.getExtensionValue() : null;
if (debug != null && responseNonce != null) {
debug.println("Response nonce: " + Arrays.toString(responseNonce));
}
// signatureAlgorithmId // signatureAlgorithmId
sigAlgId = AlgorithmId.parse(seqTmp[1]); sigAlgId = AlgorithmId.parse(seqTmp[1]);
...@@ -387,8 +373,9 @@ public final class OCSPResponse { ...@@ -387,8 +373,9 @@ public final class OCSPResponse {
} }
} }
void verify(List<CertId> certIds, X509Certificate issuerCert, void verify(List<CertId> certIds, IssuerInfo issuerInfo,
X509Certificate responderCert, Date date, byte[] nonce) X509Certificate responderCert, Date date, byte[] nonce,
String variant)
throws CertPathValidatorException throws CertPathValidatorException
{ {
switch (responseStatus) { switch (responseStatus) {
...@@ -428,7 +415,9 @@ public final class OCSPResponse { ...@@ -428,7 +415,9 @@ public final class OCSPResponse {
// Add the Issuing CA cert and/or Trusted Responder cert to the list // Add the Issuing CA cert and/or Trusted Responder cert to the list
// of certs from the OCSP response // of certs from the OCSP response
try { try {
certs.add(X509CertImpl.toImpl(issuerCert)); if (issuerInfo.getCertificate() != null) {
certs.add(X509CertImpl.toImpl(issuerInfo.getCertificate()));
}
if (responderCert != null) { if (responderCert != null) {
certs.add(X509CertImpl.toImpl(responderCert)); certs.add(X509CertImpl.toImpl(responderCert));
} }
...@@ -437,20 +426,22 @@ public final class OCSPResponse { ...@@ -437,20 +426,22 @@ public final class OCSPResponse {
"Invalid issuer or trusted responder certificate", ce); "Invalid issuer or trusted responder certificate", ce);
} }
if (responderName != null) { if (respId.getType() == ResponderId.Type.BY_NAME) {
X500Principal rName = respId.getResponderName();
for (X509CertImpl cert : certs) { for (X509CertImpl cert : certs) {
if (cert.getSubjectX500Principal().equals(responderName)) { if (cert.getSubjectX500Principal().equals(rName)) {
signerCert = cert; signerCert = cert;
break; break;
} }
} }
} else if (responderKeyId != null) { } else if (respId.getType() == ResponderId.Type.BY_KEY) {
KeyIdentifier ridKeyId = respId.getKeyIdentifier();
for (X509CertImpl cert : certs) { for (X509CertImpl cert : certs) {
// Match responder's key identifier against the cert's SKID // Match responder's key identifier against the cert's SKID
// This will match if the SKID is encoded using the 160-bit // This will match if the SKID is encoded using the 160-bit
// SHA-1 hash method as defined in RFC 5280. // SHA-1 hash method as defined in RFC 5280.
KeyIdentifier certKeyId = cert.getSubjectKeyId(); KeyIdentifier certKeyId = cert.getSubjectKeyId();
if (certKeyId != null && responderKeyId.equals(certKeyId)) { if (certKeyId != null && ridKeyId.equals(certKeyId)) {
signerCert = cert; signerCert = cert;
break; break;
} else { } else {
...@@ -464,7 +455,7 @@ public final class OCSPResponse { ...@@ -464,7 +455,7 @@ public final class OCSPResponse {
} catch (IOException e) { } catch (IOException e) {
// ignore // ignore
} }
if (responderKeyId.equals(certKeyId)) { if (ridKeyId.equals(certKeyId)) {
signerCert = cert; signerCert = cert;
break; break;
} }
...@@ -476,7 +467,10 @@ public final class OCSPResponse { ...@@ -476,7 +467,10 @@ public final class OCSPResponse {
// Check whether the signer cert returned by the responder is trusted // Check whether the signer cert returned by the responder is trusted
if (signerCert != null) { if (signerCert != null) {
// Check if the response is signed by the issuing CA // Check if the response is signed by the issuing CA
if (signerCert.equals(issuerCert)) { if (signerCert.getSubjectX500Principal().equals(
issuerInfo.getName()) &&
signerCert.getPublicKey().equals(
issuerInfo.getPublicKey())) {
if (debug != null) { if (debug != null) {
debug.println("OCSP response is signed by the target's " + debug.println("OCSP response is signed by the target's " +
"Issuing CA"); "Issuing CA");
...@@ -493,7 +487,7 @@ public final class OCSPResponse { ...@@ -493,7 +487,7 @@ public final class OCSPResponse {
// Check if the response is signed by an authorized responder // Check if the response is signed by an authorized responder
} else if (signerCert.getIssuerX500Principal().equals( } else if (signerCert.getIssuerX500Principal().equals(
issuerCert.getSubjectX500Principal())) { issuerInfo.getName())) {
// Check for the OCSPSigning key purpose // Check for the OCSPSigning key purpose
try { try {
...@@ -513,8 +507,9 @@ public final class OCSPResponse { ...@@ -513,8 +507,9 @@ public final class OCSPResponse {
// Check algorithm constraints specified in security property // Check algorithm constraints specified in security property
// "jdk.certpath.disabledAlgorithms". // "jdk.certpath.disabledAlgorithms".
AlgorithmChecker algChecker = new AlgorithmChecker( AlgorithmChecker algChecker =
new TrustAnchor(issuerCert, null)); new AlgorithmChecker(issuerInfo.getAnchor(), date,
variant);
algChecker.init(false); algChecker.init(false);
algChecker.check(signerCert, Collections.<String>emptySet()); algChecker.check(signerCert, Collections.<String>emptySet());
...@@ -552,7 +547,7 @@ public final class OCSPResponse { ...@@ -552,7 +547,7 @@ public final class OCSPResponse {
// verify the signature // verify the signature
try { try {
signerCert.verify(issuerCert.getPublicKey()); signerCert.verify(issuerInfo.getPublicKey());
if (debug != null) { if (debug != null) {
debug.println("OCSP response is signed by an " + debug.println("OCSP response is signed by an " +
"Authorized Responder"); "Authorized Responder");
...@@ -574,7 +569,7 @@ public final class OCSPResponse { ...@@ -574,7 +569,7 @@ 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); AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId, variant);
if (!verifySignature(signerCert)) { if (!verifySignature(signerCert)) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
...@@ -593,7 +588,6 @@ public final class OCSPResponse { ...@@ -593,7 +588,6 @@ public final class OCSPResponse {
} }
// Check freshness of OCSPResponse // Check freshness of OCSPResponse
long now = (date == null) ? System.currentTimeMillis() : date.getTime(); long now = (date == null) ? System.currentTimeMillis() : date.getTime();
Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW); Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW); Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
...@@ -604,16 +598,16 @@ public final class OCSPResponse { ...@@ -604,16 +598,16 @@ public final class OCSPResponse {
until = " until " + sr.nextUpdate; until = " until " + sr.nextUpdate;
} }
debug.println("OCSP response validity interval is from " + debug.println("OCSP response validity interval is from " +
sr.thisUpdate + until); sr.thisUpdate + until);
debug.println("Checking validity of OCSP response on: " + debug.println("Checking validity of OCSP response on: " +
new Date(now)); new Date(now));
} }
// Check that the test date is within the validity interval: // Check that the test date is within the validity interval:
// [ thisUpdate - MAX_CLOCK_SKEW, // [ thisUpdate - MAX_CLOCK_SKEW,
// MAX(thisUpdate, nextUpdate) + MAX_CLOCK_SKEW ] // MAX(thisUpdate, nextUpdate) + MAX_CLOCK_SKEW ]
if (nowPlusSkew.before(sr.thisUpdate) || if (nowPlusSkew.before(sr.thisUpdate) ||
nowMinusSkew.after( nowMinusSkew.after(
sr.nextUpdate != null ? sr.nextUpdate : sr.thisUpdate)) sr.nextUpdate != null ? sr.nextUpdate : sr.thisUpdate))
{ {
throw new CertPathValidatorException( throw new CertPathValidatorException(
...@@ -625,8 +619,10 @@ public final class OCSPResponse { ...@@ -625,8 +619,10 @@ public final class OCSPResponse {
/** /**
* Returns the OCSP ResponseStatus. * Returns the OCSP ResponseStatus.
*
* @return the {@code ResponseStatus} for this OCSP response
*/ */
ResponseStatus getResponseStatus() { public ResponseStatus getResponseStatus() {
return responseStatus; return responseStatus;
} }
...@@ -664,11 +660,27 @@ public final class OCSPResponse { ...@@ -664,11 +660,27 @@ public final class OCSPResponse {
/** /**
* Returns the SingleResponse of the specified CertId, or null if * Returns the SingleResponse of the specified CertId, or null if
* there is no response for that CertId. * there is no response for that CertId.
*
* @param certId the {@code CertId} for a {@code SingleResponse} to be
* searched for in the OCSP response.
*
* @return the {@code SingleResponse} for the provided {@code CertId},
* or {@code null} if it is not found.
*/ */
SingleResponse getSingleResponse(CertId certId) { public SingleResponse getSingleResponse(CertId certId) {
return singleResponseMap.get(certId); return singleResponseMap.get(certId);
} }
/**
* Return a set of all CertIds in this {@code OCSPResponse}
*
* @return an unmodifiable set containing every {@code CertId} in this
* response.
*/
public Set<CertId> getCertIds() {
return Collections.unmodifiableSet(singleResponseMap.keySet());
}
/* /*
* Returns the certificate for the authority that signed the OCSP response. * Returns the certificate for the authority that signed the OCSP response.
*/ */
...@@ -676,10 +688,86 @@ public final class OCSPResponse { ...@@ -676,10 +688,86 @@ public final class OCSPResponse {
return signerCert; // set in verify() return signerCert; // set in verify()
} }
/**
* Get the {@code ResponderId} from this {@code OCSPResponse}
*
* @return the {@code ResponderId} from this response or {@code null}
* if no responder ID is in the body of the response (e.g. a
* response with a status other than SUCCESS.
*/
public ResponderId getResponderId() {
return respId;
}
/**
* Provide a String representation of an OCSPResponse
*
* @return a human-readable representation of the OCSPResponse
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("OCSP Response:\n");
sb.append("Response Status: ").append(responseStatus).append("\n");
sb.append("Responder ID: ").append(respId).append("\n");
sb.append("Produced at: ").append(producedAtDate).append("\n");
int count = singleResponseMap.size();
sb.append(count).append(count == 1 ?
" response:\n" : " responses:\n");
for (SingleResponse sr : singleResponseMap.values()) {
sb.append(sr).append("\n");
}
if (responseExtensions != null && responseExtensions.size() > 0) {
count = responseExtensions.size();
sb.append(count).append(count == 1 ?
" extension:\n" : " extensions:\n");
for (String extId : responseExtensions.keySet()) {
sb.append(responseExtensions.get(extId)).append("\n");
}
}
return sb.toString();
}
/**
* Build a String-Extension map from DER encoded data.
* @param derVal A {@code DerValue} object built from a SEQUENCE of
* extensions
*
* @return a {@code Map} using the OID in string form as the keys. If no
* extensions are found or an empty SEQUENCE is passed in, then
* an empty {@code Map} will be returned.
*
* @throws IOException if any decoding errors occur.
*/
private static Map<String, java.security.cert.Extension>
parseExtensions(DerValue derVal) throws IOException {
DerValue[] extDer = derVal.data.getSequence(3);
Map<String, java.security.cert.Extension> extMap =
new HashMap<>(extDer.length);
for (DerValue extDerVal : extDer) {
Extension ext = new Extension(extDerVal);
if (debug != null) {
debug.println("Extension: " + ext);
}
// We don't support any extensions yet. Therefore, if it
// is critical we must throw an exception because we
// don't know how to process it.
if (ext.isCritical()) {
throw new IOException("Unsupported OCSP critical extension: " +
ext.getExtensionId());
}
extMap.put(ext.getId(), ext);
}
return extMap;
}
/* /*
* A class representing a single OCSP response. * A class representing a single OCSP response.
*/ */
final static class SingleResponse implements OCSP.RevocationStatus { public static final class SingleResponse implements OCSP.RevocationStatus {
private final CertId certId; private final CertId certId;
private final CertStatus certStatus; private final CertStatus certStatus;
private final Date thisUpdate; private final Date thisUpdate;
...@@ -724,7 +812,7 @@ public final class OCSPResponse { ...@@ -724,7 +812,7 @@ public final class OCSPResponse {
} }
} else { } else {
revocationTime = null; revocationTime = null;
revocationReason = CRLReason.UNSPECIFIED; revocationReason = null;
if (tag == CERT_STATUS_GOOD) { if (tag == CERT_STATUS_GOOD) {
certStatus = CertStatus.GOOD; certStatus = CertStatus.GOOD;
} else if (tag == CERT_STATUS_UNKNOWN) { } else if (tag == CERT_STATUS_UNKNOWN) {
...@@ -735,77 +823,131 @@ public final class OCSPResponse { ...@@ -735,77 +823,131 @@ public final class OCSPResponse {
} }
thisUpdate = tmp.getGeneralizedTime(); thisUpdate = tmp.getGeneralizedTime();
if (debug != null) {
debug.println("thisUpdate: " + thisUpdate);
}
if (tmp.available() == 0) { // Parse optional fields like nextUpdate and singleExtensions
// we are done Date tmpNextUpdate = null;
nextUpdate = null; Map<String, java.security.cert.Extension> tmpMap = null;
} else {
// Check for the first optional item, it could be nextUpdate
// [CONTEXT 0] or singleExtensions [CONTEXT 1]
if (tmp.available() > 0) {
derVal = tmp.getDerValue(); derVal = tmp.getDerValue();
tag = (byte)(derVal.tag & 0x1f);
if (tag == 0) {
// next update
nextUpdate = derVal.data.getGeneralizedTime();
if (tmp.available() == 0) { // nextUpdate processing
// we are done if (derVal.isContextSpecific((byte)0)) {
} else { tmpNextUpdate = derVal.data.getGeneralizedTime();
derVal = tmp.getDerValue(); if (debug != null) {
tag = (byte)(derVal.tag & 0x1f); debug.println("nextUpdate: " + tmpNextUpdate);
} }
} else {
nextUpdate = null; // If more data exists in the singleResponse, it
// can only be singleExtensions. Get this DER value
// for processing in the next block
derVal = tmp.available() > 0 ? tmp.getDerValue() : null;
} }
}
// singleExtensions // singleExtensions processing
if (tmp.available() > 0) { if (derVal != null) {
derVal = tmp.getDerValue(); if (derVal.isContextSpecific((byte)1)) {
if (derVal.isContextSpecific((byte)1)) { tmpMap = parseExtensions(derVal);
DerValue[] singleExtDer = derVal.data.getSequence(3);
singleExtensions = // There should not be any other items in the
new HashMap<String, java.security.cert.Extension> // singleResponse at this point.
(singleExtDer.length); if (tmp.available() > 0) {
for (int i = 0; i < singleExtDer.length; i++) { throw new IOException(tmp.available() +
Extension ext = new Extension(singleExtDer[i]); " bytes of additional data in singleResponse");
if (debug != null) {
debug.println("OCSP single extension: " + ext);
}
// We don't support any extensions yet. Therefore, if it
// is critical we must throw an exception because we
// don't know how to process it.
if (ext.isCritical()) {
throw new IOException(
"Unsupported OCSP critical extension: " +
ext.getExtensionId());
} }
singleExtensions.put(ext.getId(), ext); } else {
// Unknown item in the singleResponse
throw new IOException("Unsupported singleResponse " +
"item, tag = " + String.format("%02X", derVal.tag));
} }
} else {
singleExtensions = Collections.emptyMap();
} }
} else { }
singleExtensions = Collections.emptyMap();
nextUpdate = tmpNextUpdate;
singleExtensions = (tmpMap != null) ? tmpMap :
Collections.emptyMap();
if (debug != null) {
for (java.security.cert.Extension ext :
singleExtensions.values()) {
debug.println("singleExtension: " + ext);
}
} }
} }
/* /*
* Return the certificate's revocation status code * Return the certificate's revocation status code
*/ */
@Override public CertStatus getCertStatus() { @Override
public CertStatus getCertStatus() {
return certStatus; return certStatus;
} }
private CertId getCertId() { /**
* Get the Cert ID that this SingleResponse is for.
*
* @return the {@code CertId} for this {@code SingleResponse}
*/
public CertId getCertId() {
return certId; return certId;
} }
@Override public Date getRevocationTime() { /**
return (Date) revocationTime.clone(); * Get the {@code thisUpdate} field from this {@code SingleResponse}.
*
* @return a {@link Date} object containing the thisUpdate date
*/
public Date getThisUpdate() {
return (thisUpdate != null ? (Date) thisUpdate.clone() : null);
} }
@Override public CRLReason getRevocationReason() { /**
* Get the {@code nextUpdate} field from this {@code SingleResponse}.
*
* @return a {@link Date} object containing the nexUpdate date or
* {@code null} if a nextUpdate field is not present in the response.
*/
public Date getNextUpdate() {
return (nextUpdate != null ? (Date) nextUpdate.clone() : null);
}
/**
* Get the {@code revocationTime} field from this
* {@code SingleResponse}.
*
* @return a {@link Date} object containing the revocationTime date or
* {@code null} if the {@code SingleResponse} does not have a status
* of {@code REVOKED}.
*/
@Override
public Date getRevocationTime() {
return (revocationTime != null ? (Date) revocationTime.clone() :
null);
}
/**
* Get the {@code revocationReason} field for the
* {@code SingleResponse}.
*
* @return a {@link CRLReason} containing the revocation reason, or
* {@code null} if a revocation reason was not provided or the
* response status is not {@code REVOKED}.
*/
@Override
public CRLReason getRevocationReason() {
return revocationReason; return revocationReason;
} }
/**
* Get the {@code singleExtensions} for this {@code SingleResponse}.
*
* @return a {@link Map} of {@link Extension} objects, keyed by
* their OID value in string form.
*/
@Override @Override
public Map<String, java.security.cert.Extension> getSingleExtensions() { public Map<String, java.security.cert.Extension> getSingleExtensions() {
return Collections.unmodifiableMap(singleExtensions); return Collections.unmodifiableMap(singleExtensions);
...@@ -816,17 +958,116 @@ public final class OCSPResponse { ...@@ -816,17 +958,116 @@ public final class OCSPResponse {
*/ */
@Override public String toString() { @Override public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("SingleResponse: \n"); sb.append("SingleResponse:\n");
sb.append(certId); sb.append(certId);
sb.append("\nCertStatus: "+ certStatus + "\n"); sb.append("\nCertStatus: ").append(certStatus).append("\n");
if (certStatus == CertStatus.REVOKED) { if (certStatus == CertStatus.REVOKED) {
sb.append("revocationTime is " + revocationTime + "\n"); sb.append("revocationTime is ");
sb.append("revocationReason is " + revocationReason + "\n"); sb.append(revocationTime).append("\n");
sb.append("revocationReason is ");
sb.append(revocationReason).append("\n");
} }
sb.append("thisUpdate is " + thisUpdate + "\n"); sb.append("thisUpdate is ").append(thisUpdate).append("\n");
if (nextUpdate != null) { if (nextUpdate != null) {
sb.append("nextUpdate is " + nextUpdate + "\n"); sb.append("nextUpdate is ").append(nextUpdate).append("\n");
}
for (java.security.cert.Extension ext : singleExtensions.values()) {
sb.append("singleExtension: ");
sb.append(ext.toString()).append("\n");
}
return sb.toString();
}
}
/**
* Helper class that allows consumers to pass in issuer information. This
* will always consist of the issuer's name and public key, but may also
* contain a certificate if the originating data is in that form. The
* trust anchor for the certificate chain will be included for certpath
* disabled algorithm checking.
*/
static final class IssuerInfo {
private final TrustAnchor anchor;
private final X509Certificate certificate;
private final X500Principal name;
private final PublicKey pubKey;
IssuerInfo(TrustAnchor anchor) {
this(anchor, (anchor != null) ? anchor.getTrustedCert() : null);
}
IssuerInfo(X509Certificate issuerCert) {
this(null, issuerCert);
}
IssuerInfo(TrustAnchor anchor, X509Certificate issuerCert) {
if (anchor == null && issuerCert == null) {
throw new NullPointerException("TrustAnchor and issuerCert " +
"cannot be null");
}
this.anchor = anchor;
if (issuerCert != null) {
name = issuerCert.getSubjectX500Principal();
pubKey = issuerCert.getPublicKey();
certificate = issuerCert;
} else {
name = anchor.getCA();
pubKey = anchor.getCAPublicKey();
certificate = anchor.getTrustedCert();
} }
}
/**
* Get the certificate in this IssuerInfo if present.
*
* @return the {@code X509Certificate} used to create this IssuerInfo
* object, or {@code null} if a certificate was not used in its
* creation.
*/
X509Certificate getCertificate() {
return certificate;
}
/**
* Get the name of this issuer.
*
* @return an {@code X500Principal} corresponding to this issuer's
* name. If derived from an issuer's {@code X509Certificate} this
* would be equivalent to the certificate subject name.
*/
X500Principal getName() {
return name;
}
/**
* Get the public key for this issuer.
*
* @return a {@code PublicKey} for this issuer.
*/
PublicKey getPublicKey() {
return pubKey;
}
/**
* Get the TrustAnchor for the certificate chain.
*
* @return a {@code TrustAnchor}.
*/
TrustAnchor getAnchor() {
return anchor;
}
/**
* Create a string representation of this IssuerInfo.
*
* @return a {@code String} form of this IssuerInfo object.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Issuer Info:\n");
sb.append("Name: ").append(name.toString()).append("\n");
sb.append("Public Key:\n").append(pubKey.toString()).append("\n");
return sb.toString(); return sb.toString();
} }
} }
......
/* /*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2017, 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
...@@ -26,6 +26,7 @@ package sun.security.provider.certpath; ...@@ -26,6 +26,7 @@ package sun.security.provider.certpath;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.Timestamp;
import java.security.cert.*; import java.security.cert.*;
import java.security.interfaces.DSAPublicKey; import java.security.interfaces.DSAPublicKey;
import java.util.*; import java.util.*;
...@@ -85,6 +86,8 @@ class PKIX { ...@@ -85,6 +86,8 @@ class PKIX {
private CertSelector constraints; private CertSelector constraints;
private Set<TrustAnchor> anchors; private Set<TrustAnchor> anchors;
private List<X509Certificate> certs; private List<X509Certificate> certs;
private Timestamp timestamp;
private String variant;
ValidatorParams(CertPath cp, PKIXParameters params) ValidatorParams(CertPath cp, PKIXParameters params)
throws InvalidAlgorithmParameterException throws InvalidAlgorithmParameterException
...@@ -100,6 +103,11 @@ class PKIX { ...@@ -100,6 +103,11 @@ class PKIX {
ValidatorParams(PKIXParameters params) ValidatorParams(PKIXParameters params)
throws InvalidAlgorithmParameterException throws InvalidAlgorithmParameterException
{ {
if (params instanceof PKIXExtendedParameters) {
timestamp = ((PKIXExtendedParameters) params).getTimestamp();
variant = ((PKIXExtendedParameters) params).getVariant();
}
this.anchors = params.getTrustAnchors(); this.anchors = params.getTrustAnchors();
// Make sure that none of the trust anchors include name constraints // Make sure that none of the trust anchors include name constraints
// (not supported). // (not supported).
...@@ -189,6 +197,14 @@ class PKIX { ...@@ -189,6 +197,14 @@ class PKIX {
PKIXParameters getPKIXParameters() { PKIXParameters getPKIXParameters() {
return params; return params;
} }
Timestamp timestamp() {
return timestamp;
}
String variant() {
return variant;
}
} }
static class BuilderParams extends ValidatorParams { static class BuilderParams extends ValidatorParams {
......
/* /*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2017, 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
...@@ -172,7 +172,8 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi { ...@@ -172,7 +172,8 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>(); List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
// 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)); certPathCheckers.add(new AlgorithmChecker(anchor, null, params.date(),
params.timestamp(), 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));
...@@ -189,8 +190,11 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi { ...@@ -189,8 +190,11 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
rootNode); rootNode);
certPathCheckers.add(pc); certPathCheckers.add(pc);
// default value for date is current time // default value for date is current time
BasicChecker bc = new BasicChecker(anchor, params.date(), BasicChecker bc;
params.sigProvider(), false); bc = new BasicChecker(anchor,
(params.timestamp() == null ? params.date() :
params.timestamp().getTimestamp()),
params.sigProvider(), false);
certPathCheckers.add(bc); certPathCheckers.add(bc);
boolean revCheckerAdded = false; boolean revCheckerAdded = false;
......
/*
* Copyright (c) 2016, 2017, 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.InvalidAlgorithmParameterException;
import java.security.Timestamp;
import java.security.cert.CertSelector;
import java.security.cert.CertStore;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.TrustAnchor;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* This class is a wrapper for PKIXBuilderParameters so that a Timestamp object
* and a string for the variant type, can be passed when doing certpath
* checking.
*/
public class PKIXExtendedParameters extends PKIXBuilderParameters {
private final PKIXBuilderParameters p;
private Timestamp jarTimestamp;
private final String variant;
public PKIXExtendedParameters(PKIXBuilderParameters params,
Timestamp timestamp, String variant)
throws InvalidAlgorithmParameterException {
super(params.getTrustAnchors(), null);
p = params;
jarTimestamp = timestamp;
this.variant = variant;
}
public Timestamp getTimestamp() {
return jarTimestamp;
}
public void setTimestamp(Timestamp t) {
jarTimestamp = t;
}
public String getVariant() {
return variant;
}
@Override
public void setDate(Date d) {
p.setDate(d);
}
@Override
public void addCertPathChecker(PKIXCertPathChecker c) {
p.addCertPathChecker(c);
}
@Override
public void setMaxPathLength(int maxPathLength) {
p.setMaxPathLength(maxPathLength);
}
@Override
public int getMaxPathLength() {
return p.getMaxPathLength();
}
@Override
public String toString() {
return p.toString();
}
@Override
public Set<TrustAnchor> getTrustAnchors() {
return p.getTrustAnchors();
}
@Override
public void setTrustAnchors(Set<TrustAnchor> trustAnchors)
throws InvalidAlgorithmParameterException {
// To avoid problems with PKIXBuilderParameter's constructors
if (p == null) {
return;
}
p.setTrustAnchors(trustAnchors);
}
@Override
public Set<String> getInitialPolicies() {
return p.getInitialPolicies();
}
@Override
public void setInitialPolicies(Set<String> initialPolicies) {
p.setInitialPolicies(initialPolicies);
}
@Override
public void setCertStores(List<CertStore> stores) {
p.setCertStores(stores);
}
@Override
public void addCertStore(CertStore store) {
p.addCertStore(store);
}
@Override
public List<CertStore> getCertStores() {
return p.getCertStores();
}
@Override
public void setRevocationEnabled(boolean val) {
p.setRevocationEnabled(val);
}
@Override
public boolean isRevocationEnabled() {
return p.isRevocationEnabled();
}
@Override
public void setExplicitPolicyRequired(boolean val) {
p.setExplicitPolicyRequired(val);
}
@Override
public boolean isExplicitPolicyRequired() {
return p.isExplicitPolicyRequired();
}
@Override
public void setPolicyMappingInhibited(boolean val) {
p.setPolicyMappingInhibited(val);
}
@Override
public boolean isPolicyMappingInhibited() {
return p.isPolicyMappingInhibited();
}
@Override
public void setAnyPolicyInhibited(boolean val) {
p.setAnyPolicyInhibited(val);
}
@Override
public boolean isAnyPolicyInhibited() {
return p.isAnyPolicyInhibited();
}
@Override
public void setPolicyQualifiersRejected(boolean qualifiersRejected) {
p.setPolicyQualifiersRejected(qualifiersRejected);
}
@Override
public boolean getPolicyQualifiersRejected() {
return p.getPolicyQualifiersRejected();
}
@Override
public Date getDate() {
return p.getDate();
}
@Override
public void setCertPathCheckers(List<PKIXCertPathChecker> checkers) {
p.setCertPathCheckers(checkers);
}
@Override
public List<PKIXCertPathChecker> getCertPathCheckers() {
return p.getCertPathCheckers();
}
@Override
public String getSigProvider() {
return p.getSigProvider();
}
@Override
public void setSigProvider(String sigProvider) {
p.setSigProvider(sigProvider);
}
@Override
public CertSelector getTargetCertConstraints() {
return p.getTargetCertConstraints();
}
@Override
public void setTargetCertConstraints(CertSelector selector) {
// To avoid problems with PKIXBuilderParameter's constructors
if (p == null) {
return;
}
p.setTargetCertConstraints(selector);
}
}
/*
* Copyright (c) 2015, 2017 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.util.Arrays;
import java.io.IOException;
import java.security.PublicKey;
import javax.security.auth.x500.X500Principal;
import sun.security.x509.KeyIdentifier;
import sun.security.util.DerValue;
/**
* Class for ResponderId entities as described in RFC6960. ResponderId objects
* are used to uniquely identify OCSP responders.
* <p>
* The RFC 6960 defines a ResponderID structure as:
* <pre>
* ResponderID ::= CHOICE {
* byName [1] Name,
* byKey [2] KeyHash }
*
* KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
* (excluding the tag and length fields)
*
* Name is defined in RFC 5280.
* </pre>
*
* @see ResponderId.Type
* @since 9
*/
public final class ResponderId {
/**
* A {@code ResponderId} enumeration describing the accepted forms for a
* {@code ResponderId}.
*
* @see ResponderId
* @since 9
*/
public static enum Type {
/**
* A BY_NAME {@code ResponderId} will be built from a subject name,
* either as an {@code X500Principal} or a DER-encoded byte array.
*/
BY_NAME(1, "byName"),
/**
* A BY_KEY {@code ResponderId} will be built from a public key
* identifier, either derived from a {@code PublicKey} or directly
* from a DER-encoded byte array containing the key identifier.
*/
BY_KEY(2, "byKey");
private final int tagNumber;
private final String ridTypeName;
private Type(int value, String name) {
this.tagNumber = value;
this.ridTypeName = name;
}
public int value() {
return tagNumber;
}
@Override
public String toString() {
return ridTypeName;
}
}
private Type type;
private X500Principal responderName;
private KeyIdentifier responderKeyId;
private byte[] encodedRid;
/**
* Constructs a {@code ResponderId} object using an {@code X500Principal}.
* When encoded in DER this object will use the BY_NAME option.
*
* @param subjectName the subject name of the certificate used
* to sign OCSP responses.
*
* @throws IOException if the internal DER-encoding of the
* {@code X500Principal} fails.
*/
public ResponderId(X500Principal subjectName) throws IOException {
responderName = subjectName;
responderKeyId = null;
encodedRid = principalToBytes();
type = Type.BY_NAME;
}
/**
* Constructs a {@code ResponderId} object using a {@code PublicKey}.
* When encoded in DER this object will use the byKey option, a
* SHA-1 hash of the responder's public key.
*
* @param pubKey the the OCSP responder's public key
*
* @throws IOException if the internal DER-encoding of the
* {@code KeyIdentifier} fails.
*/
public ResponderId(PublicKey pubKey) throws IOException {
responderKeyId = new KeyIdentifier(pubKey);
responderName = null;
encodedRid = keyIdToBytes();
type = Type.BY_KEY;
}
/**
* Constructs a {@code ResponderId} object from its DER-encoding.
*
* @param encodedData the DER-encoded bytes
*
* @throws IOException if the encodedData is not properly DER encoded
*/
public ResponderId(byte[] encodedData) throws IOException {
DerValue outer = new DerValue(encodedData);
if (outer.isContextSpecific((byte)Type.BY_NAME.value())
&& outer.isConstructed()) {
// Use the X500Principal constructor as a way to sanity
// check the incoming data.
responderName = new X500Principal(outer.getDataBytes());
encodedRid = principalToBytes();
type = Type.BY_NAME;
} else if (outer.isContextSpecific((byte)Type.BY_KEY.value())
&& outer.isConstructed()) {
// Use the KeyIdentifier constructor as a way to sanity
// check the incoming data.
responderKeyId =
new KeyIdentifier(new DerValue(outer.getDataBytes()));
encodedRid = keyIdToBytes();
type = Type.BY_KEY;
} else {
throw new IOException("Invalid ResponderId content");
}
}
/**
* Encode a {@code ResponderId} in DER form
*
* @return a byte array containing the DER-encoded representation for this
* {@code ResponderId}
*/
public byte[] getEncoded() {
return encodedRid.clone();
}
/**
* Return the type of {@ResponderId}
*
* @return a number corresponding to the context-specific tag number
* used in the DER-encoding for a {@code ResponderId}
*/
public ResponderId.Type getType() {
return type;
}
/**
* Get the length of the encoded {@code ResponderId} (including the tag and
* length of the explicit tagging from the outer ASN.1 CHOICE).
*
* @return the length of the encoded {@code ResponderId}
*/
public int length() {
return encodedRid.length;
}
/**
* Obtain the underlying {@code X500Principal} from a {@code ResponderId}
*
* @return the {@code X500Principal} for this {@code ResponderId} if it
* is a BY_NAME variant. If the {@code ResponderId} is a BY_KEY
* variant, this routine will return {@code null}.
*/
public X500Principal getResponderName() {
return responderName;
}
/**
* Obtain the underlying key identifier from a {@code ResponderId}
*
* @return the {@code KeyIdentifier} for this {@code ResponderId} if it
* is a BY_KEY variant. If the {@code ResponderId} is a BY_NAME
* variant, this routine will return {@code null}.
*/
public KeyIdentifier getKeyIdentifier() {
return responderKeyId;
}
/**
* Compares the specified object with this {@code ResponderId} for equality.
* A ResponderId will only be considered equivalent if both the type and
* data value are equal. Two ResponderIds initialized by name and
* key ID, respectively, will not be equal even if the
* ResponderId objects are created from the same source certificate.
*
* @param obj the object to be compared against
*
* @return true if the specified object is equal to this {@code Responderid}
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (obj instanceof ResponderId) {
ResponderId respObj = (ResponderId)obj;
return Arrays.equals(encodedRid, respObj.getEncoded());
}
return false;
}
/**
* Returns the hash code value for this {@code ResponderId}
*
* @return the hash code value for this {@code ResponderId}
*/
@Override
public int hashCode() {
return Arrays.hashCode(encodedRid);
}
/**
* Create a String representation of this {@code ResponderId}
*
* @return a String representation of this {@code ResponderId}
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
switch (type) {
case BY_NAME:
sb.append(type).append(": ").append(responderName);
break;
case BY_KEY:
sb.append(type).append(": ");
for (byte keyIdByte : responderKeyId.getIdentifier()) {
sb.append(String.format("%02X", keyIdByte));
}
break;
default:
sb.append("Unknown ResponderId Type: ").append(type);
}
return sb.toString();
}
/**
* Convert the responderName data member into its DER-encoded form
*
* @return the DER encoding for a responder ID byName option, including
* explicit context-specific tagging.
*
* @throws IOException if any encoding error occurs
*/
private byte[] principalToBytes() throws IOException {
DerValue dv = new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte)Type.BY_NAME.value()),
responderName.getEncoded());
return dv.toByteArray();
}
/**
* Convert the responderKeyId data member into its DER-encoded form
*
* @return the DER encoding for a responder ID byKey option, including
* explicit context-specific tagging.
*
* @throws IOException if any encoding error occurs
*/
private byte[] keyIdToBytes() throws IOException {
// Place the KeyIdentifier bytes into an OCTET STRING
DerValue inner = new DerValue(DerValue.tag_OctetString,
responderKeyId.getIdentifier());
// Mark the OCTET STRING-wrapped KeyIdentifier bytes
// as EXPLICIT CONTEXT 2
DerValue outer = new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte)Type.BY_KEY.value()), inner.toByteArray());
return outer.toByteArray();
}
}
/* /*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2017, 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
...@@ -43,7 +43,6 @@ import javax.security.auth.x500.X500Principal; ...@@ -43,7 +43,6 @@ import javax.security.auth.x500.X500Principal;
import static sun.security.provider.certpath.OCSP.*; import static sun.security.provider.certpath.OCSP.*;
import static sun.security.provider.certpath.PKIX.*; import static sun.security.provider.certpath.PKIX.*;
import sun.security.action.GetPropertyAction;
import sun.security.x509.*; import sun.security.x509.*;
import static sun.security.x509.PKIXExtensions.*; import static sun.security.x509.PKIXExtensions.*;
import sun.security.util.Debug; import sun.security.util.Debug;
...@@ -62,12 +61,12 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -62,12 +61,12 @@ class RevocationChecker extends PKIXRevocationChecker {
private List<CertStore> certStores; private List<CertStore> certStores;
private Map<X509Certificate, byte[]> ocspResponses; private Map<X509Certificate, byte[]> ocspResponses;
private List<Extension> ocspExtensions; private List<Extension> ocspExtensions;
private boolean legacy; private final boolean legacy;
private LinkedList<CertPathValidatorException> softFailExceptions = private LinkedList<CertPathValidatorException> softFailExceptions =
new LinkedList<>(); new LinkedList<>();
// state variables // state variables
private X509Certificate issuerCert; private OCSPResponse.IssuerInfo issuerInfo;
private PublicKey prevPubKey; private PublicKey prevPubKey;
private boolean crlSignFlag; private boolean crlSignFlag;
private int certIndex; private int certIndex;
...@@ -302,9 +301,9 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -302,9 +301,9 @@ class RevocationChecker extends PKIXRevocationChecker {
CertPathValidatorException("forward checking not supported"); CertPathValidatorException("forward checking not supported");
} }
if (anchor != null) { if (anchor != null) {
issuerCert = anchor.getTrustedCert(); issuerInfo = new OCSPResponse.IssuerInfo(anchor);
prevPubKey = (issuerCert != null) ? issuerCert.getPublicKey() prevPubKey = issuerInfo.getPublicKey();
: anchor.getCAPublicKey();
} }
crlSignFlag = true; crlSignFlag = true;
if (params != null && params.certPath() != null) { if (params != null && params.certPath() != null) {
...@@ -438,7 +437,7 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -438,7 +437,7 @@ class RevocationChecker extends PKIXRevocationChecker {
private void updateState(X509Certificate cert) private void updateState(X509Certificate cert)
throws CertPathValidatorException throws CertPathValidatorException
{ {
issuerCert = cert; issuerInfo = new OCSPResponse.IssuerInfo(anchor, cert);
// Make new public key if parameters are missing // Make new public key if parameters are missing
PublicKey pubKey = cert.getPublicKey(); PublicKey pubKey = cert.getPublicKey();
...@@ -466,6 +465,34 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -466,6 +465,34 @@ class RevocationChecker extends PKIXRevocationChecker {
stackedCerts, params.trustAnchors()); stackedCerts, params.trustAnchors());
} }
static boolean isCausedByNetworkIssue(String type, CertStoreException cse) {
boolean result;
Throwable t = cse.getCause();
switch (type) {
case "LDAP":
if (t != null) {
// These two exception classes are inside java.naming module
String cn = t.getClass().getName();
result = (cn.equals("javax.naming.ServiceUnavailableException") ||
cn.equals("javax.naming.CommunicationException"));
} else {
result = false;
}
break;
case "SSLServer":
result = (t != null && t instanceof IOException);
break;
case "URI":
result = (t != null && t instanceof IOException);
break;
default:
// we don't know about any other remote CertStore types
return false;
}
return result;
}
private void checkCRLs(X509Certificate cert, PublicKey prevKey, private void checkCRLs(X509Certificate cert, PublicKey prevKey,
X509Certificate prevCert, boolean signFlag, X509Certificate prevCert, boolean signFlag,
boolean allowSeparateKey, boolean allowSeparateKey,
...@@ -478,9 +505,9 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -478,9 +505,9 @@ class RevocationChecker extends PKIXRevocationChecker {
" ---checking revocation status ..."); " ---checking revocation status ...");
} }
// reject circular dependencies - RFC 3280 is not explicit on how // Reject circular dependencies - RFC 5280 is not explicit on how
// to handle this, so we feel it is safest to reject them until // to handle this, but does suggest that they can be a security
// the issue is resolved in the PKIX WG. // risk and can create unresolvable dependencies
if (stackedCerts != null && stackedCerts.contains(cert)) { if (stackedCerts != null && stackedCerts.contains(cert)) {
if (debug != null) { if (debug != null) {
debug.println("RevocationChecker.checkCRLs()" + debug.println("RevocationChecker.checkCRLs()" +
...@@ -510,7 +537,7 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -510,7 +537,7 @@ class RevocationChecker extends PKIXRevocationChecker {
"CertStoreException: " + e.getMessage()); "CertStoreException: " + e.getMessage());
} }
if (networkFailureException == null && if (networkFailureException == null &&
CertStoreHelper.isCausedByNetworkIssue(store.getType(),e)) { isCausedByNetworkIssue(store.getType(),e)) {
// save this exception, we may need to throw it later // save this exception, we may need to throw it later
networkFailureException = new CertPathValidatorException( networkFailureException = new CertPathValidatorException(
"Unable to determine revocation status due to " + "Unable to determine revocation status due to " +
...@@ -550,15 +577,14 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -550,15 +577,14 @@ class RevocationChecker extends PKIXRevocationChecker {
try { try {
if (crlDP) { if (crlDP) {
approvedCRLs.addAll(DistributionPointFetcher.getCRLs( approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
sel, signFlag, prevKey, prevCert, sel, signFlag, prevKey, prevCert,
params.sigProvider(), certStores, params.sigProvider(), certStores, reasonsMask,
reasonsMask, anchors, null)); anchors, null, params.variant()));
} }
} catch (CertStoreException e) { } catch (CertStoreException e) {
if (e instanceof CertStoreTypeException) { if (e instanceof CertStoreTypeException) {
CertStoreTypeException cste = (CertStoreTypeException)e; CertStoreTypeException cste = (CertStoreTypeException)e;
if (CertStoreHelper.isCausedByNetworkIssue(cste.getType(), if (isCausedByNetworkIssue(cste.getType(), e)) {
e)) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
"Unable to determine revocation status due to " + "Unable to determine revocation status due to " +
"network error", e, null, -1, "network error", e, null, -1,
...@@ -634,7 +660,7 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -634,7 +660,7 @@ class RevocationChecker extends PKIXRevocationChecker {
/* /*
* Abort CRL validation and throw exception if there are any * Abort CRL validation and throw exception if there are any
* unrecognized critical CRL entry extensions (see section * unrecognized critical CRL entry extensions (see section
* 5.3 of RFC 3280). * 5.3 of RFC 5280).
*/ */
Set<String> unresCritExts = entry.getCriticalExtensionOIDs(); Set<String> unresCritExts = entry.getCriticalExtensionOIDs();
if (unresCritExts != null && !unresCritExts.isEmpty()) { if (unresCritExts != null && !unresCritExts.isEmpty()) {
...@@ -682,14 +708,8 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -682,14 +708,8 @@ class RevocationChecker extends PKIXRevocationChecker {
OCSPResponse response = null; OCSPResponse response = null;
CertId certId = null; CertId certId = null;
try { try {
if (issuerCert != null) { certId = new CertId(issuerInfo.getName(), issuerInfo.getPublicKey(),
certId = new CertId(issuerCert, currCert.getSerialNumberObject());
currCert.getSerialNumberObject());
} else {
// must be an anchor name and key
certId = new CertId(anchor.getCA(), anchor.getCAPublicKey(),
currCert.getSerialNumberObject());
}
// check if there is a cached OCSP response available // check if there is a cached OCSP response available
byte[] responseBytes = ocspResponses.get(cert); byte[] responseBytes = ocspResponses.get(cert);
...@@ -706,8 +726,8 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -706,8 +726,8 @@ class RevocationChecker extends PKIXRevocationChecker {
nonce = ext.getValue(); nonce = ext.getValue();
} }
} }
response.verify(Collections.singletonList(certId), issuerCert, response.verify(Collections.singletonList(certId), issuerInfo,
responderCert, params.date(), nonce); responderCert, params.date(), nonce, params.variant());
} else { } else {
URI responderURI = (this.responderURI != null) URI responderURI = (this.responderURI != null)
...@@ -720,8 +740,8 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -720,8 +740,8 @@ class RevocationChecker extends PKIXRevocationChecker {
} }
response = OCSP.check(Collections.singletonList(certId), response = OCSP.check(Collections.singletonList(certId),
responderURI, issuerCert, responderCert, responderURI, issuerInfo, responderCert, null,
null, ocspExtensions); ocspExtensions, params.variant());
} }
} catch (IOException e) { } catch (IOException e) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
...@@ -833,7 +853,7 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -833,7 +853,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())) certStores, params.date(), params.variant()))
{ {
results.add(crl); results.add(crl);
} }
...@@ -886,9 +906,9 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -886,9 +906,9 @@ class RevocationChecker extends PKIXRevocationChecker {
" ---checking " + msg + "..."); " ---checking " + msg + "...");
} }
// reject circular dependencies - RFC 3280 is not explicit on how // Reject circular dependencies - RFC 5280 is not explicit on how
// to handle this, so we feel it is safest to reject them until // to handle this, but does suggest that they can be a security
// the issue is resolved in the PKIX WG. // risk and can create unresolvable dependencies
if ((stackedCerts != null) && stackedCerts.contains(cert)) { if ((stackedCerts != null) && stackedCerts.contains(cert)) {
if (debug != null) { if (debug != null) {
debug.println( debug.println(
......
/* /*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2017, 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
...@@ -50,7 +50,7 @@ import sun.security.util.Debug; ...@@ -50,7 +50,7 @@ import sun.security.util.Debug;
* <p> If successful, it returns a certification path which has successfully * <p> If successful, it returns a certification path which has successfully
* satisfied all the constraints and requirements specified in the * satisfied all the constraints and requirements specified in the
* PKIXBuilderParameters object and has been validated according to the PKIX * PKIXBuilderParameters object and has been validated according to the PKIX
* path validation algorithm defined in RFC 3280. * path validation algorithm defined in RFC 5280.
* *
* <p> This implementation uses a depth-first search approach to finding * <p> This implementation uses a depth-first search approach to finding
* certification paths. If it comes to a point in which it cannot find * certification paths. If it comes to a point in which it cannot find
...@@ -343,7 +343,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -343,7 +343,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
checkers.add(policyChecker); checkers.add(policyChecker);
// add the algorithm checker // add the algorithm checker
checkers.add(new AlgorithmChecker(builder.trustAnchor)); checkers.add(new AlgorithmChecker(builder.trustAnchor,
buildParams.date(), null));
BasicChecker basicChecker = null; BasicChecker basicChecker = null;
if (nextState.keyParamsNeeded()) { if (nextState.keyParamsNeeded()) {
......
/* /*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2017, 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
...@@ -37,6 +37,7 @@ import javax.net.ssl.*; ...@@ -37,6 +37,7 @@ import javax.net.ssl.*;
import sun.security.provider.certpath.AlgorithmChecker; import sun.security.provider.certpath.AlgorithmChecker;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
import sun.security.validator.Validator;
public abstract class SSLContextImpl extends SSLContextSpi { public abstract class SSLContextImpl extends SSLContextSpi {
...@@ -1040,7 +1041,7 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager ...@@ -1040,7 +1041,7 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
constraints = new SSLAlgorithmConstraints(sslSocket, true); constraints = new SSLAlgorithmConstraints(sslSocket, true);
} }
checkAlgorithmConstraints(chain, constraints); checkAlgorithmConstraints(chain, constraints, isClient);
} }
} }
...@@ -1082,12 +1083,12 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager ...@@ -1082,12 +1083,12 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
constraints = new SSLAlgorithmConstraints(engine, true); constraints = new SSLAlgorithmConstraints(engine, true);
} }
checkAlgorithmConstraints(chain, constraints); checkAlgorithmConstraints(chain, constraints, isClient);
} }
} }
private void checkAlgorithmConstraints(X509Certificate[] chain, private void checkAlgorithmConstraints(X509Certificate[] chain,
AlgorithmConstraints constraints) throws CertificateException { AlgorithmConstraints constraints, boolean isClient) throws CertificateException {
try { try {
// Does the certificate chain end with a trusted certificate? // Does the certificate chain end with a trusted certificate?
...@@ -1105,7 +1106,9 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager ...@@ -1105,7 +1106,9 @@ 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 = new AlgorithmChecker(constraints); AlgorithmChecker checker =
new AlgorithmChecker(constraints, null,
(isClient ? Validator.VAR_TLS_CLIENT : Validator.VAR_TLS_SERVER));
checker.init(false); checker.init(false);
for (int i = checkedLength; i >= 0; i--) { for (int i = checkedLength; i >= 0; i--) {
Certificate cert = chain[i]; Certificate cert = chain[i];
......
/* /*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2017, 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
...@@ -39,6 +39,7 @@ import java.security.cert.Certificate; ...@@ -39,6 +39,7 @@ import java.security.cert.Certificate;
import javax.net.ssl.*; import javax.net.ssl.*;
import sun.security.provider.certpath.AlgorithmChecker; import sun.security.provider.certpath.AlgorithmChecker;
import sun.security.validator.Validator;
/** /**
* The new X509 key manager implementation. The main differences to the * The new X509 key manager implementation. The main differences to the
...@@ -62,7 +63,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager ...@@ -62,7 +63,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
private static final Debug debug = Debug.getInstance("ssl"); private static final Debug debug = Debug.getInstance("ssl");
private final static boolean useDebug = private static final boolean useDebug =
(debug != null) && Debug.isOn("keymanager"); (debug != null) && Debug.isOn("keymanager");
// for unit testing only, set via privileged reflection // for unit testing only, set via privileged reflection
...@@ -661,6 +662,15 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager ...@@ -661,6 +662,15 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
return CheckResult.OK; return CheckResult.OK;
} }
public String getValidator() {
if (this == CLIENT) {
return Validator.VAR_TLS_CLIENT;
} else if (this == SERVER) {
return Validator.VAR_TLS_SERVER;
}
return Validator.VAR_GENERIC;
}
} }
// enum for the result of the extension check // enum for the result of the extension check
...@@ -774,7 +784,8 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager ...@@ -774,7 +784,8 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
// check the algorithm constraints // check the algorithm constraints
if (constraints != null && if (constraints != null &&
!conformsToAlgorithmConstraints(constraints, chain)) { !conformsToAlgorithmConstraints(constraints, chain,
checkType.getValidator())) {
if (useDebug) { if (useDebug) {
debug.println("Ignoring alias " + alias + debug.println("Ignoring alias " + alias +
...@@ -811,13 +822,19 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager ...@@ -811,13 +822,19 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
} }
private static boolean conformsToAlgorithmConstraints( private static boolean conformsToAlgorithmConstraints(
AlgorithmConstraints constraints, Certificate[] chain) { AlgorithmConstraints constraints, Certificate[] chain,
String variant) {
AlgorithmChecker checker = new AlgorithmChecker(constraints); AlgorithmChecker checker = new AlgorithmChecker(constraints, null, variant);
try { try {
checker.init(false); checker.init(false);
} catch (CertPathValidatorException cpve) { } catch (CertPathValidatorException cpve) {
// unlikely to happen // unlikely to happen
if (useDebug) {
debug.println(
"Cannot initialize algorithm constraints checker: " + cpve);
}
return false; return false;
} }
...@@ -828,6 +845,11 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager ...@@ -828,6 +845,11 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
// We don't care about the unresolved critical extensions. // We don't care about the unresolved critical extensions.
checker.check(cert, Collections.<String>emptySet()); checker.check(cert, Collections.<String>emptySet());
} catch (CertPathValidatorException cpve) { } catch (CertPathValidatorException cpve) {
if (useDebug) {
debug.println("Certificate (" + cert +
") does not conform to algorithm constraints: " + cpve);
}
return false; return false;
} }
} }
......
...@@ -31,8 +31,10 @@ import java.security.AccessController; ...@@ -31,8 +31,10 @@ import java.security.AccessController;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
...@@ -44,7 +46,7 @@ public class AnchorCertificates { ...@@ -44,7 +46,7 @@ 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 HashSet<String> certs; private static Set<String> certs = Collections.emptySet();
static { static {
AccessController.doPrivileged(new PrivilegedAction<Void>() { AccessController.doPrivileged(new PrivilegedAction<Void>() {
......
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017 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
...@@ -25,29 +25,93 @@ ...@@ -25,29 +25,93 @@
package sun.security.util; package sun.security.util;
import sun.security.validator.Validator;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Timestamp;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Date;
/** /**
* This class is a wrapper for keeping state and passing objects between PKIX, * This class contains parameters for checking against constraints that extend
* AlgorithmChecker, and DisabledAlgorithmConstraints. * past the publicly available parameters in java.security.AlgorithmConstraints.
* This is currently on passed between between PKIX, AlgorithmChecker,
* and DisabledAlgorithmConstraints.
*/ */
public class CertConstraintParameters { public class ConstraintsParameters {
/*
* The below 3 values are used the same as the permit() methods
* published in java.security.AlgorithmConstraints.
*/
// Algorithm string to be checked against constraints
private final String algorithm;
// AlgorithmParameters to the algorithm being checked
private final AlgorithmParameters algParams;
// Public Key being checked against constraints
private final Key publicKey;
/*
* New values that are checked against constraints that the current public
* API does not support.
*/
// A certificate being passed to check against constraints. // A certificate being passed to check against constraints.
private final X509Certificate cert; private final X509Certificate cert;
// This is true if the trust anchor in the certificate chain matches a cert // This is true if the trust anchor in the certificate chain matches a cert
// in AnchorCertificates // in AnchorCertificates
private final boolean trustedMatch; private final boolean trustedMatch;
// PKIXParameter date
private final Date pkixDate;
// Timestamp of the signed JAR file
private final Timestamp jarTimestamp;
private final String variant;
public CertConstraintParameters(X509Certificate c, boolean match) { public ConstraintsParameters(X509Certificate c, boolean match,
Date pkixdate, Timestamp jarTime, String variant) {
cert = c; cert = c;
trustedMatch = match; trustedMatch = match;
pkixDate = pkixdate;
jarTimestamp = jarTime;
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
algorithm = null;
algParams = null;
publicKey = null;
}
public ConstraintsParameters(String algorithm, AlgorithmParameters params,
Key key, String variant) {
this.algorithm = algorithm;
algParams = params;
this.publicKey = 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 CertConstraintParameters(X509Certificate c) { public AlgorithmParameters getAlgParams() {
this(c, false); return algParams;
} }
public Key getPublicKey() {
return publicKey;
}
// Returns if the trust anchor has a match if anchor checking is enabled. // Returns if the trust anchor has a match if anchor checking is enabled.
public boolean isTrustedMatch() { public boolean isTrustedMatch() {
return trustedMatch; return trustedMatch;
...@@ -56,4 +120,16 @@ public class CertConstraintParameters { ...@@ -56,4 +120,16 @@ public class CertConstraintParameters {
public X509Certificate getCertificate() { public X509Certificate getCertificate() {
return cert; return cert;
} }
public Date getPKIXParamDate() {
return pkixDate;
}
public Timestamp getJARTimestamp() {
return jarTimestamp;
}
public String getVariant() {
return variant;
}
} }
/* /*
* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2017, 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
...@@ -25,17 +25,28 @@ ...@@ -25,17 +25,28 @@
package sun.security.util; package sun.security.util;
import sun.security.validator.Validator;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.security.CryptoPrimitive; import java.security.CryptoPrimitive;
import java.security.AlgorithmParameters; import java.security.AlgorithmParameters;
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.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
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.Set;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.Matcher; import java.util.regex.Matcher;
...@@ -49,11 +60,11 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -49,11 +60,11 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
// the known security property, jdk.certpath.disabledAlgorithms // the known security property, jdk.certpath.disabledAlgorithms
public final static String PROPERTY_CERTPATH_DISABLED_ALGS = public static final String PROPERTY_CERTPATH_DISABLED_ALGS =
"jdk.certpath.disabledAlgorithms"; "jdk.certpath.disabledAlgorithms";
// the known security property, jdk.tls.disabledAlgorithms // the known security property, jdk.tls.disabledAlgorithms
public final static String PROPERTY_TLS_DISABLED_ALGS = public static final String PROPERTY_TLS_DISABLED_ALGS =
"jdk.tls.disabledAlgorithms"; "jdk.tls.disabledAlgorithms";
// the known security property, jdk.jar.disabledAlgorithms // the known security property, jdk.jar.disabledAlgorithms
...@@ -93,14 +104,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -93,14 +104,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* there are keysize or other limit, this method allow the algorithm. * there are keysize or other limit, this method allow the algorithm.
*/ */
@Override @Override
final public boolean permits(Set<CryptoPrimitive> primitives, public final boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters) { String algorithm, AlgorithmParameters parameters) {
if (primitives == null || primitives.isEmpty()) {
throw new IllegalArgumentException(
"No cryptographic primitive specified");
}
return checkAlgorithm(disabledAlgorithms, algorithm, decomposer); return checkAlgorithm(disabledAlgorithms, algorithm, decomposer);
} }
...@@ -109,7 +114,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -109,7 +114,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* placed on the key. * placed on the key.
*/ */
@Override @Override
final public boolean permits(Set<CryptoPrimitive> primitives, Key key) { public final boolean permits(Set<CryptoPrimitive> primitives, Key key) {
return checkConstraints(primitives, "", key, null); return checkConstraints(primitives, "", key, null);
} }
...@@ -118,7 +123,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -118,7 +123,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* been placed on the key. * been placed on the key.
*/ */
@Override @Override
final public boolean permits(Set<CryptoPrimitive> primitives, public final boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters) { String algorithm, Key key, AlgorithmParameters parameters) {
if (algorithm == null || algorithm.length() == 0) { if (algorithm == null || algorithm.length() == 0) {
...@@ -128,6 +133,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -128,6 +133,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return checkConstraints(primitives, algorithm, key, parameters); return checkConstraints(primitives, algorithm, key, parameters);
} }
public final void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
permits(cp.getAlgorithm(), cp);
}
public final void permits(String algorithm, Key key,
AlgorithmParameters params, String variant)
throws CertPathValidatorException {
permits(algorithm, new ConstraintsParameters(algorithm, params, key,
(variant == null) ? Validator.VAR_GENERIC : variant));
}
/* /*
* Check if a x509Certificate object is permitted. Check if all * Check if a x509Certificate object is permitted. Check if all
* algorithms are allowed, certificate constraints, and the * algorithms are allowed, certificate constraints, and the
...@@ -135,18 +152,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -135,18 +152,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* *
* Uses new style permit() which throws exceptions. * Uses new style permit() which throws exceptions.
*/ */
public final void permits(Set<CryptoPrimitive> primitives,
CertConstraintParameters cp) throws CertPathValidatorException {
checkConstraints(primitives, cp);
}
/* public final void permits(String algorithm, ConstraintsParameters cp)
* Check if Certificate object is within the constraints. throws CertPathValidatorException {
* Uses new style permit() which throws exceptions. algorithmConstraints.permits(algorithm, cp);
*/
public final void permits(Set<CryptoPrimitive> primitives,
X509Certificate cert) throws CertPathValidatorException {
checkConstraints(primitives, new CertConstraintParameters(cert));
} }
// Check if a string is contained inside the property // Check if a string is contained inside the property
...@@ -169,7 +178,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -169,7 +178,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
throw new IllegalArgumentException("The key cannot be null"); throw new IllegalArgumentException("The key cannot be null");
} }
// check the signature algorithm // check the signature algorithm with parameters
if (algorithm != null && algorithm.length() != 0) { if (algorithm != null && algorithm.length() != 0) {
if (!permits(primitives, algorithm, parameters)) { if (!permits(primitives, algorithm, parameters)) {
return false; return false;
...@@ -185,36 +194,6 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -185,36 +194,6 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return algorithmConstraints.permits(key); return algorithmConstraints.permits(key);
} }
/*
* Check algorithm constraints with Certificate
* Uses new style permit() which throws exceptions.
*/
private void checkConstraints(Set<CryptoPrimitive> primitives,
CertConstraintParameters cp) throws CertPathValidatorException {
X509Certificate cert = cp.getCertificate();
String algorithm = cert.getSigAlgName();
// Check signature algorithm is not disabled
if (!permits(primitives, algorithm, null)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed on disabled "+
"signature algorithm: " + algorithm,
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
// Check key algorithm is not disabled
if (!permits(primitives, cert.getPublicKey().getAlgorithm(), null)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed on disabled "+
"public key algorithm: " + algorithm,
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
// Check the certificate and key constraints
algorithmConstraints.permits(cp);
}
/** /**
* Key and Certificate Constraints * Key and Certificate Constraints
...@@ -229,15 +208,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -229,15 +208,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* 'true' means the operation is allowed. * 'true' means the operation is allowed.
* 'false' means it failed the constraints and is disallowed. * 'false' means it failed the constraints and is disallowed.
* *
* When passing CertConstraintParameters through permit(), an exception * When passing ConstraintsParameters through permit(), an exception
* will be thrown on a failure to better identify why the operation was * will be thrown on a failure to better identify why the operation was
* disallowed. * disallowed.
*/ */
private static class Constraints { private static class Constraints {
private Map<String, Set<Constraint>> constraintsMap = new HashMap<>(); private Map<String, List<Constraint>> constraintsMap = new HashMap<>();
private static final Pattern keySizePattern = Pattern.compile(
"keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); private static class Holder {
private static final Pattern DENY_AFTER_PATTERN = Pattern.compile(
"denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
}
public Constraints(String[] constraintArray) { public Constraints(String[] constraintArray) {
for (String constraintEntry : constraintArray) { for (String constraintEntry : constraintArray) {
...@@ -252,39 +234,47 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -252,39 +234,47 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
// Check if constraint is a complete disabling of an // Check if constraint is a complete disabling of an
// algorithm or has conditions. // algorithm or has conditions.
String algorithm;
String policy;
int space = constraintEntry.indexOf(' '); int space = constraintEntry.indexOf(' ');
if (space > 0) { String algorithm = AlgorithmDecomposer.hashName(
algorithm = AlgorithmDecomposer.hashName( ((space > 0 ? constraintEntry.substring(0, space) :
constraintEntry.substring(0, space). constraintEntry).
toUpperCase(Locale.ENGLISH)); toUpperCase(Locale.ENGLISH)));
policy = constraintEntry.substring(space + 1); List<Constraint> constraintList =
} else { constraintsMap.getOrDefault(algorithm,
constraintsMap.putIfAbsent( new ArrayList<>(1));
constraintEntry.toUpperCase(Locale.ENGLISH), constraintsMap.putIfAbsent(algorithm, constraintList);
new HashSet<>()); if (space <= 0) {
constraintList.add(new DisabledConstraint(algorithm));
continue; continue;
} }
String policy = constraintEntry.substring(space + 1);
// Convert constraint conditions into Constraint classes // Convert constraint conditions into Constraint classes
Constraint c = null; Constraint c, lastConstraint = null;
Constraint lastConstraint = null;
// Allow only one jdkCA entry per constraint entry // Allow only one jdkCA entry per constraint entry
boolean jdkCALimit = false; boolean jdkCALimit = false;
// Allow only one denyAfter entry per constraint entry
boolean denyAfterLimit = false;
for (String entry : policy.split("&")) { for (String entry : policy.split("&")) {
entry = entry.trim(); entry = entry.trim();
Matcher matcher = keySizePattern.matcher(entry); Matcher matcher;
if (matcher.matches()) { if (entry.startsWith("keySize")) {
if (debug != null) { if (debug != null) {
debug.println("Constraints set to keySize: " + debug.println("Constraints set to keySize: " +
entry); entry);
} }
StringTokenizer tokens = new StringTokenizer(entry);
if (!"keySize".equals(tokens.nextToken())) {
throw new IllegalArgumentException("Error in " +
"security property. Constraint unknown: " +
entry);
}
c = new KeySizeConstraint(algorithm, c = new KeySizeConstraint(algorithm,
KeySizeConstraint.Operator.of(matcher.group(1)), KeySizeConstraint.Operator.of(tokens.nextToken()),
Integer.parseInt(matcher.group(2))); Integer.parseInt(tokens.nextToken()));
} else if (entry.equalsIgnoreCase("jdkCA")) { } else if (entry.equalsIgnoreCase("jdkCA")) {
if (debug != null) { if (debug != null) {
...@@ -297,18 +287,39 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -297,18 +287,39 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
} }
c = new jdkCAConstraint(algorithm); c = new jdkCAConstraint(algorithm);
jdkCALimit = true; jdkCALimit = true;
} else if (entry.startsWith("denyAfter") &&
(matcher = Holder.DENY_AFTER_PATTERN.matcher(entry))
.matches()) {
if (debug != null) {
debug.println("Constraints set to denyAfter");
}
if (denyAfterLimit) {
throw new IllegalArgumentException("Only one " +
"denyAfter entry allowed in property. " +
"Constraint: " + constraintEntry);
}
int year = Integer.parseInt(matcher.group(1));
int month = Integer.parseInt(matcher.group(2));
int day = Integer.parseInt(matcher.group(3));
c = new DenyAfterConstraint(algorithm, year, month,
day);
denyAfterLimit = true;
} else if (entry.startsWith("usage")) {
String s[] = (entry.substring(5)).trim().split(" ");
c = new UsageConstraint(algorithm, s);
if (debug != null) {
debug.println("Constraints usage length is " + s.length);
}
} else {
throw new IllegalArgumentException("Error in security" +
" property. Constraint unknown: " + entry);
} }
// Link multiple conditions for a single constraint // Link multiple conditions for a single constraint
// into a linked list. // into a linked list.
if (lastConstraint == null) { if (lastConstraint == null) {
if (!constraintsMap.containsKey(algorithm)) { constraintList.add(c);
constraintsMap.putIfAbsent(algorithm,
new HashSet<>());
}
if (c != null) {
constraintsMap.get(algorithm).add(c);
}
} else { } else {
lastConstraint.nextConstraint = c; lastConstraint.nextConstraint = c;
} }
...@@ -318,61 +329,73 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -318,61 +329,73 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
} }
// Get applicable constraints based off the signature algorithm // Get applicable constraints based off the signature algorithm
private Set<Constraint> getConstraints(String algorithm) { private List<Constraint> getConstraints(String algorithm) {
return constraintsMap.get(algorithm); return constraintsMap.get(algorithm);
} }
// Check if KeySizeConstraints permit the specified key // Check if KeySizeConstraints permit the specified key
public boolean permits(Key key) { public boolean permits(Key key) {
Set<Constraint> set = getConstraints(key.getAlgorithm()); List<Constraint> list = getConstraints(key.getAlgorithm());
if (set == null) { if (list == null) {
return true; return true;
} }
for (Constraint constraint : set) { for (Constraint constraint : list) {
if (!constraint.permits(key)) { if (!constraint.permits(key)) {
if (debug != null) { if (debug != null) {
debug.println("keySizeConstraint: failed key " + debug.println("keySizeConstraint: failed key " +
"constraint check " + KeyUtil.getKeySize(key)); "constraint check " + KeyUtil.getKeySize(key));
} }
return false; return false;
} }
} }
return true; return true;
} }
// Check if constraints permit this cert. // Check if constraints permit this cert.
public void permits(CertConstraintParameters cp) public void permits(String algorithm, ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
X509Certificate cert = cp.getCertificate(); X509Certificate cert = cp.getCertificate();
if (debug != null) { if (debug != null) {
debug.println("Constraints.permits(): " + cert.getSigAlgName()); debug.println("Constraints.permits(): " + algorithm +
" Variant: " + cp.getVariant());
} }
// Get all signature algorithms to check for constraints // Get all signature algorithms to check for constraints
Set<String> algorithms = Set<String> algorithms = new HashSet<>();
AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName()); if (algorithm != null) {
if (algorithms == null || algorithms.isEmpty()) { algorithms.addAll(AlgorithmDecomposer.decomposeOneHash(algorithm));
return; }
}
// Attempt to add the public key algorithm to the set
algorithms.add(cert.getPublicKey().getAlgorithm());
// Attempt to add the public key algorithm if cert provided
if (cert != null) {
algorithms.add(cert.getPublicKey().getAlgorithm());
}
if (cp.getPublicKey() != null) {
algorithms.add(cp.getPublicKey().getAlgorithm());
}
// Check all applicable constraints // Check all applicable constraints
for (String algorithm : algorithms) { for (String alg : algorithms) {
Set<Constraint> set = getConstraints(algorithm); List<Constraint> list = getConstraints(alg);
if (set == null) { if (list == null) {
continue; continue;
} }
for (Constraint constraint : set) { for (Constraint constraint : list) {
constraint.permits(cp); constraint.permits(cp);
} }
} }
} }
} }
// Abstract class for algorithm constraint checking /**
* This abstract Constraint class for algorithm-based checking
* may contain one or more constraints. If the '&' on the {@Security}
* property is used, multiple constraints have been grouped together
* requiring all the constraints to fail for the check to be disallowed.
*
* If the class contains multiple constraints, the next constraint
* is stored in {@code nextConstraint} in linked-list fashion.
*/
private abstract static class Constraint { private abstract static class Constraint {
String algorithm; String algorithm;
Constraint nextConstraint = null; Constraint nextConstraint = null;
...@@ -408,22 +431,87 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -408,22 +431,87 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
} }
/** /**
* Check if an algorithm constraint permit this key to be used. * Check if an algorithm constraint is permitted with a given key.
*
* If the check inside of {@code permit()} fails, it must call
* {@code next()} with the same {@code Key} parameter passed if
* multiple constraints need to be checked.
*
* @param key Public key * @param key Public key
* @return true if constraints do not match * @return 'true' if constraint is allowed, 'false' if disallowed.
*/ */
public boolean permits(Key key) { public boolean permits(Key key) {
return true; return true;
} }
/** /**
* Check if an algorithm constraint is permit this certificate to * Check if an algorithm constraint is permitted with a given
* be used. * ConstraintsParameters.
* @param cp CertificateParameter containing certificate and state info *
* @return true if constraints do not match * If the check inside of {@code permits()} fails, it must call
* {@code next()} with the same {@code ConstraintsParameters}
* parameter passed if multiple constraints need to be checked.
*
* @param cp CertConstraintParameter containing certificate info
* @throws CertPathValidatorException if constraint disallows.
*
*/ */
public abstract void permits(CertConstraintParameters cp) public abstract void permits(ConstraintsParameters cp)
throws CertPathValidatorException; throws CertPathValidatorException;
/**
* Recursively check if the constraints are allowed.
*
* If {@code nextConstraint} is non-null, this method will
* call {@code nextConstraint}'s {@code permits()} to check if the
* constraint is allowed or denied. If the constraint's
* {@code permits()} is allowed, this method will exit this and any
* recursive next() calls, returning 'true'. If the constraints called
* were disallowed, the last constraint will throw
* {@code CertPathValidatorException}.
*
* @param cp ConstraintsParameters
* @return 'true' if constraint allows the operation, 'false' if
* we are at the end of the constraint list or,
* {@code nextConstraint} is null.
*/
boolean next(ConstraintsParameters cp)
throws CertPathValidatorException {
if (nextConstraint != null) {
nextConstraint.permits(cp);
return true;
}
return false;
}
/**
* Recursively check if this constraint is allowed,
*
* If {@code nextConstraint} is non-null, this method will
* call {@code nextConstraint}'s {@code permit()} to check if the
* constraint is allowed or denied. If the constraint's
* {@code permit()} is allowed, this method will exit this and any
* recursive next() calls, returning 'true'. If the constraints
* called were disallowed the check will exit with 'false'.
*
* @param key Public key
* @return 'true' if constraint allows the operation, 'false' if
* the constraint denies the operation.
*/
boolean next(Key key) {
if (nextConstraint != null && nextConstraint.permits(key)) {
return true;
}
return false;
}
String extendedMsg(ConstraintsParameters cp) {
return (cp.getCertificate() == null ? "." :
" used with certificate: " +
cp.getCertificate().getSubjectX500Principal() +
(cp.getVariant() != Validator.VAR_GENERIC ?
". Usage was " + cp.getVariant() : "."));
}
} }
/* /*
...@@ -436,30 +524,175 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -436,30 +524,175 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
} }
/* /*
* Check if each constraint fails and check if there is a linked * Check if ConstraintsParameters has a trusted match, if it does
* constraint Any permitted constraint will exit the linked list * call next() for any following constraints. If it does not, exit
* to allow the operation. * as this constraint(s) does not restrict the operation.
*/ */
public void permits(CertConstraintParameters cp) public void permits(ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
if (debug != null) { if (debug != null) {
debug.println("jdkCAConstraints.permits(): " + algorithm); debug.println("jdkCAConstraints.permits(): " + algorithm);
} }
// Return false if the chain has a trust anchor in cacerts // Check chain has a trust anchor in cacerts
if (cp.isTrustedMatch()) { if (cp.isTrustedMatch()) {
if (nextConstraint != null) { if (next(cp)) {
nextConstraint.permits(cp);
return; return;
} }
throw new CertPathValidatorException( throw new CertPathValidatorException(
"Algorithm constraints check failed on certificate " + "Algorithm constraints check failed on certificate " +
"anchor limits", "anchor limits. " + algorithm + extendedMsg(cp),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
} }
} }
} }
/*
* This class handles the denyAfter constraint. The date is in the UTC/GMT
* timezone.
*/
private static class DenyAfterConstraint extends Constraint {
private Date denyAfterDate;
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("EEE, MMM d HH:mm:ss z yyyy");
DenyAfterConstraint(String algo, int year, int month, int day) {
Calendar c;
algorithm = algo;
if (debug != null) {
debug.println("DenyAfterConstraint read in as: year " +
year + ", month = " + month + ", day = " + day);
}
c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT"))
.setDate(year, month - 1, day).build();
if (year > c.getActualMaximum(Calendar.YEAR) ||
year < c.getActualMinimum(Calendar.YEAR)) {
throw new IllegalArgumentException(
"Invalid year given in constraint: " + year);
}
if ((month - 1) > c.getActualMaximum(Calendar.MONTH) ||
(month - 1) < c.getActualMinimum(Calendar.MONTH)) {
throw new IllegalArgumentException(
"Invalid month given in constraint: " + month);
}
if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) ||
day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) {
throw new IllegalArgumentException(
"Invalid Day of Month given in constraint: " + day);
}
denyAfterDate = c.getTime();
if (debug != null) {
debug.println("DenyAfterConstraint date set to: " +
dateFormat.format(denyAfterDate));
}
}
/*
* Checking that the provided date is not beyond the constraint date.
* The provided date can be the PKIXParameter date if given,
* otherwise it is the current date.
*
* If the constraint disallows, call next() for any following
* constraints. Throw an exception if this is the last constraint.
*/
@Override
public void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
Date currentDate;
String errmsg;
if (cp.getJARTimestamp() != null) {
currentDate = cp.getJARTimestamp().getTimestamp();
errmsg = "JAR Timestamp date: ";
} else if (cp.getPKIXParamDate() != null) {
currentDate = cp.getPKIXParamDate();
errmsg = "PKIXParameter date: ";
} else {
currentDate = new Date();
errmsg = "Current date: ";
}
if (!denyAfterDate.after(currentDate)) {
if (next(cp)) {
return;
}
throw new CertPathValidatorException(
"denyAfter constraint check failed: " + algorithm +
" used with Constraint date: " +
dateFormat.format(denyAfterDate) + "; " + errmsg +
dateFormat.format(currentDate) + extendedMsg(cp),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
/*
* Return result if the constraint's date is beyond the current date
* in UTC timezone.
*/
public boolean permits(Key key) {
if (next(key)) {
return true;
}
if (debug != null) {
debug.println("DenyAfterConstraints.permits(): " + algorithm);
}
return denyAfterDate.after(new Date());
}
}
/*
* The usage constraint is for the "usage" keyword. It checks against the
* variant value in ConstraintsParameters.
*/
private static class UsageConstraint extends Constraint {
String[] usages;
UsageConstraint(String algorithm, String[] usages) {
this.algorithm = algorithm;
this.usages = usages;
}
public void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
for (String usage : usages) {
String v = null;
if (usage.compareToIgnoreCase("TLSServer") == 0) {
v = Validator.VAR_TLS_SERVER;
} else if (usage.compareToIgnoreCase("TLSClient") == 0) {
v = Validator.VAR_TLS_CLIENT;
} else if (usage.compareToIgnoreCase("SignedJAR") == 0) {
v = Validator.VAR_PLUGIN_CODE_SIGNING;
}
if (debug != null) {
debug.println("Checking if usage constraint \"" + v +
"\" matches \"" + cp.getVariant() + "\"");
// Because usage checking can come from many places
// a stack trace is very helpful.
ByteArrayOutputStream ba = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(ba);
(new Exception()).printStackTrace(ps);
debug.println(ba.toString());
}
if (cp.getVariant().compareTo(v) == 0) {
if (next(cp)) {
return;
}
throw new CertPathValidatorException("Usage constraint " +
usage + " check failed: " + algorithm +
extendedMsg(cp),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
}
}
/* /*
* This class contains constraints dealing with the key size * This class contains constraints dealing with the key size
...@@ -470,6 +703,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -470,6 +703,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
private int minSize; // the minimal available key size private int minSize; // the minimal available key size
private int maxSize; // the maximal available key size private int maxSize; // the maximal available key size
private int prohibitedSize = -1; // unavailable key sizes private int prohibitedSize = -1; // unavailable key sizes
private int size;
public KeySizeConstraint(String algo, Operator operator, int length) { public KeySizeConstraint(String algo, Operator operator, int length) {
algorithm = algo; algorithm = algo;
...@@ -513,15 +747,22 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -513,15 +747,22 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* constraint Any permitted constraint will exit the linked list * constraint Any permitted constraint will exit the linked list
* to allow the operation. * to allow the operation.
*/ */
public void permits(CertConstraintParameters cp) public void permits(ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
if (!permitsImpl(cp.getCertificate().getPublicKey())) { Key key = null;
if (cp.getPublicKey() != null) {
key = cp.getPublicKey();
} else if (cp.getCertificate() != null) {
key = cp.getCertificate().getPublicKey();
}
if (key != null && !permitsImpl(key)) {
if (nextConstraint != null) { if (nextConstraint != null) {
nextConstraint.permits(cp); nextConstraint.permits(cp);
return; return;
} }
throw new CertPathValidatorException( throw new CertPathValidatorException(
"Algorithm constraints check failed on keysize limits", "Algorithm constraints check failed on keysize limits. "
+ algorithm + " " + size + "bit key" + extendedMsg(cp),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
} }
} }
...@@ -548,7 +789,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -548,7 +789,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return true; return true;
} }
int size = KeyUtil.getKeySize(key); size = KeyUtil.getKeySize(key);
if (size == 0) { if (size == 0) {
return false; // we don't allow any key of size 0. return false; // we don't allow any key of size 0.
} else if (size > 0) { } else if (size > 0) {
...@@ -559,6 +800,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -559,6 +800,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return true; return true;
} }
}
/*
* This constraint is used for the complete disabling of the algorithm.
*/
private static class DisabledConstraint extends Constraint {
DisabledConstraint(String algo) {
algorithm = algo;
}
public void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
throw new CertPathValidatorException(
"Algorithm constraints check failed on disabled " +
"algorithm: " + algorithm + extendedMsg(cp),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
public boolean permits(Key key) {
return false;
} }
} }
}
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, 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,25 +28,23 @@ package sun.security.util; ...@@ -28,25 +28,23 @@ package sun.security.util;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.security.CodeSigner; import java.security.CodeSigner;
import java.security.CryptoPrimitive; import java.security.GeneralSecurityException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
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;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64; import java.util.Base64;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Iterator; 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,9 +59,6 @@ public class SignatureFileVerifier { ...@@ -61,9 +59,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");
private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET =
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK = private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
new DisabledAlgorithmConstraints( new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS); DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
...@@ -78,7 +73,7 @@ public class SignatureFileVerifier { ...@@ -78,7 +73,7 @@ public class SignatureFileVerifier {
private PKCS7 block; private PKCS7 block;
/** the raw bytes of the .SF file */ /** the raw bytes of the .SF file */
private byte sfBytes[]; private byte[] sfBytes;
/** the name of the signature block file, uppercased and without /** the name of the signature block file, uppercased and without
* the extension (.DSA/.RSA/.EC) * the extension (.DSA/.RSA/.EC)
...@@ -97,6 +92,14 @@ public class SignatureFileVerifier { ...@@ -97,6 +92,14 @@ 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. */
private Map<String, Boolean> permittedAlgs= new HashMap<>();
/** TSA timestamp of signed jar. The newest timestamp is used. If there
* was no TSA timestamp used when signed, current time is used ("null").
*/
private Timestamp timestamp = null;
/** /**
* Create the named SignatureFileVerifier. * Create the named SignatureFileVerifier.
* *
...@@ -107,7 +110,7 @@ public class SignatureFileVerifier { ...@@ -107,7 +110,7 @@ public class SignatureFileVerifier {
public SignatureFileVerifier(ArrayList<CodeSigner[]> signerCache, public SignatureFileVerifier(ArrayList<CodeSigner[]> signerCache,
ManifestDigester md, ManifestDigester md,
String name, String name,
byte rawBytes[]) byte[] rawBytes)
throws IOException, CertificateException throws IOException, CertificateException
{ {
// new PKCS7() calls CertificateFactory.getInstance() // new PKCS7() calls CertificateFactory.getInstance()
...@@ -121,7 +124,7 @@ public class SignatureFileVerifier { ...@@ -121,7 +124,7 @@ public class SignatureFileVerifier {
} finally { } finally {
Providers.stopJarVerification(obj); Providers.stopJarVerification(obj);
} }
this.name = name.substring(0, name.lastIndexOf(".")) this.name = name.substring(0, name.lastIndexOf('.'))
.toUpperCase(Locale.ENGLISH); .toUpperCase(Locale.ENGLISH);
this.md = md; this.md = md;
this.signerCache = signerCache; this.signerCache = signerCache;
...@@ -152,7 +155,7 @@ public class SignatureFileVerifier { ...@@ -152,7 +155,7 @@ public class SignatureFileVerifier {
* used to set the raw bytes of the .SF file when it * used to set the raw bytes of the .SF file when it
* is external to the signature block file. * is external to the signature block file.
*/ */
public void setSignatureFile(byte sfBytes[]) public void setSignatureFile(byte[] sfBytes)
{ {
this.sfBytes = sfBytes; this.sfBytes = sfBytes;
} }
...@@ -168,11 +171,10 @@ public class SignatureFileVerifier { ...@@ -168,11 +171,10 @@ public class SignatureFileVerifier {
*/ */
public static boolean isBlockOrSF(String s) { public static boolean isBlockOrSF(String s) {
// we currently only support DSA and RSA PKCS7 blocks // we currently only support DSA and RSA PKCS7 blocks
if (s.endsWith(".SF") || s.endsWith(".DSA") || return s.endsWith(".SF")
s.endsWith(".RSA") || s.endsWith(".EC")) { || s.endsWith(".DSA")
return true; || s.endsWith(".RSA")
} || s.endsWith(".EC");
return false;
} }
/** /**
...@@ -182,7 +184,7 @@ public class SignatureFileVerifier { ...@@ -182,7 +184,7 @@ public class SignatureFileVerifier {
* unknown signature related files (those starting with SIG- with * unknown signature related files (those starting with SIG- with
* an optional [A-Z0-9]{1,3} extension right inside META-INF). * an optional [A-Z0-9]{1,3} extension right inside META-INF).
* *
* @param s file name * @param name file name
* @return true if the input file name is signature related * @return true if the input file name is signature related
*/ */
public static boolean isSigningRelated(String name) { public static boolean isSigningRelated(String name) {
...@@ -198,7 +200,7 @@ public class SignatureFileVerifier { ...@@ -198,7 +200,7 @@ public class SignatureFileVerifier {
return true; return true;
} else if (name.startsWith("SIG-")) { } else if (name.startsWith("SIG-")) {
// check filename extension // check filename extension
// see https://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures // see http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures
// for what filename extensions are legal // for what filename extensions are legal
int extIndex = name.lastIndexOf('.'); int extIndex = name.lastIndexOf('.');
if (extIndex != -1) { if (extIndex != -1) {
...@@ -223,17 +225,10 @@ public class SignatureFileVerifier { ...@@ -223,17 +225,10 @@ public class SignatureFileVerifier {
/** get digest from cache */ /** get digest from cache */
private MessageDigest getDigest(String algorithm) throws SignatureException { private MessageDigest getDigest(String algorithm)
// check that algorithm is not restricted throws SignatureException {
if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, algorithm, null)) {
SignatureException e =
new SignatureException("SignatureFile check failed. " +
"Disabled algorithm used: " + algorithm);
throw e;
}
if (createdDigests == null) if (createdDigests == null)
createdDigests = new HashMap<String, MessageDigest>(); createdDigests = new HashMap<>();
MessageDigest digest = createdDigests.get(algorithm); MessageDigest digest = createdDigests.get(algorithm);
...@@ -303,6 +298,27 @@ public class SignatureFileVerifier { ...@@ -303,6 +298,27 @@ public class SignatureFileVerifier {
if (newSigners == null) if (newSigners == null)
return; return;
/*
* Look for the latest timestamp in the signature block. If an entry
* has no timestamp, use current time (aka null).
*/
for (CodeSigner s: newSigners) {
if (debug != null) {
debug.println("Gathering timestamp for: " + s.toString());
}
if (s.getTimestamp() == null) {
timestamp = null;
break;
} else if (timestamp == null) {
timestamp = s.getTimestamp();
} else {
if (timestamp.getTimestamp().before(
s.getTimestamp().getTimestamp())) {
timestamp = s.getTimestamp();
}
}
}
Iterator<Map.Entry<String,Attributes>> entries = Iterator<Map.Entry<String,Attributes>> entries =
sf.getEntries().entrySet().iterator(); sf.getEntries().entrySet().iterator();
...@@ -345,6 +361,68 @@ public class SignatureFileVerifier { ...@@ -345,6 +361,68 @@ public class SignatureFileVerifier {
updateSigners(newSigners, signers, JarFile.MANIFEST_NAME); updateSigners(newSigners, signers, JarFile.MANIFEST_NAME);
} }
/**
* Check if algorithm is permitted using the permittedAlgs Map.
* If the algorithm is not in the map, check against disabled algorithms and
* store the result. If the algorithm is in the map use that result.
* False is returned for weak algorithm, true for good algorithms.
*/
boolean permittedCheck(String key, String algorithm) {
Boolean permitted = permittedAlgs.get(algorithm);
if (permitted == null) {
try {
JAR_DISABLED_CHECK.permits(algorithm,
new ConstraintsParameters(timestamp));
} catch(GeneralSecurityException e) {
permittedAlgs.put(algorithm, Boolean.FALSE);
permittedAlgs.put(key.toUpperCase(), Boolean.FALSE);
if (debug != null) {
if (e.getMessage() != null) {
debug.println(key + ": " + e.getMessage());
} else {
debug.println(key + ": " + algorithm +
" was disabled, no exception msg given.");
e.printStackTrace();
}
}
return false;
}
permittedAlgs.put(algorithm, Boolean.TRUE);
return true;
}
// Algorithm has already been checked, return the value from map.
return permitted.booleanValue();
}
/**
* With a given header (*-DIGEST*), return a string that lists all the
* algorithms associated with the header.
* If there are none, return "Unknown Algorithm".
*/
String getWeakAlgorithms(String header) {
String w = "";
try {
for (String key : permittedAlgs.keySet()) {
if (key.endsWith(header)) {
w += key.substring(0, key.length() - header.length()) + " ";
}
}
} catch (RuntimeException e) {
w = "Unknown Algorithm(s). Error processing " + header + ". " +
e.getMessage();
}
// This means we have an error in finding weak algorithms, run in
// debug mode to see permittedAlgs map's values.
if (w.length() == 0) {
return "Unknown Algorithm(s)";
}
return w;
}
/** /**
* See if the whole manifest was signed. * See if the whole manifest was signed.
*/ */
...@@ -355,6 +433,10 @@ public class SignatureFileVerifier { ...@@ -355,6 +433,10 @@ public class SignatureFileVerifier {
{ {
Attributes mattr = sf.getMainAttributes(); Attributes mattr = sf.getMainAttributes();
boolean manifestSigned = false; boolean manifestSigned = false;
// If only weak algorithms are used.
boolean weakAlgs = true;
// If a "*-DIGEST-MANIFEST" entry is found.
boolean validEntry = false;
// go through all the attributes and process *-Digest-Manifest entries // go through all the attributes and process *-Digest-Manifest entries
for (Map.Entry<Object,Object> se : mattr.entrySet()) { for (Map.Entry<Object,Object> se : mattr.entrySet()) {
...@@ -364,6 +446,16 @@ public class SignatureFileVerifier { ...@@ -364,6 +446,16 @@ public class SignatureFileVerifier {
if (key.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST-MANIFEST")) { if (key.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST-MANIFEST")) {
// 16 is length of "-Digest-Manifest" // 16 is length of "-Digest-Manifest"
String algorithm = key.substring(0, key.length()-16); String algorithm = key.substring(0, key.length()-16);
validEntry = true;
// Check if this algorithm is permitted, skip if false.
if (!permittedCheck(key, algorithm)) {
continue;
}
// A non-weak algorithm was used, any weak algorithms found do
// not need to be reported.
weakAlgs = false;
manifestDigests.add(key); manifestDigests.add(key);
manifestDigests.add(se.getValue()); manifestDigests.add(se.getValue());
...@@ -374,15 +466,14 @@ public class SignatureFileVerifier { ...@@ -374,15 +466,14 @@ public class SignatureFileVerifier {
Base64.getMimeDecoder().decode((String)se.getValue()); Base64.getMimeDecoder().decode((String)se.getValue());
if (debug != null) { if (debug != null) {
debug.println("Signature File: Manifest digest " + debug.println("Signature File: Manifest digest " +
digest.getAlgorithm()); algorithm);
debug.println( " sigfile " + toHex(expectedHash)); debug.println( " sigfile " + toHex(expectedHash));
debug.println( " computed " + toHex(computedHash)); debug.println( " computed " + toHex(computedHash));
debug.println(); debug.println();
} }
if (MessageDigest.isEqual(computedHash, if (MessageDigest.isEqual(computedHash, expectedHash)) {
expectedHash)) {
manifestSigned = true; manifestSigned = true;
} else { } else {
//XXX: we will continue and verify each section //XXX: we will continue and verify each section
...@@ -390,15 +481,33 @@ public class SignatureFileVerifier { ...@@ -390,15 +481,33 @@ public class SignatureFileVerifier {
} }
} }
} }
if (debug != null) {
debug.println("PermittedAlgs mapping: ");
for (String key : permittedAlgs.keySet()) {
debug.println(key + " : " +
permittedAlgs.get(key).toString());
}
}
// If there were only weak algorithms entries used, throw an exception.
if (validEntry && weakAlgs) {
throw new SignatureException("Manifest hash check failed " +
"(DIGEST-MANIFEST). Disabled algorithm(s) used: " +
getWeakAlgorithms("-DIGEST-MANIFEST"));
}
return manifestSigned; return manifestSigned;
} }
private boolean verifyManifestMainAttrs(Manifest sf, private boolean verifyManifestMainAttrs(Manifest sf, ManifestDigester md)
ManifestDigester md)
throws IOException, SignatureException throws IOException, SignatureException
{ {
Attributes mattr = sf.getMainAttributes(); Attributes mattr = sf.getMainAttributes();
boolean attrsVerified = true; boolean attrsVerified = true;
// If only weak algorithms are used.
boolean weakAlgs = true;
// If a ATTR_DIGEST entry is found.
boolean validEntry = false;
// go through all the attributes and process // go through all the attributes and process
// digest entries for the manifest main attributes // digest entries for the manifest main attributes
...@@ -408,6 +517,16 @@ public class SignatureFileVerifier { ...@@ -408,6 +517,16 @@ public class SignatureFileVerifier {
if (key.toUpperCase(Locale.ENGLISH).endsWith(ATTR_DIGEST)) { if (key.toUpperCase(Locale.ENGLISH).endsWith(ATTR_DIGEST)) {
String algorithm = String algorithm =
key.substring(0, key.length() - ATTR_DIGEST.length()); key.substring(0, key.length() - ATTR_DIGEST.length());
validEntry = true;
// Check if this algorithm is permitted, skip if false.
if (!permittedCheck(key, algorithm)) {
continue;
}
// A non-weak algorithm was used, any weak algorithms found do
// not need to be reported.
weakAlgs = false;
MessageDigest digest = getDigest(algorithm); MessageDigest digest = getDigest(algorithm);
if (digest != null) { if (digest != null) {
...@@ -426,8 +545,7 @@ public class SignatureFileVerifier { ...@@ -426,8 +545,7 @@ public class SignatureFileVerifier {
debug.println(); debug.println();
} }
if (MessageDigest.isEqual(computedHash, if (MessageDigest.isEqual(computedHash, expectedHash)) {
expectedHash)) {
// good // good
} else { } else {
// we will *not* continue and verify each section // we will *not* continue and verify each section
...@@ -443,6 +561,22 @@ public class SignatureFileVerifier { ...@@ -443,6 +561,22 @@ public class SignatureFileVerifier {
} }
} }
if (debug != null) {
debug.println("PermittedAlgs mapping: ");
for (String key : permittedAlgs.keySet()) {
debug.println(key + " : " +
permittedAlgs.get(key).toString());
}
}
// If there were only weak algorithms entries used, throw an exception.
if (validEntry && weakAlgs) {
throw new SignatureException("Manifest Main Attribute check " +
"failed (" + ATTR_DIGEST + "). " +
"Disabled algorithm(s) used: " +
getWeakAlgorithms(ATTR_DIGEST));
}
// this method returns 'true' if either: // this method returns 'true' if either:
// . manifest main attributes were not signed, or // . manifest main attributes were not signed, or
// . manifest main attributes were signed and verified // . manifest main attributes were signed and verified
...@@ -465,6 +599,10 @@ public class SignatureFileVerifier { ...@@ -465,6 +599,10 @@ public class SignatureFileVerifier {
{ {
boolean oneDigestVerified = false; boolean oneDigestVerified = false;
ManifestDigester.Entry mde = md.get(name,block.isOldStyle()); ManifestDigester.Entry mde = md.get(name,block.isOldStyle());
// If only weak algorithms are used.
boolean weakAlgs = true;
// If a "*-DIGEST" entry is found.
boolean validEntry = false;
if (mde == null) { if (mde == null) {
throw new SecurityException( throw new SecurityException(
...@@ -472,8 +610,7 @@ public class SignatureFileVerifier { ...@@ -472,8 +610,7 @@ public class SignatureFileVerifier {
} }
if (sfAttr != null) { if (sfAttr != null) {
//sun.security.util.HexDumpEncoder hex = new sun.security.util.HexDumpEncoder();
//sun.misc.HexDumpEncoder hex = new sun.misc.HexDumpEncoder();
//hex.encodeBuffer(data, System.out); //hex.encodeBuffer(data, System.out);
// go through all the attributes and process *-Digest entries // go through all the attributes and process *-Digest entries
...@@ -483,6 +620,16 @@ public class SignatureFileVerifier { ...@@ -483,6 +620,16 @@ public class SignatureFileVerifier {
if (key.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST")) { if (key.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST")) {
// 7 is length of "-Digest" // 7 is length of "-Digest"
String algorithm = key.substring(0, key.length()-7); String algorithm = key.substring(0, key.length()-7);
validEntry = true;
// Check if this algorithm is permitted, skip if false.
if (!permittedCheck(key, algorithm)) {
continue;
}
// A non-weak algorithm was used, any weak algorithms found do
// not need to be reported.
weakAlgs = false;
MessageDigest digest = getDigest(algorithm); MessageDigest digest = getDigest(algorithm);
...@@ -533,6 +680,22 @@ public class SignatureFileVerifier { ...@@ -533,6 +680,22 @@ public class SignatureFileVerifier {
} }
} }
} }
if (debug != null) {
debug.println("PermittedAlgs mapping: ");
for (String key : permittedAlgs.keySet()) {
debug.println(key + " : " +
permittedAlgs.get(key).toString());
}
}
// If there were only weak algorithms entries used, throw an exception.
if (validEntry && weakAlgs) {
throw new SignatureException("Manifest Main Attribute check " +
"failed (DIGEST). Disabled algorithm(s) used: " +
getWeakAlgorithms("DIGEST"));
}
return oneDigestVerified; return oneDigestVerified;
} }
...@@ -541,7 +704,7 @@ public class SignatureFileVerifier { ...@@ -541,7 +704,7 @@ public class SignatureFileVerifier {
* CodeSigner objects. We do this only *once* for a given * CodeSigner objects. We do this only *once* for a given
* signature block file. * signature block file.
*/ */
private CodeSigner[] getSigners(SignerInfo infos[], PKCS7 block) private CodeSigner[] getSigners(SignerInfo[] infos, PKCS7 block)
throws IOException, NoSuchAlgorithmException, SignatureException, throws IOException, NoSuchAlgorithmException, SignatureException,
CertificateException { CertificateException {
...@@ -553,7 +716,7 @@ public class SignatureFileVerifier { ...@@ -553,7 +716,7 @@ public class SignatureFileVerifier {
ArrayList<X509Certificate> chain = info.getCertificateChain(block); ArrayList<X509Certificate> chain = info.getCertificateChain(block);
CertPath certChain = certificateFactory.generateCertPath(chain); CertPath certChain = certificateFactory.generateCertPath(chain);
if (signers == null) { if (signers == null) {
signers = new ArrayList<CodeSigner>(); signers = new ArrayList<>();
} }
// Append the new code signer // Append the new code signer
signers.add(new CodeSigner(certChain, info.getTimestamp())); signers.add(new CodeSigner(certChain, info.getTimestamp()));
...@@ -582,7 +745,7 @@ public class SignatureFileVerifier { ...@@ -582,7 +745,7 @@ public class SignatureFileVerifier {
static String toHex(byte[] data) { static String toHex(byte[] data) {
StringBuffer sb = new StringBuffer(data.length*2); StringBuilder sb = new StringBuilder(data.length*2);
for (int i=0; i<data.length; i++) { for (int i=0; i<data.length; i++) {
sb.append(hexc[(data[i] >>4) & 0x0f]); sb.append(hexc[(data[i] >>4) & 0x0f]);
......
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2017, 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,10 +33,11 @@ import java.security.cert.*; ...@@ -33,10 +33,11 @@ import java.security.cert.*;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import sun.security.action.GetBooleanAction; import sun.security.action.GetBooleanAction;
import sun.security.provider.certpath.AlgorithmChecker; import sun.security.provider.certpath.AlgorithmChecker;
import sun.security.provider.certpath.PKIXExtendedParameters;
/** /**
* Validator implementation built on the PKIX CertPath API. This * Validator implementation built on the PKIX CertPath API. This
* implementation will be emphasized going forward.<p> * implementation will be emphasized going forward.
* <p> * <p>
* Note that the validate() implementation tries to use a PKIX validator * Note that the validate() implementation tries to use a PKIX validator
* if that appears possible and a PKIX builder otherwise. This increases * if that appears possible and a PKIX builder otherwise. This increases
...@@ -208,13 +209,22 @@ public final class PKIXValidator extends Validator { ...@@ -208,13 +209,22 @@ public final class PKIXValidator extends Validator {
("null or zero-length certificate chain"); ("null or zero-length certificate chain");
} }
// add new algorithm constraints checker // Use PKIXExtendedParameters for timestamp and variant additions
PKIXBuilderParameters pkixParameters = PKIXBuilderParameters pkixParameters = null;
(PKIXBuilderParameters) parameterTemplate.clone(); try {
AlgorithmChecker algorithmChecker = null; pkixParameters = new PKIXExtendedParameters(
(PKIXBuilderParameters) parameterTemplate.clone(),
(parameter instanceof Timestamp) ?
(Timestamp) parameter : null,
variant);
} catch (InvalidAlgorithmParameterException e) {
// ignore exception
}
// add a new algorithm constraints checker
if (constraints != null) { if (constraints != null) {
algorithmChecker = new AlgorithmChecker(constraints); pkixParameters.addCertPathChecker(
pkixParameters.addCertPathChecker(algorithmChecker); new AlgorithmChecker(constraints, null, variant));
} }
if (TRY_VALIDATOR) { if (TRY_VALIDATOR) {
......
/* /*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2017, 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,6 +34,7 @@ import java.security.cert.*; ...@@ -34,6 +34,7 @@ import java.security.cert.*;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
import sun.security.x509.KeyIdentifier;
import sun.security.x509.NetscapeCertTypeExtension; import sun.security.x509.NetscapeCertTypeExtension;
import sun.security.util.DerValue; import sun.security.util.DerValue;
import sun.security.util.DerInputStream; import sun.security.util.DerInputStream;
...@@ -153,12 +154,14 @@ public final class SimpleValidator extends Validator { ...@@ -153,12 +154,14 @@ public final class SimpleValidator extends Validator {
// create default algorithm constraints checker // create default algorithm constraints checker
TrustAnchor anchor = new TrustAnchor(anchorCert, null); TrustAnchor anchor = new TrustAnchor(anchorCert, null);
AlgorithmChecker defaultAlgChecker = new AlgorithmChecker(anchor); AlgorithmChecker defaultAlgChecker =
new AlgorithmChecker(anchor, variant);
// create application level algorithm constraints checker // create application level algorithm constraints checker
AlgorithmChecker appAlgChecker = null; AlgorithmChecker appAlgChecker = null;
if (constraints != null) { if (constraints != null) {
appAlgChecker = new AlgorithmChecker(anchor, constraints); appAlgChecker = new AlgorithmChecker(anchor, constraints, null,
null, variant);
} }
// verify top down, starting at the certificate issued by // verify top down, starting at the certificate issued by
......
/* /*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, 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
...@@ -49,34 +49,39 @@ import sun.security.util.*; ...@@ -49,34 +49,39 @@ import sun.security.util.*;
*/ */
public class PKIXExtensions { public class PKIXExtensions {
// The object identifiers // The object identifiers
private static final int AuthorityKey_data [] = { 2, 5, 29, 35 }; private static final int[] AuthorityKey_data = { 2, 5, 29, 35 };
private static final int SubjectKey_data [] = { 2, 5, 29, 14 }; private static final int[] SubjectKey_data = { 2, 5, 29, 14 };
private static final int KeyUsage_data [] = { 2, 5, 29, 15 }; private static final int[] KeyUsage_data = { 2, 5, 29, 15 };
private static final int PrivateKeyUsage_data [] = { 2, 5, 29, 16 }; private static final int[] PrivateKeyUsage_data = { 2, 5, 29, 16 };
private static final int CertificatePolicies_data [] = { 2, 5, 29, 32 }; private static final int[] CertificatePolicies_data = { 2, 5, 29, 32 };
private static final int PolicyMappings_data [] = { 2, 5, 29, 33 }; private static final int[] PolicyMappings_data = { 2, 5, 29, 33 };
private static final int SubjectAlternativeName_data [] = { 2, 5, 29, 17 }; private static final int[] SubjectAlternativeName_data = { 2, 5, 29, 17 };
private static final int IssuerAlternativeName_data [] = { 2, 5, 29, 18 }; private static final int[] IssuerAlternativeName_data = { 2, 5, 29, 18 };
private static final int SubjectDirectoryAttributes_data [] = { 2, 5, 29, 9 }; private static final int[] SubjectDirectoryAttributes_data = { 2, 5, 29, 9 };
private static final int BasicConstraints_data [] = { 2, 5, 29, 19 }; private static final int[] BasicConstraints_data = { 2, 5, 29, 19 };
private static final int NameConstraints_data [] = { 2, 5, 29, 30 }; private static final int[] NameConstraints_data = { 2, 5, 29, 30 };
private static final int PolicyConstraints_data [] = { 2, 5, 29, 36 }; private static final int[] PolicyConstraints_data = { 2, 5, 29, 36 };
private static final int CRLDistributionPoints_data [] = { 2, 5, 29, 31 }; private static final int[] CRLDistributionPoints_data = { 2, 5, 29, 31 };
private static final int CRLNumber_data [] = { 2, 5, 29, 20 }; private static final int[] CRLNumber_data = { 2, 5, 29, 20 };
private static final int IssuingDistributionPoint_data [] = { 2, 5, 29, 28 }; private static final int[] IssuingDistributionPoint_data = { 2, 5, 29, 28 };
private static final int DeltaCRLIndicator_data [] = { 2, 5, 29, 27 }; private static final int[] DeltaCRLIndicator_data = { 2, 5, 29, 27 };
private static final int ReasonCode_data [] = { 2, 5, 29, 21 }; private static final int[] ReasonCode_data = { 2, 5, 29, 21 };
private static final int HoldInstructionCode_data [] = { 2, 5, 29, 23 }; private static final int[] HoldInstructionCode_data = { 2, 5, 29, 23 };
private static final int InvalidityDate_data [] = { 2, 5, 29, 24 }; private static final int[] InvalidityDate_data = { 2, 5, 29, 24 };
private static final int ExtendedKeyUsage_data [] = { 2, 5, 29, 37 }; private static final int[] ExtendedKeyUsage_data = { 2, 5, 29, 37 };
private static final int InhibitAnyPolicy_data [] = { 2, 5, 29, 54 }; private static final int[] InhibitAnyPolicy_data = { 2, 5, 29, 54 };
private static final int CertificateIssuer_data [] = { 2, 5, 29, 29 }; private static final int[] CertificateIssuer_data = { 2, 5, 29, 29 };
private static final int AuthInfoAccess_data [] = { 1, 3, 6, 1, 5, 5, 7, 1, 1}; private static final int[] AuthInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 1};
private static final int SubjectInfoAccess_data [] = { 1, 3, 6, 1, 5, 5, 7, 1, 11}; private static final int[] SubjectInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 11};
private static final int FreshestCRL_data [] = { 2, 5, 29, 46 }; private static final int[] FreshestCRL_data = { 2, 5, 29, 46 };
private static final int OCSPNoCheck_data [] = { 1, 3, 6, 1, 5, 5, 7, private static final int[] OCSPNoCheck_data = { 1, 3, 6, 1, 5, 5, 7,
48, 1, 5}; 48, 1, 5};
// Additional extensions under the PKIX arc that are not necessarily
// used in X.509 Certificates or CRLs.
private static final int[] OCSPNonce_data = { 1, 3, 6, 1, 5, 5, 7,
48, 1, 2};
/** /**
* Identifies the particular public key used to sign the certificate. * Identifies the particular public key used to sign the certificate.
*/ */
...@@ -104,18 +109,20 @@ public class PKIXExtensions { ...@@ -104,18 +109,20 @@ public class PKIXExtensions {
public static final ObjectIdentifier CertificatePolicies_Id; public static final ObjectIdentifier CertificatePolicies_Id;
/** /**
* Lists pairs of objectidentifiers of policies considered equivalent by the * Lists pairs of object identifiers of policies considered equivalent by
* issuing CA to the subject CA. * the issuing CA to the subject CA.
*/ */
public static final ObjectIdentifier PolicyMappings_Id; public static final ObjectIdentifier PolicyMappings_Id;
/** /**
* Allows additional identities to be bound to the subject of the certificate. * Allows additional identities to be bound to the subject of the
* certificate.
*/ */
public static final ObjectIdentifier SubjectAlternativeName_Id; public static final ObjectIdentifier SubjectAlternativeName_Id;
/** /**
* Allows additional identities to be associated with the certificate issuer. * Allows additional identities to be associated with the certificate
* issuer.
*/ */
public static final ObjectIdentifier IssuerAlternativeName_Id; public static final ObjectIdentifier IssuerAlternativeName_Id;
...@@ -224,6 +231,12 @@ public class PKIXExtensions { ...@@ -224,6 +231,12 @@ public class PKIXExtensions {
*/ */
public static final ObjectIdentifier OCSPNoCheck_Id; public static final ObjectIdentifier OCSPNoCheck_Id;
/**
* This extension is used to provide nonce data for OCSP requests
* or responses.
*/
public static final ObjectIdentifier OCSPNonce_Id;
static { static {
AuthorityKey_Id = ObjectIdentifier.newInternal(AuthorityKey_data); AuthorityKey_Id = ObjectIdentifier.newInternal(AuthorityKey_data);
SubjectKey_Id = ObjectIdentifier.newInternal(SubjectKey_data); SubjectKey_Id = ObjectIdentifier.newInternal(SubjectKey_data);
...@@ -266,5 +279,6 @@ public class PKIXExtensions { ...@@ -266,5 +279,6 @@ public class PKIXExtensions {
ObjectIdentifier.newInternal(SubjectInfoAccess_data); ObjectIdentifier.newInternal(SubjectInfoAccess_data);
FreshestCRL_Id = ObjectIdentifier.newInternal(FreshestCRL_data); FreshestCRL_Id = ObjectIdentifier.newInternal(FreshestCRL_data);
OCSPNoCheck_Id = ObjectIdentifier.newInternal(OCSPNoCheck_data); OCSPNoCheck_Id = ObjectIdentifier.newInternal(OCSPNoCheck_data);
OCSPNonce_Id = ObjectIdentifier.newInternal(OCSPNonce_data);
} }
} }
...@@ -422,9 +422,7 @@ krb5.kdc.bad.policy = tryLast ...@@ -422,9 +422,7 @@ krb5.kdc.bad.policy = tryLast
# describes the mechanism for disabling algorithms based on algorithm name # describes the mechanism for disabling algorithms based on algorithm name
# and/or key length. This includes algorithms used in certificates, as well # and/or key length. This includes algorithms used in certificates, as well
# as revocation information such as CRLs and signed OCSP Responses. # as revocation information such as CRLs and signed OCSP Responses.
# # The syntax of the disabled algorithm string is described as follows:
# The syntax of the disabled algorithm string is described as this Java
# BNF-style:
# DisabledAlgorithms: # DisabledAlgorithms:
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
...@@ -435,25 +433,26 @@ krb5.kdc.bad.policy = tryLast ...@@ -435,25 +433,26 @@ krb5.kdc.bad.policy = tryLast
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint, CertConstraint # KeySizeConstraint | CAConstraint | DenyAfterConstraint |
# UsageConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator DecimalInteger # keySize Operator KeyLength
# #
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
# DecimalInteger: # KeyLength:
# DecimalDigits # Integer value of the algorithm's key length in bits
# #
# DecimalDigits: # CAConstraint:
# DecimalDigit {DecimalDigit} # jdkCA
# #
# DecimalDigit: one of # DenyAfterConstraint:
# 1 2 3 4 5 6 7 8 9 0 # denyAfter YYYY-MM-DD
# #
# CertConstraint # UsageConstraint:
# jdkCA # usage [TLSServer] [TLSClient] [SignedJAR]
# #
# The "AlgorithmName" is the standard algorithm name of the disabled # The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
...@@ -467,27 +466,55 @@ krb5.kdc.bad.policy = tryLast ...@@ -467,27 +466,55 @@ krb5.kdc.bad.policy = tryLast
# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion
# will not disable algorithms related to "ECDSA". # will not disable algorithms related to "ECDSA".
# #
# A "Constraint" provides further guidance for the algorithm being specified. # A "Constraint" defines restrictions on the keys and/or certificates for
# The "KeySizeConstraint" requires a key of a valid size range if the # a specified AlgorithmName:
# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the #
# key size specified in number of bits. For example, "RSA keySize <= 1024" # KeySizeConstraint:
# indicates that any RSA key with key size less than or equal to 1024 bits # keySize Operator KeyLength
# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates # The constraint requires a key of a valid size range if the
# that any RSA key with key size less than 1024 or greater than 2048 should # "AlgorithmName" is of a key algorithm. The "KeyLength" indicates
# be disabled. Note that the "KeySizeConstraint" only makes sense to key # the key size specified in number of bits. For example,
# algorithms. # "RSA keySize <= 1024" indicates that any RSA key with key size less
# # than or equal to 1024 bits should be disabled, and
# "CertConstraint" specifies additional constraints for # "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key
# certificates that contain algorithms that are restricted: # with key size less than 1024 or greater than 2048 should be disabled.
# # This constraint is only used on algorithms that have a key size.
# "jdkCA" prohibits the specified algorithm only if the algorithm is used #
# in a certificate chain that terminates at a marked trust anchor in the # CAConstraint:
# lib/security/cacerts keystore. All other chains are not affected. # jdkCA
# If the jdkCA constraint is not set, then all chains using the # This constraint prohibits the specified algorithm only if the
# specified algorithm are restricted. jdkCA may only be used once in # algorithm is used in a certificate chain that terminates at a marked
# a DisabledAlgorithm expression. # trust anchor in the lib/security/cacerts keystore. If the jdkCA
# Example: To apply this constraint to SHA-1 certificates, include # constraint is not set, then all chains using the specified algorithm
# the following "SHA1 jdkCA" # are restricted. jdkCA may only be used once in a DisabledAlgorithm
# expression.
# Example:  To apply this constraint to SHA-1 certificates, include
# the following:  "SHA1 jdkCA"
#
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
# This constraint prohibits a certificate with the specified algorithm
# from being used after the date regardless of the certificate's
# validity.  JAR files that are signed and timestamped before the
# constraint date with certificates containing the disabled algorithm
# will not be restricted.  The date is processed in the UTC timezone.
# This constraint can only be used once in a DisabledAlgorithm
# expression.
# Example: To deny usage of RSA 2048 bit certificates after Feb 3 2020,
# use the following: "RSA keySize == 2048 & denyAfter 2020-02-03"
#
# UsageConstraint:
# usage [TLSServer] [TLSClient] [SignedJAR]
# This constraint prohibits the specified algorithm for
# a specified usage. This should be used when disabling an algorithm
# for all usages is not practical. 'TLSServer' restricts the algorithm
# in TLS server certificate chains when server authentication is
# performed. 'TLSClient' restricts the algorithm in TLS client
# certificate chains when client authentication is performed.
# 'SignedJAR' constrains use of certificates in signed jar files.
# The usage type follows the keyword and more than one usage type can
# be specified with a whitespace delimiter.
# Example: "SHA1 usage TLSServer TLSClient"
# #
# When an algorithm must satisfy more than one constraint, it must be # When an algorithm must satisfy more than one constraint, it must be
# delimited by an ampersand '&'. For example, to restrict certificates in a # delimited by an ampersand '&'. For example, to restrict certificates in a
...@@ -500,6 +527,9 @@ krb5.kdc.bad.policy = tryLast ...@@ -500,6 +527,9 @@ krb5.kdc.bad.policy = tryLast
# before larger keysize constraints of the same algorithm. For example: # before larger keysize constraints of the same algorithm. For example:
# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". # "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by Oracle's PKIX implementation. It # Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations. # is not guaranteed to be examined and used by other implementations.
# #
...@@ -507,9 +537,10 @@ krb5.kdc.bad.policy = tryLast ...@@ -507,9 +537,10 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
# #
# #
jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
DSA keySize < 1024, EC keySize < 224 RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
#
# Algorithm restrictions for signed JAR files # Algorithm restrictions for signed JAR files
# #
# In some environments, certain algorithms or key lengths may be undesirable # In some environments, certain algorithms or key lengths may be undesirable
...@@ -524,17 +555,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -524,17 +555,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
# DisabledAlgorithm: # DisabledAlgorithm:
# AlgorithmName [Constraint] # AlgorithmName [Constraint] { '&' Constraint }
# #
# AlgorithmName: # AlgorithmName:
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint # KeySizeConstraint | DenyAfterConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator KeyLength # keySize Operator KeyLength
# #
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
#
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
...@@ -545,8 +579,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -545,8 +579,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# implementation. It is not guaranteed to be examined and used by other # implementation. It is not guaranteed to be examined and used by other
# implementations. # implementations.
# #
# See "jdk.certpath.disabledAlgorithms" for syntax descriptions.
#
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
#
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing # (SSL/TLS) processing
# #
...@@ -568,6 +605,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 ...@@ -568,6 +605,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the # See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string. # syntax of the disabled algorithm string.
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by the JDK Reference implementation. # Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations. # It is not guaranteed to be examined and used by other implementations.
# #
......
...@@ -422,9 +422,7 @@ krb5.kdc.bad.policy = tryLast ...@@ -422,9 +422,7 @@ krb5.kdc.bad.policy = tryLast
# describes the mechanism for disabling algorithms based on algorithm name # describes the mechanism for disabling algorithms based on algorithm name
# and/or key length. This includes algorithms used in certificates, as well # and/or key length. This includes algorithms used in certificates, as well
# as revocation information such as CRLs and signed OCSP Responses. # as revocation information such as CRLs and signed OCSP Responses.
# # The syntax of the disabled algorithm string is described as follows:
# The syntax of the disabled algorithm string is described as this Java
# BNF-style:
# DisabledAlgorithms: # DisabledAlgorithms:
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
...@@ -435,25 +433,26 @@ krb5.kdc.bad.policy = tryLast ...@@ -435,25 +433,26 @@ krb5.kdc.bad.policy = tryLast
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint, CertConstraint # KeySizeConstraint | CAConstraint | DenyAfterConstraint |
# UsageConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator DecimalInteger # keySize Operator KeyLength
# #
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
# DecimalInteger: # KeyLength:
# DecimalDigits # Integer value of the algorithm's key length in bits
# #
# DecimalDigits: # CAConstraint:
# DecimalDigit {DecimalDigit} # jdkCA
# #
# DecimalDigit: one of # DenyAfterConstraint:
# 1 2 3 4 5 6 7 8 9 0 # denyAfter YYYY-MM-DD
# #
# CertConstraint # UsageConstraint:
# jdkCA # usage [TLSServer] [TLSClient] [SignedJAR]
# #
# The "AlgorithmName" is the standard algorithm name of the disabled # The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
...@@ -467,27 +466,55 @@ krb5.kdc.bad.policy = tryLast ...@@ -467,27 +466,55 @@ krb5.kdc.bad.policy = tryLast
# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion
# will not disable algorithms related to "ECDSA". # will not disable algorithms related to "ECDSA".
# #
# A "Constraint" provides further guidance for the algorithm being specified. # A "Constraint" defines restrictions on the keys and/or certificates for
# The "KeySizeConstraint" requires a key of a valid size range if the # a specified AlgorithmName:
# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the #
# key size specified in number of bits. For example, "RSA keySize <= 1024" # KeySizeConstraint:
# indicates that any RSA key with key size less than or equal to 1024 bits # keySize Operator KeyLength
# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates # The constraint requires a key of a valid size range if the
# that any RSA key with key size less than 1024 or greater than 2048 should # "AlgorithmName" is of a key algorithm. The "KeyLength" indicates
# be disabled. Note that the "KeySizeConstraint" only makes sense to key # the key size specified in number of bits. For example,
# algorithms. # "RSA keySize <= 1024" indicates that any RSA key with key size less
# # than or equal to 1024 bits should be disabled, and
# "CertConstraint" specifies additional constraints for # "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key
# certificates that contain algorithms that are restricted: # with key size less than 1024 or greater than 2048 should be disabled.
# # This constraint is only used on algorithms that have a key size.
# "jdkCA" prohibits the specified algorithm only if the algorithm is used #
# in a certificate chain that terminates at a marked trust anchor in the # CAConstraint:
# lib/security/cacerts keystore. All other chains are not affected. # jdkCA
# If the jdkCA constraint is not set, then all chains using the # This constraint prohibits the specified algorithm only if the
# specified algorithm are restricted. jdkCA may only be used once in # algorithm is used in a certificate chain that terminates at a marked
# a DisabledAlgorithm expression. # trust anchor in the lib/security/cacerts keystore. If the jdkCA
# Example: To apply this constraint to SHA-1 certificates, include # constraint is not set, then all chains using the specified algorithm
# the following: "SHA1 jdkCA" # are restricted. jdkCA may only be used once in a DisabledAlgorithm
# expression.
# Example:  To apply this constraint to SHA-1 certificates, include
# the following:  "SHA1 jdkCA"
#
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
# This constraint prohibits a certificate with the specified algorithm
# from being used after the date regardless of the certificate's
# validity.  JAR files that are signed and timestamped before the
# constraint date with certificates containing the disabled algorithm
# will not be restricted.  The date is processed in the UTC timezone.
# This constraint can only be used once in a DisabledAlgorithm
# expression.
# Example: To deny usage of RSA 2048 bit certificates after Feb 3 2020,
# use the following: "RSA keySize == 2048 & denyAfter 2020-02-03"
#
# UsageConstraint:
# usage [TLSServer] [TLSClient] [SignedJAR]
# This constraint prohibits the specified algorithm for
# a specified usage. This should be used when disabling an algorithm
# for all usages is not practical. 'TLSServer' restricts the algorithm
# in TLS server certificate chains when server authentication is
# performed. 'TLSClient' restricts the algorithm in TLS client
# certificate chains when client authentication is performed.
# 'SignedJAR' constrains use of certificates in signed jar files.
# The usage type follows the keyword and more than one usage type can
# be specified with a whitespace delimiter.
# Example: "SHA1 usage TLSServer TLSClient"
# #
# When an algorithm must satisfy more than one constraint, it must be # When an algorithm must satisfy more than one constraint, it must be
# delimited by an ampersand '&'. For example, to restrict certificates in a # delimited by an ampersand '&'. For example, to restrict certificates in a
...@@ -500,6 +527,9 @@ krb5.kdc.bad.policy = tryLast ...@@ -500,6 +527,9 @@ krb5.kdc.bad.policy = tryLast
# before larger keysize constraints of the same algorithm. For example: # before larger keysize constraints of the same algorithm. For example:
# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". # "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by Oracle's PKIX implementation. It # Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations. # is not guaranteed to be examined and used by other implementations.
# #
...@@ -507,9 +537,10 @@ krb5.kdc.bad.policy = tryLast ...@@ -507,9 +537,10 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
# #
# #
jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
DSA keySize < 1024, EC keySize < 224 RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
#
# Algorithm restrictions for signed JAR files # Algorithm restrictions for signed JAR files
# #
# In some environments, certain algorithms or key lengths may be undesirable # In some environments, certain algorithms or key lengths may be undesirable
...@@ -524,17 +555,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -524,17 +555,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
# DisabledAlgorithm: # DisabledAlgorithm:
# AlgorithmName [Constraint] # AlgorithmName [Constraint] { '&' Constraint }
# #
# AlgorithmName: # AlgorithmName:
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint # KeySizeConstraint | DenyAfterConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator KeyLength # keySize Operator KeyLength
# #
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
#
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
...@@ -545,8 +579,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -545,8 +579,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# implementation. It is not guaranteed to be examined and used by other # implementation. It is not guaranteed to be examined and used by other
# implementations. # implementations.
# #
# See "jdk.certpath.disabledAlgorithms" for syntax descriptions.
#
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
#
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing # (SSL/TLS) processing
# #
...@@ -568,6 +605,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 ...@@ -568,6 +605,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the # See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string. # syntax of the disabled algorithm string.
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by the JDK Reference implementation. # Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations. # It is not guaranteed to be examined and used by other implementations.
# #
......
...@@ -425,9 +425,7 @@ krb5.kdc.bad.policy = tryLast ...@@ -425,9 +425,7 @@ krb5.kdc.bad.policy = tryLast
# describes the mechanism for disabling algorithms based on algorithm name # describes the mechanism for disabling algorithms based on algorithm name
# and/or key length. This includes algorithms used in certificates, as well # and/or key length. This includes algorithms used in certificates, as well
# as revocation information such as CRLs and signed OCSP Responses. # as revocation information such as CRLs and signed OCSP Responses.
# # The syntax of the disabled algorithm string is described as follows:
# The syntax of the disabled algorithm string is described as this Java
# BNF-style:
# DisabledAlgorithms: # DisabledAlgorithms:
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
...@@ -438,25 +436,26 @@ krb5.kdc.bad.policy = tryLast ...@@ -438,25 +436,26 @@ krb5.kdc.bad.policy = tryLast
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint, CertConstraint # KeySizeConstraint | CAConstraint | DenyAfterConstraint |
# UsageConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator DecimalInteger # keySize Operator KeyLength
# #
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
# DecimalInteger: # KeyLength:
# DecimalDigits # Integer value of the algorithm's key length in bits
# #
# DecimalDigits: # CAConstraint:
# DecimalDigit {DecimalDigit} # jdkCA
# #
# DecimalDigit: one of # DenyAfterConstraint:
# 1 2 3 4 5 6 7 8 9 0 # denyAfter YYYY-MM-DD
# #
# CertConstraint # UsageConstraint:
# jdkCA # usage [TLSServer] [TLSClient] [SignedJAR]
# #
# The "AlgorithmName" is the standard algorithm name of the disabled # The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
...@@ -470,27 +469,55 @@ krb5.kdc.bad.policy = tryLast ...@@ -470,27 +469,55 @@ krb5.kdc.bad.policy = tryLast
# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion
# will not disable algorithms related to "ECDSA". # will not disable algorithms related to "ECDSA".
# #
# A "Constraint" provides further guidance for the algorithm being specified. # A "Constraint" defines restrictions on the keys and/or certificates for
# The "KeySizeConstraint" requires a key of a valid size range if the # a specified AlgorithmName:
# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the #
# key size specified in number of bits. For example, "RSA keySize <= 1024" # KeySizeConstraint:
# indicates that any RSA key with key size less than or equal to 1024 bits # keySize Operator KeyLength
# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates # The constraint requires a key of a valid size range if the
# that any RSA key with key size less than 1024 or greater than 2048 should # "AlgorithmName" is of a key algorithm. The "KeyLength" indicates
# be disabled. Note that the "KeySizeConstraint" only makes sense to key # the key size specified in number of bits. For example,
# algorithms. # "RSA keySize <= 1024" indicates that any RSA key with key size less
# # than or equal to 1024 bits should be disabled, and
# "CertConstraint" specifies additional constraints for # "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key
# certificates that contain algorithms that are restricted: # with key size less than 1024 or greater than 2048 should be disabled.
# # This constraint is only used on algorithms that have a key size.
# "jdkCA" prohibits the specified algorithm only if the algorithm is used #
# in a certificate chain that terminates at a marked trust anchor in the # CAConstraint:
# lib/security/cacerts keystore. All other chains are not affected. # jdkCA
# If the jdkCA constraint is not set, then all chains using the # This constraint prohibits the specified algorithm only if the
# specified algorithm are restricted. jdkCA may only be used once in # algorithm is used in a certificate chain that terminates at a marked
# a DisabledAlgorithm expression. # trust anchor in the lib/security/cacerts keystore. If the jdkCA
# Example: To apply this constraint to SHA-1 certificates, include # constraint is not set, then all chains using the specified algorithm
# the following: "SHA1 jdkCA" # are restricted. jdkCA may only be used once in a DisabledAlgorithm
# expression.
# Example:  To apply this constraint to SHA-1 certificates, include
# the following:  "SHA1 jdkCA"
#
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
# This constraint prohibits a certificate with the specified algorithm
# from being used after the date regardless of the certificate's
# validity.  JAR files that are signed and timestamped before the
# constraint date with certificates containing the disabled algorithm
# will not be restricted.  The date is processed in the UTC timezone.
# This constraint can only be used once in a DisabledAlgorithm
# expression.
# Example: To deny usage of RSA 2048 bit certificates after Feb 3 2020,
# use the following: "RSA keySize == 2048 & denyAfter 2020-02-03"
#
# UsageConstraint:
# usage [TLSServer] [TLSClient] [SignedJAR]
# This constraint prohibits the specified algorithm for
# a specified usage. This should be used when disabling an algorithm
# for all usages is not practical. 'TLSServer' restricts the algorithm
# in TLS server certificate chains when server authentication is
# performed. 'TLSClient' restricts the algorithm in TLS client
# certificate chains when client authentication is performed.
# 'SignedJAR' constrains use of certificates in signed jar files.
# The usage type follows the keyword and more than one usage type can
# be specified with a whitespace delimiter.
# Example: "SHA1 usage TLSServer TLSClient"
# #
# When an algorithm must satisfy more than one constraint, it must be # When an algorithm must satisfy more than one constraint, it must be
# delimited by an ampersand '&'. For example, to restrict certificates in a # delimited by an ampersand '&'. For example, to restrict certificates in a
...@@ -503,6 +530,9 @@ krb5.kdc.bad.policy = tryLast ...@@ -503,6 +530,9 @@ krb5.kdc.bad.policy = tryLast
# before larger keysize constraints of the same algorithm. For example: # before larger keysize constraints of the same algorithm. For example:
# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". # "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by Oracle's PKIX implementation. It # Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations. # is not guaranteed to be examined and used by other implementations.
# #
...@@ -510,9 +540,10 @@ krb5.kdc.bad.policy = tryLast ...@@ -510,9 +540,10 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
# #
# #
jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
DSA keySize < 1024, EC keySize < 224 RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
#
# Algorithm restrictions for signed JAR files # Algorithm restrictions for signed JAR files
# #
# In some environments, certain algorithms or key lengths may be undesirable # In some environments, certain algorithms or key lengths may be undesirable
...@@ -527,17 +558,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -527,17 +558,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
# DisabledAlgorithm: # DisabledAlgorithm:
# AlgorithmName [Constraint] # AlgorithmName [Constraint] { '&' Constraint }
# #
# AlgorithmName: # AlgorithmName:
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint # KeySizeConstraint | DenyAfterConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator KeyLength # keySize Operator KeyLength
# #
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
#
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
...@@ -548,8 +582,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -548,8 +582,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# implementation. It is not guaranteed to be examined and used by other # implementation. It is not guaranteed to be examined and used by other
# implementations. # implementations.
# #
# See "jdk.certpath.disabledAlgorithms" for syntax descriptions.
#
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
#
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing # (SSL/TLS) processing
# #
...@@ -571,6 +608,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 ...@@ -571,6 +608,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the # See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string. # syntax of the disabled algorithm string.
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by the JDK Reference implementation. # Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations. # It is not guaranteed to be examined and used by other implementations.
# #
......
...@@ -424,9 +424,7 @@ krb5.kdc.bad.policy = tryLast ...@@ -424,9 +424,7 @@ krb5.kdc.bad.policy = tryLast
# describes the mechanism for disabling algorithms based on algorithm name # describes the mechanism for disabling algorithms based on algorithm name
# and/or key length. This includes algorithms used in certificates, as well # and/or key length. This includes algorithms used in certificates, as well
# as revocation information such as CRLs and signed OCSP Responses. # as revocation information such as CRLs and signed OCSP Responses.
# # The syntax of the disabled algorithm string is described as follows:
# The syntax of the disabled algorithm string is described as this Java
# BNF-style:
# DisabledAlgorithms: # DisabledAlgorithms:
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
...@@ -437,25 +435,26 @@ krb5.kdc.bad.policy = tryLast ...@@ -437,25 +435,26 @@ krb5.kdc.bad.policy = tryLast
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint, CertConstraint # KeySizeConstraint | CAConstraint | DenyAfterConstraint |
# UsageConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator DecimalInteger # keySize Operator KeyLength
# #
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
# DecimalInteger: # KeyLength:
# DecimalDigits # Integer value of the algorithm's key length in bits
# #
# DecimalDigits: # CAConstraint:
# DecimalDigit {DecimalDigit} # jdkCA
# #
# DecimalDigit: one of # DenyAfterConstraint:
# 1 2 3 4 5 6 7 8 9 0 # denyAfter YYYY-MM-DD
# #
# CertConstraint # UsageConstraint:
# jdkCA # usage [TLSServer] [TLSClient] [SignedJAR]
# #
# The "AlgorithmName" is the standard algorithm name of the disabled # The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
...@@ -469,27 +468,55 @@ krb5.kdc.bad.policy = tryLast ...@@ -469,27 +468,55 @@ krb5.kdc.bad.policy = tryLast
# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion
# will not disable algorithms related to "ECDSA". # will not disable algorithms related to "ECDSA".
# #
# A "Constraint" provides further guidance for the algorithm being specified. # A "Constraint" defines restrictions on the keys and/or certificates for
# The "KeySizeConstraint" requires a key of a valid size range if the # a specified AlgorithmName:
# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the #
# key size specified in number of bits. For example, "RSA keySize <= 1024" # KeySizeConstraint:
# indicates that any RSA key with key size less than or equal to 1024 bits # keySize Operator KeyLength
# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates # The constraint requires a key of a valid size range if the
# that any RSA key with key size less than 1024 or greater than 2048 should # "AlgorithmName" is of a key algorithm. The "KeyLength" indicates
# be disabled. Note that the "KeySizeConstraint" only makes sense to key # the key size specified in number of bits. For example,
# algorithms. # "RSA keySize <= 1024" indicates that any RSA key with key size less
# # than or equal to 1024 bits should be disabled, and
# "CertConstraint" specifies additional constraints for # "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key
# certificates that contain algorithms that are restricted: # with key size less than 1024 or greater than 2048 should be disabled.
# # This constraint is only used on algorithms that have a key size.
# "jdkCA" prohibits the specified algorithm only if the algorithm is used #
# in a certificate chain that terminates at a marked trust anchor in the # CAConstraint:
# lib/security/cacerts keystore. All other chains are not affected. # jdkCA
# If the jdkCA constraint is not set, then all chains using the # This constraint prohibits the specified algorithm only if the
# specified algorithm are restricted. jdkCA may only be used once in # algorithm is used in a certificate chain that terminates at a marked
# a DisabledAlgorithm expression. # trust anchor in the lib/security/cacerts keystore. If the jdkCA
# Example: To apply this constraint to SHA-1 certificates, include # constraint is not set, then all chains using the specified algorithm
# the following: "SHA1 jdkCA" # are restricted. jdkCA may only be used once in a DisabledAlgorithm
# expression.
# Example:  To apply this constraint to SHA-1 certificates, include
# the following:  "SHA1 jdkCA"
#
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
# This constraint prohibits a certificate with the specified algorithm
# from being used after the date regardless of the certificate's
# validity.  JAR files that are signed and timestamped before the
# constraint date with certificates containing the disabled algorithm
# will not be restricted.  The date is processed in the UTC timezone.
# This constraint can only be used once in a DisabledAlgorithm
# expression.
# Example: To deny usage of RSA 2048 bit certificates after Feb 3 2020,
# use the following: "RSA keySize == 2048 & denyAfter 2020-02-03"
#
# UsageConstraint:
# usage [TLSServer] [TLSClient] [SignedJAR]
# This constraint prohibits the specified algorithm for
# a specified usage. This should be used when disabling an algorithm
# for all usages is not practical. 'TLSServer' restricts the algorithm
# in TLS server certificate chains when server authentication is
# performed. 'TLSClient' restricts the algorithm in TLS client
# certificate chains when client authentication is performed.
# 'SignedJAR' constrains use of certificates in signed jar files.
# The usage type follows the keyword and more than one usage type can
# be specified with a whitespace delimiter.
# Example: "SHA1 usage TLSServer TLSClient"
# #
# When an algorithm must satisfy more than one constraint, it must be # When an algorithm must satisfy more than one constraint, it must be
# delimited by an ampersand '&'. For example, to restrict certificates in a # delimited by an ampersand '&'. For example, to restrict certificates in a
...@@ -502,6 +529,9 @@ krb5.kdc.bad.policy = tryLast ...@@ -502,6 +529,9 @@ krb5.kdc.bad.policy = tryLast
# before larger keysize constraints of the same algorithm. For example: # before larger keysize constraints of the same algorithm. For example:
# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". # "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by Oracle's PKIX implementation. It # Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations. # is not guaranteed to be examined and used by other implementations.
# #
...@@ -509,9 +539,10 @@ krb5.kdc.bad.policy = tryLast ...@@ -509,9 +539,10 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
# #
# #
jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
DSA keySize < 1024, EC keySize < 224 RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
#
# Algorithm restrictions for signed JAR files # Algorithm restrictions for signed JAR files
# #
# In some environments, certain algorithms or key lengths may be undesirable # In some environments, certain algorithms or key lengths may be undesirable
...@@ -526,17 +557,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -526,17 +557,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
# DisabledAlgorithm: # DisabledAlgorithm:
# AlgorithmName [Constraint] # AlgorithmName [Constraint] { '&' Constraint }
# #
# AlgorithmName: # AlgorithmName:
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint # KeySizeConstraint | DenyAfterConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator KeyLength # keySize Operator KeyLength
# #
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
#
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
...@@ -547,8 +581,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -547,8 +581,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# implementation. It is not guaranteed to be examined and used by other # implementation. It is not guaranteed to be examined and used by other
# implementations. # implementations.
# #
# See "jdk.certpath.disabledAlgorithms" for syntax descriptions.
#
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
#
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing # (SSL/TLS) processing
# #
...@@ -570,6 +607,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 ...@@ -570,6 +607,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the # See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string. # syntax of the disabled algorithm string.
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by the JDK Reference implementation. # Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations. # It is not guaranteed to be examined and used by other implementations.
# #
......
...@@ -425,9 +425,7 @@ krb5.kdc.bad.policy = tryLast ...@@ -425,9 +425,7 @@ krb5.kdc.bad.policy = tryLast
# describes the mechanism for disabling algorithms based on algorithm name # describes the mechanism for disabling algorithms based on algorithm name
# and/or key length. This includes algorithms used in certificates, as well # and/or key length. This includes algorithms used in certificates, as well
# as revocation information such as CRLs and signed OCSP Responses. # as revocation information such as CRLs and signed OCSP Responses.
# # The syntax of the disabled algorithm string is described as follows:
# The syntax of the disabled algorithm string is described as this Java
# BNF-style:
# DisabledAlgorithms: # DisabledAlgorithms:
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
...@@ -438,25 +436,26 @@ krb5.kdc.bad.policy = tryLast ...@@ -438,25 +436,26 @@ krb5.kdc.bad.policy = tryLast
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint, CertConstraint # KeySizeConstraint | CAConstraint | DenyAfterConstraint |
# UsageConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator DecimalInteger # keySize Operator KeyLength
# #
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
# DecimalInteger: # KeyLength:
# DecimalDigits # Integer value of the algorithm's key length in bits
# #
# DecimalDigits: # CAConstraint:
# DecimalDigit {DecimalDigit} # jdkCA
# #
# DecimalDigit: one of # DenyAfterConstraint:
# 1 2 3 4 5 6 7 8 9 0 # denyAfter YYYY-MM-DD
# #
# CertConstraint # UsageConstraint:
# jdkCA # usage [TLSServer] [TLSClient] [SignedJAR]
# #
# The "AlgorithmName" is the standard algorithm name of the disabled # The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
...@@ -470,27 +469,55 @@ krb5.kdc.bad.policy = tryLast ...@@ -470,27 +469,55 @@ krb5.kdc.bad.policy = tryLast
# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion
# will not disable algorithms related to "ECDSA". # will not disable algorithms related to "ECDSA".
# #
# A "Constraint" provides further guidance for the algorithm being specified. # A "Constraint" defines restrictions on the keys and/or certificates for
# The "KeySizeConstraint" requires a key of a valid size range if the # a specified AlgorithmName:
# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the #
# key size specified in number of bits. For example, "RSA keySize <= 1024" # KeySizeConstraint:
# indicates that any RSA key with key size less than or equal to 1024 bits # keySize Operator KeyLength
# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates # The constraint requires a key of a valid size range if the
# that any RSA key with key size less than 1024 or greater than 2048 should # "AlgorithmName" is of a key algorithm. The "KeyLength" indicates
# be disabled. Note that the "KeySizeConstraint" only makes sense to key # the key size specified in number of bits. For example,
# algorithms. # "RSA keySize <= 1024" indicates that any RSA key with key size less
# # than or equal to 1024 bits should be disabled, and
# "CertConstraint" specifies additional constraints for # "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key
# certificates that contain algorithms that are restricted: # with key size less than 1024 or greater than 2048 should be disabled.
# # This constraint is only used on algorithms that have a key size.
# "jdkCA" prohibits the specified algorithm only if the algorithm is used #
# in a certificate chain that terminates at a marked trust anchor in the # CAConstraint:
# lib/security/cacerts keystore. All other chains are not affected. # jdkCA
# If the jdkCA constraint is not set, then all chains using the # This constraint prohibits the specified algorithm only if the
# specified algorithm are restricted. jdkCA may only be used once in # algorithm is used in a certificate chain that terminates at a marked
# a DisabledAlgorithm expression. # trust anchor in the lib/security/cacerts keystore. If the jdkCA
# Example: To apply this constraint to SHA-1 certificates, include # constraint is not set, then all chains using the specified algorithm
# the following: "SHA1 jdkCA" # are restricted. jdkCA may only be used once in a DisabledAlgorithm
# expression.
# Example:  To apply this constraint to SHA-1 certificates, include
# the following:  "SHA1 jdkCA"
#
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
# This constraint prohibits a certificate with the specified algorithm
# from being used after the date regardless of the certificate's
# validity.  JAR files that are signed and timestamped before the
# constraint date with certificates containing the disabled algorithm
# will not be restricted.  The date is processed in the UTC timezone.
# This constraint can only be used once in a DisabledAlgorithm
# expression.
# Example: To deny usage of RSA 2048 bit certificates after Feb 3 2020,
# use the following: "RSA keySize == 2048 & denyAfter 2020-02-03"
#
# UsageConstraint:
# usage [TLSServer] [TLSClient] [SignedJAR]
# This constraint prohibits the specified algorithm for
# a specified usage. This should be used when disabling an algorithm
# for all usages is not practical. 'TLSServer' restricts the algorithm
# in TLS server certificate chains when server authentication is
# performed. 'TLSClient' restricts the algorithm in TLS client
# certificate chains when client authentication is performed.
# 'SignedJAR' constrains use of certificates in signed jar files.
# The usage type follows the keyword and more than one usage type can
# be specified with a whitespace delimiter.
# Example: "SHA1 usage TLSServer TLSClient"
# #
# When an algorithm must satisfy more than one constraint, it must be # When an algorithm must satisfy more than one constraint, it must be
# delimited by an ampersand '&'. For example, to restrict certificates in a # delimited by an ampersand '&'. For example, to restrict certificates in a
...@@ -503,6 +530,9 @@ krb5.kdc.bad.policy = tryLast ...@@ -503,6 +530,9 @@ krb5.kdc.bad.policy = tryLast
# before larger keysize constraints of the same algorithm. For example: # before larger keysize constraints of the same algorithm. For example:
# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". # "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by Oracle's PKIX implementation. It # Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations. # is not guaranteed to be examined and used by other implementations.
# #
...@@ -510,9 +540,10 @@ krb5.kdc.bad.policy = tryLast ...@@ -510,9 +540,10 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
# #
# #
jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
DSA keySize < 1024, EC keySize < 224 RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
#
# Algorithm restrictions for signed JAR files # Algorithm restrictions for signed JAR files
# #
# In some environments, certain algorithms or key lengths may be undesirable # In some environments, certain algorithms or key lengths may be undesirable
...@@ -527,17 +558,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -527,17 +558,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# " DisabledAlgorithm { , DisabledAlgorithm } " # " DisabledAlgorithm { , DisabledAlgorithm } "
# #
# DisabledAlgorithm: # DisabledAlgorithm:
# AlgorithmName [Constraint] # AlgorithmName [Constraint] { '&' Constraint }
# #
# AlgorithmName: # AlgorithmName:
# (see below) # (see below)
# #
# Constraint: # Constraint:
# KeySizeConstraint # KeySizeConstraint | DenyAfterConstraint
# #
# KeySizeConstraint: # KeySizeConstraint:
# keySize Operator KeyLength # keySize Operator KeyLength
# #
# DenyAfterConstraint:
# denyAfter YYYY-MM-DD
#
# Operator: # Operator:
# <= | < | == | != | >= | > # <= | < | == | != | >= | >
# #
...@@ -548,8 +582,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ ...@@ -548,8 +582,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# implementation. It is not guaranteed to be examined and used by other # implementation. It is not guaranteed to be examined and used by other
# implementations. # implementations.
# #
# See "jdk.certpath.disabledAlgorithms" for syntax descriptions.
#
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
#
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing # (SSL/TLS) processing
# #
...@@ -571,6 +608,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 ...@@ -571,6 +608,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the # See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string. # syntax of the disabled algorithm string.
# #
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
# Note: This property is currently used by the JDK Reference implementation. # Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations. # It is not guaranteed to be examined and used by other implementations.
# #
......
...@@ -240,6 +240,9 @@ sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java generic-all ...@@ -240,6 +240,9 @@ sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java generic-all
# 8158827 # 8158827
sun/security/krb5/auto/tools/KinitConfPlusProps.java windows-all sun/security/krb5/auto/tools/KinitConfPlusProps.java windows-all
# 8160071 ClientJSSEServerJSSE.java test failure
sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java linux-all
############################################################################ ############################################################################
# jdk_sound # jdk_sound
......
...@@ -463,7 +463,7 @@ public class TimestampCheck { ...@@ -463,7 +463,7 @@ public class TimestampCheck {
.shouldMatch("Timestamp signature algorithm: .*key.*weak"); .shouldMatch("Timestamp signature algorithm: .*key.*weak");
verify(file, "-J-Djava.security.debug=jar") verify(file, "-J-Djava.security.debug=jar")
.shouldHaveExitValue(0) .shouldHaveExitValue(0)
.shouldMatch("SignatureException:.*Disabled"); .shouldMatch("SignatureException:.*disabled");
} }
static void checkHalfWeak(String file) throws Throwable { static void checkHalfWeak(String file) throws Throwable {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册