diff --git a/src/share/classes/sun/security/pkcs/SignerInfo.java b/src/share/classes/sun/security/pkcs/SignerInfo.java index 78d3f631d68d636659e23b43960dcd3d1004dc75..5e69438c8d0bb8ff97cfe107ae6b2c6d98447d30 100644 --- a/src/share/classes/sun/security/pkcs/SignerInfo.java +++ b/src/share/classes/sun/security/pkcs/SignerInfo.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.Timestamp; +import java.security.cert.CertPathValidatorException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CertPath; @@ -49,6 +50,7 @@ import java.util.Set; import sun.misc.HexDumpEncoder; import sun.security.timestamp.TimestampToken; +import sun.security.util.ConstraintsParameters; import sun.security.util.Debug; import sun.security.util.DerEncoder; import sun.security.util.DerInputStream; @@ -209,7 +211,7 @@ public class SignerInfo implements DerEncoder { /** * DER encode this object onto an output stream. - * Implements the DerEncoder interface. + * Implements the {@code DerEncoder} interface. * * @param out * the output stream on which to write the DER encoding. @@ -266,7 +268,7 @@ public class SignerInfo implements DerEncoder { if (userCert == null) return null; - ArrayList certList = new ArrayList(); + ArrayList certList = new ArrayList<>(); certList.add(userCert); X509Certificate[] pkcsCerts = block.getCertificates(); @@ -321,6 +323,8 @@ public class SignerInfo implements DerEncoder { data = content.getContentBytes(); } + ConstraintsParameters cparams = + new ConstraintsParameters(timestamp); String digestAlgname = getDigestAlgorithmId().getName(); byte[] dataSigned; @@ -347,11 +351,11 @@ public class SignerInfo implements DerEncoder { if (messageDigest == null) // fail if there is no message digest return null; - // check that algorithm is not restricted - if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, - digestAlgname, null)) { - throw new SignatureException("Digest check failed. " + - "Disabled algorithm used: " + digestAlgname); + // check that digest algorithm is not restricted + try { + JAR_DISABLED_CHECK.permits(digestAlgname, cparams); + } catch (CertPathValidatorException e) { + throw new SignatureException(e.getMessage(), e); } MessageDigest md = MessageDigest.getInstance(digestAlgname); @@ -385,17 +389,18 @@ public class SignerInfo implements DerEncoder { String algname = AlgorithmId.makeSigAlg( digestAlgname, encryptionAlgname); - // check that algorithm is not restricted - if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, algname, null)) { - throw new SignatureException("Signature check failed. " + - "Disabled algorithm used: " + algname); + // check that jar signature algorithm is not restricted + try { + JAR_DISABLED_CHECK.permits(algname, cparams); + } catch (CertPathValidatorException e) { + throw new SignatureException(e.getMessage(), e); } X509Certificate cert = getCertificate(block); - PublicKey key = cert.getPublicKey(); if (cert == null) { return null; } + PublicKey key = cert.getPublicKey(); // check if the public key is restricted if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { @@ -519,7 +524,7 @@ public class SignerInfo implements DerEncoder { * Extracts a timestamp from a PKCS7 SignerInfo. * * Examines the signer's unsigned attributes for a - * signatureTimestampToken attribute. If present, + * {@code signatureTimestampToken} attribute. If present, * then it is parsed to extract the date and time at which the * timestamp was generated. * diff --git a/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java index 73031564557f9a07abfab982734e3ee4cbcd4479..f7bedb99ccbf0702b1fd5f5d030de0977473f808 100644 --- a/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java +++ b/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,11 @@ package sun.security.provider.certpath; import java.security.AlgorithmConstraints; import java.security.CryptoPrimitive; +import java.security.Timestamp; +import java.security.cert.CertPathValidator; import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.Set; import java.util.EnumSet; import java.math.BigInteger; @@ -51,15 +54,16 @@ import java.security.interfaces.DSAPublicKey; import java.security.spec.DSAPublicKeySpec; import sun.security.util.AnchorCertificates; -import sun.security.util.CertConstraintParameters; +import sun.security.util.ConstraintsParameters; import sun.security.util.Debug; import sun.security.util.DisabledAlgorithmConstraints; +import sun.security.validator.Validator; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; import sun.security.x509.AlgorithmId; /** - * A PKIXCertPathChecker implementation to check whether a + * A {@code PKIXCertPathChecker} implementation to check whether a * specified certificate contains the required algorithm constraints. *

* Certificate fields such as the subject public key, the signature @@ -69,24 +73,27 @@ import sun.security.x509.AlgorithmId; * @see PKIXCertPathChecker * @see PKIXParameters */ -final public class AlgorithmChecker extends PKIXCertPathChecker { +public final class AlgorithmChecker extends PKIXCertPathChecker { private static final Debug debug = Debug.getInstance("certpath"); private final AlgorithmConstraints constraints; private final PublicKey trustedPubKey; + private final Date pkixdate; private PublicKey prevPubKey; + private final Timestamp jarTimestamp; + private final String variant; - private final static Set SIGNATURE_PRIMITIVE_SET = + private static final Set SIGNATURE_PRIMITIVE_SET = Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); - private final static Set KU_PRIMITIVE_SET = + private static final Set KU_PRIMITIVE_SET = Collections.unmodifiableSet(EnumSet.of( CryptoPrimitive.SIGNATURE, CryptoPrimitive.KEY_ENCAPSULATION, CryptoPrimitive.PUBLIC_KEY_ENCRYPTION, CryptoPrimitive.KEY_AGREEMENT)); - private final static DisabledAlgorithmConstraints + private static final DisabledAlgorithmConstraints certPathDefaultConstraints = new DisabledAlgorithmConstraints( DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); @@ -99,64 +106,99 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { private boolean trustedMatch = false; /** - * Create a new AlgorithmChecker with the algorithm - * constraints specified in security property - * "jdk.certpath.disabledAlgorithms". + * Create a new {@code AlgorithmChecker} with the given algorithm + * given {@code TrustAnchor} and {@code String} variant. * * @param anchor the trust anchor selected to validate the target * certificate + * @param variant is the Validator variants of the operation. A null value + * passed will set it to Validator.GENERIC. */ - public AlgorithmChecker(TrustAnchor anchor) { - this(anchor, certPathDefaultConstraints); + public AlgorithmChecker(TrustAnchor anchor, String variant) { + this(anchor, certPathDefaultConstraints, null, null, variant); } /** - * Create a new AlgorithmChecker with the - * given {@code AlgorithmConstraints}. - *

- * Note that this constructor will be used to check a certification - * path where the trust anchor is unknown, or a certificate list which may - * contain the trust anchor. This constructor is used by SunJSSE. + * Create a new {@code AlgorithmChecker} with the given + * {@code AlgorithmConstraints}, {@code Timestamp}, and {@code String} + * variant. + * + * Note that this constructor can initialize a variation of situations where + * the AlgorithmConstraints, Timestamp, or Variant maybe known. * * @param constraints the algorithm constraints (or null) + * @param jarTimestamp Timestamp passed for JAR timestamp constraint + * checking. Set to null if not applicable. + * @param variant is the Validator variants of the operation. A null value + * passed will set it to Validator.GENERIC. */ - public AlgorithmChecker(AlgorithmConstraints constraints) { - this.prevPubKey = null; - this.trustedPubKey = null; - this.constraints = constraints; + public AlgorithmChecker(AlgorithmConstraints constraints, + Timestamp jarTimestamp, String variant) { + this(null, constraints, null, jarTimestamp, variant); } /** - * Create a new AlgorithmChecker with the - * given TrustAnchor and AlgorithmConstraints. + * Create a new {@code AlgorithmChecker} with the + * given {@code TrustAnchor}, {@code AlgorithmConstraints}, + * {@code Timestamp}, and {@code String} variant. * * @param anchor the trust anchor selected to validate the target * certificate * @param constraints the algorithm constraints (or null) - * - * @throws IllegalArgumentException if the anchor is null + * @param pkixdate The date specified by the PKIXParameters date. If the + * PKIXParameters is null, the current date is used. This + * should be null when jar files are being checked. + * @param jarTimestamp Timestamp passed for JAR timestamp constraint + * checking. Set to null if not applicable. + * @param variant is the Validator variants of the operation. A null value + * passed will set it to Validator.GENERIC. */ public AlgorithmChecker(TrustAnchor anchor, - AlgorithmConstraints constraints) { + AlgorithmConstraints constraints, Date pkixdate, + Timestamp jarTimestamp, String variant) { - if (anchor == null) { - throw new IllegalArgumentException( - "The trust anchor cannot be null"); - } - - if (anchor.getTrustedCert() != null) { - this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); - // Check for anchor certificate restrictions - trustedMatch = checkFingerprint(anchor.getTrustedCert()); - if (trustedMatch && debug != null) { - debug.println("trustedMatch = true"); + if (anchor != null) { + if (anchor.getTrustedCert() != null) { + this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); + // Check for anchor certificate restrictions + trustedMatch = checkFingerprint(anchor.getTrustedCert()); + if (trustedMatch && debug != null) { + debug.println("trustedMatch = true"); + } + } else { + this.trustedPubKey = anchor.getCAPublicKey(); } } else { - this.trustedPubKey = anchor.getCAPublicKey(); + this.trustedPubKey = null; + if (debug != null) { + debug.println("TrustAnchor is null, trustedMatch is false."); + } } - this.prevPubKey = trustedPubKey; - this.constraints = constraints; + this.prevPubKey = this.trustedPubKey; + this.constraints = (constraints == null ? certPathDefaultConstraints : + constraints); + // If we are checking jar files, set pkixdate the same as the timestamp + // for certificate checking + this.pkixdate = (jarTimestamp != null ? jarTimestamp.getTimestamp() : + pkixdate); + this.jarTimestamp = jarTimestamp; + this.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 @@ -217,6 +259,28 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { 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 Set primitives = KU_PRIMITIVE_SET; @@ -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) { - // Check against DisabledAlgorithmConstraints certpath constraints. - // permits() will throw exception on failure. - ((DisabledAlgorithmConstraints)constraints).permits(primitives, - 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); - } + ((DisabledAlgorithmConstraints)constraints).permits(currSigAlg, cp); + // DisabledAlgorithmsConstraints does not check primitives, so key + // additional key check. - AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); - String currSigAlg = x509Cert.getSigAlgName(); - - // If 'constraints' is not of DisabledAlgorithmConstraints, check all - // everything individually - if (!(constraints instanceof DisabledAlgorithmConstraints)) { - // Check the current signature algorithm - if (!constraints.permits( - SIGNATURE_PRIMITIVE_SET, - currSigAlg, currSigAlgParams)) { + } else { + // Perform the default constraints checking anyway. + certPathDefaultConstraints.permits(currSigAlg, cp); + // Call locally set constraints to check key with primitives. + if (!constraints.permits(primitives, currPubKey)) { throw new CertPathValidatorException( - "Algorithm constraints check failed on signature " + - "algorithm: " + currSigAlg, null, null, -1, - BasicReason.ALGORITHM_CONSTRAINED); + "Algorithm constraints check failed on key " + + currPubKey.getAlgorithm() + " with size of " + + 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 - if (prevPubKey != null) { - if (!constraints.permits( - SIGNATURE_PRIMITIVE_SET, - currSigAlg, prevPubKey, currSigAlgParams)) { - throw new CertPathValidatorException( + if (!constraints.permits( + SIGNATURE_PRIMITIVE_SET, + currSigAlg, prevPubKey, currSigAlgParams)) { + throw new CertPathValidatorException( "Algorithm constraints check failed on " + "signature algorithm: " + currSigAlg, - null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); - } + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } - // Inherit key parameters from previous key - if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { - // Inherit DSA parameters from previous key - if (!(prevPubKey instanceof DSAPublicKey)) { - throw new CertPathValidatorException("Input key is not " + + // Inherit key parameters from previous key + if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { + // Inherit DSA parameters from previous key + if (!(prevPubKey instanceof DSAPublicKey)) { + throw new CertPathValidatorException("Input key is not " + "of a appropriate type for inheriting parameters"); - } + } - DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); - if (params == null) { - throw new CertPathValidatorException( + DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); + if (params == null) { + throw new CertPathValidatorException( "Key parameters missing from public key."); - } + } - try { - BigInteger y = ((DSAPublicKey)currPubKey).getY(); - KeyFactory kf = KeyFactory.getInstance("DSA"); - DSAPublicKeySpec ks = new DSAPublicKeySpec(y, - params.getP(), - params.getQ(), - params.getG()); - currPubKey = kf.generatePublic(ks); - } catch (GeneralSecurityException e) { - throw new CertPathValidatorException("Unable to generate " + + try { + BigInteger y = ((DSAPublicKey)currPubKey).getY(); + KeyFactory kf = KeyFactory.getInstance("DSA"); + DSAPublicKeySpec ks = new DSAPublicKeySpec(y, params.getP(), + params.getQ(), params.getG()); + currPubKey = kf.generatePublic(ks); + } catch (GeneralSecurityException e) { + throw new CertPathValidatorException("Unable to generate " + "key with inherited parameters: " + e.getMessage(), e); - } } } // reset the previous public key prevPubKey = currPubKey; - - // check the extended key usage, ignore the check now - // List extendedKeyUsages = x509Cert.getExtendedKeyUsage(); - - // DO NOT remove any unresolved critical extensions } /** @@ -387,8 +424,10 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { * * @param key the public key to verify the CRL signature * @param crl the target CRL + * @param variant is the Validator variants of the operation. A null value + * 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 { X509CRLImpl x509CRLImpl = null; @@ -399,28 +438,24 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { } AlgorithmId algorithmId = x509CRLImpl.getSigAlgId(); - check(key, algorithmId); + check(key, algorithmId, variant); } /** * Check the signature algorithm with the specified public key. * * @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 { String sigAlgName = algorithmId.getName(); AlgorithmParameters sigAlgParams = algorithmId.getParameters(); - if (!certPathDefaultConstraints.permits( - SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed on signature algorithm: " + - sigAlgName + " is disabled", - null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); - } + certPathDefaultConstraints.permits(new ConstraintsParameters( + sigAlgName, sigAlgParams, key, variant)); } - } diff --git a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java index 086e73f64c938fa1b404c699bd2aa5fa11bc23ba..e4429e0892e5c7eb8faeaa4f74177641d0c42b38 100644 --- a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java +++ b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import javax.security.auth.x500.X500Principal; import java.util.*; import sun.security.util.Debug; +import sun.security.validator.Validator; import static sun.security.x509.PKIXExtensions.*; import sun.security.x509.*; @@ -65,6 +66,20 @@ public class DistributionPointFetcher { * Return the X509CRLs matching this selector. The selector must be * an X509CRLSelector with certificateChecking set. */ + public static Collection getCRLs(X509CRLSelector selector, + boolean signFlag, PublicKey prevKey, String provider, + List certStores, boolean[] reasonsMask, + Set 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 getCRLs(X509CRLSelector selector, boolean signFlag, PublicKey prevKey, @@ -76,7 +91,7 @@ public class DistributionPointFetcher { throws CertStoreException { return getCRLs(selector, signFlag, prevKey, null, provider, certStores, - reasonsMask, trustAnchors, validity); + reasonsMask, trustAnchors, validity, Validator.VAR_GENERIC); } /** @@ -91,7 +106,8 @@ public class DistributionPointFetcher { List certStores, boolean[] reasonsMask, Set trustAnchors, - Date validity) + Date validity, + String variant) throws CertStoreException { X509Certificate cert = selector.getCertificateChecking(); @@ -120,7 +136,7 @@ public class DistributionPointFetcher { DistributionPoint point = t.next(); Collection crls = getCRLs(selector, certImpl, point, reasonsMask, signFlag, prevKey, prevCert, provider, - certStores, trustAnchors, validity); + certStores, trustAnchors, validity, variant); results.addAll(crls); } if (debug != null) { @@ -145,7 +161,7 @@ public class DistributionPointFetcher { X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask, boolean signFlag, PublicKey prevKey, X509Certificate prevCert, String provider, List certStores, - Set trustAnchors, Date validity) + Set trustAnchors, Date validity, String variant) throws CertStoreException { // check for full name @@ -208,7 +224,7 @@ public class DistributionPointFetcher { selector.setIssuerNames(null); if (selector.match(crl) && verifyCRL(certImpl, point, crl, reasonsMask, signFlag, prevKey, prevCert, provider, - trustAnchors, certStores, validity)) { + trustAnchors, certStores, validity, variant)) { crls.add(crl); } } catch (IOException | CRLException e) { @@ -317,7 +333,7 @@ public class DistributionPointFetcher { X509CRL crl, boolean[] reasonsMask, boolean signFlag, PublicKey prevKey, X509Certificate prevCert, String provider, Set trustAnchors, List certStores, - Date validity) throws CRLException, IOException { + Date validity, String variant) throws CRLException, IOException { if (debug != null) { debug.println("DistributionPointFetcher.verifyCRL: " + @@ -443,7 +459,7 @@ public class DistributionPointFetcher { } if (indirectCRL) { 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 if (debug != null) { debug.println("must only be one CRL " + @@ -664,7 +680,7 @@ public class DistributionPointFetcher { // check the crl signature algorithm try { - AlgorithmChecker.check(prevKey, crl); + AlgorithmChecker.check(prevKey, crl, variant); } catch (CertPathValidatorException cpve) { if (debug != null) { debug.println("CRL signature algorithm check failed: " + cpve); diff --git a/src/share/classes/sun/security/provider/certpath/OCSP.java b/src/share/classes/sun/security/provider/certpath/OCSP.java index dce8fd6b93403b14effc8288ba44d2dd8ea6701c..dce73028cd0e140fb6283f9b8f205e61e942f7d3 100644 --- a/src/share/classes/sun/security/provider/certpath/OCSP.java +++ b/src/share/classes/sun/security/provider/certpath/OCSP.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.CRLReason; import java.security.cert.Extension; +import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; @@ -42,14 +43,14 @@ import java.util.Date; import java.util.List; import java.util.Map; -import static sun.security.provider.certpath.OCSPResponse.*; import sun.security.action.GetIntegerAction; import sun.security.util.Debug; -import sun.security.util.ObjectIdentifier; +import sun.security.validator.Validator; import sun.security.x509.AccessDescription; import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.GeneralName; import sun.security.x509.GeneralNameInterface; +import sun.security.x509.PKIXExtensions; import sun.security.x509.URIName; import sun.security.x509.X509CertImpl; @@ -65,9 +66,6 @@ import sun.security.x509.X509CertImpl; */ 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 int DEFAULT_CONNECT_TIMEOUT = 15000; @@ -97,42 +95,6 @@ public final class 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.emptyList()); - return (RevocationStatus)ocspResponse.getSingleResponse(certId); - } /** * Obtains the revocation status of a certificate using OCSP. @@ -149,6 +111,8 @@ public final class OCSP { * @throws CertPathValidatorException if an exception occurs while * encoding the OCSP Request or validating the OCSP Response */ + + // Called by com.sun.deploy.security.TrustDecider public static RevocationStatus check(X509Certificate cert, X509Certificate issuerCert, URI responderURI, @@ -157,18 +121,27 @@ public final class OCSP { throws IOException, CertPathValidatorException { return check(cert, issuerCert, responderURI, responderCert, date, - Collections.emptyList()); + Collections.emptyList(), Validator.VAR_GENERIC); } - // Called by com.sun.deploy.security.TrustDecider + public static RevocationStatus check(X509Certificate cert, - X509Certificate issuerCert, - URI responderURI, - X509Certificate responderCert, - Date date, List extensions) + X509Certificate issuerCert, URI responderURI, + X509Certificate responderCert, Date date, List extensions, + String variant) 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 extensions, String variant) + throws IOException, CertPathValidatorException + { + CertId certId; try { X509CertImpl certImpl = X509CertImpl.toImpl(cert); certId = new CertId(issuerCert, certImpl.getSerialNumberObject()); @@ -177,19 +150,23 @@ public final class OCSP { ("Exception while encoding OCSPRequest", e); } 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); } /** * 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 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 date the time the validity of the OCSP responder's certificate * 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 * @throws IOException if there is an exception connecting to or * communicating with the OCSP responder @@ -197,24 +174,59 @@ public final class OCSP { * encoding the OCSP Request or validating the OCSP Response */ static OCSPResponse check(List certIds, URI responderURI, - X509Certificate issuerCert, + OCSPResponse.IssuerInfo issuerInfo, X509Certificate responderCert, Date date, - List extensions) + List extensions, String variant) throws IOException, CertPathValidatorException { - byte[] bytes = null; - OCSPRequest request = null; + byte[] nonce = null; + for (Extension ext : extensions) { + if (ext.getId().equals(PKIXExtensions.OCSPNonce_Id.toString())) { + nonce = ext.getValue(); + } + } + + OCSPResponse ocspResponse = null; try { - request = new OCSPRequest(certIds, extensions); - bytes = request.encodeBytes(); + byte[] response = getOCSPBytes(certIds, responderURI, extensions); + ocspResponse = new OCSPResponse(response); + + // verify the response + ocspResponse.verify(certIds, issuerInfo, responderCert, date, + nonce, variant); } catch (IOException ioe) { - throw new CertPathValidatorException - ("Exception while encoding OCSPRequest", ioe); + throw new CertPathValidatorException( + "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 certIds, URI responderURI, + List extensions) throws IOException { + OCSPRequest request = new OCSPRequest(certIds, extensions); + byte[] bytes = request.encodeBytes(); + InputStream in = null; OutputStream out = null; byte[] response = null; + try { URL url = responderURI.toURL(); if (debug != null) { @@ -257,10 +269,6 @@ public final class OCSP { } } 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 { if (in != null) { try { @@ -277,20 +285,7 @@ public final class OCSP { } } } - - 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; + return response; } /** @@ -322,7 +317,7 @@ public final class OCSP { List descriptions = aia.getAccessDescriptions(); for (AccessDescription description : descriptions) { - if (description.getAccessMethod().equals((Object) + if (description.getAccessMethod().equals( AccessDescription.Ad_OCSP_Id)) { GeneralName generalName = description.getAccessLocation(); diff --git a/src/share/classes/sun/security/provider/certpath/OCSPRequest.java b/src/share/classes/sun/security/provider/certpath/OCSPRequest.java index 6bded97293b9afc44236e0f6120e7e101b0fe0ca..5eb97d264ba8d5817c24975baeba5c382b942989 100644 --- a/src/share/classes/sun/security/provider/certpath/OCSPRequest.java +++ b/src/share/classes/sun/security/provider/certpath/OCSPRequest.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,11 @@ import java.util.List; import sun.misc.HexDumpEncoder; import sun.security.util.*; +import sun.security.x509.PKIXExtensions; /** * 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 ASN.1 definition is as follows: *

@@ -118,7 +119,8 @@ class OCSPRequest {
             DerOutputStream extOut = new DerOutputStream();
             for (Extension ext : extensions) {
                 ext.encode(extOut);
-                if (ext.getId().equals(OCSP.NONCE_EXTENSION_OID.toString())) {
+                if (ext.getId().equals(
+                        PKIXExtensions.OCSPNonce_Id.toString())) {
                     nonce = ext.getValue();
                 }
             }
diff --git a/src/share/classes/sun/security/provider/certpath/OCSPResponse.java b/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
index 47755e7fb67399a17a798b2684c82c16f4f88c6d..f2c23b991b7ecfa1c24758b4f23ef6fd6e62ce8a 100644
--- a/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
+++ b/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
@@ -1,5 +1,5 @@
 /*
- * 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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import javax.security.auth.x500.X500Principal;
 
 import sun.misc.HexDumpEncoder;
@@ -129,7 +130,7 @@ public final class OCSPResponse {
         SIG_REQUIRED,          // Must sign the request
         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 boolean dump = debug != null && Debug.isOn("ocsp");
@@ -173,7 +174,7 @@ public final class OCSPResponse {
     }
 
     // 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 Map singleResponseMap;
@@ -183,13 +184,16 @@ public final class OCSPResponse {
     private final byte[] responseNonce;
     private List certs;
     private X509CertImpl signerCert = null;
-    private X500Principal responderName = null;
-    private KeyIdentifier responderKeyId = null;
+    private final ResponderId respId;
+    private Date producedAtDate = null;
+    private final Map responseExtensions;
 
     /*
      * 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) {
             HexDumpEncoder hexEnc = new HexDumpEncoder();
             debug.println("OCSPResponse bytes...\n\n" +
@@ -221,6 +225,8 @@ public final class OCSPResponse {
             signature = null;
             tbsResponseData = null;
             responseNonce = null;
+            responseExtensions = Collections.emptyMap();
+            respId = null;
             return;
         }
 
@@ -289,27 +295,15 @@ public final class OCSPResponse {
         }
 
         // responderID
-        short tag = (byte)(seq.tag & 0x1f);
-        if (tag == NAME_TAG) {
-            responderName = new X500Principal(seq.getData().toByteArray());
-            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");
+        respId = new ResponderId(seq.toByteArray());
+        if (debug != null) {
+            debug.println("Responder ID: " + respId);
         }
 
         // producedAt
         seq = seqDerIn.getDerValue();
+        producedAtDate = seq.getGeneralizedTime();
         if (debug != null) {
-            Date producedAtDate = seq.getGeneralizedTime();
             debug.println("OCSP response produced at: " + producedAtDate);
         }
 
@@ -320,37 +314,29 @@ public final class OCSPResponse {
             debug.println("OCSP number of SingleResponses: "
                           + singleResponseDer.length);
         }
-        for (int i = 0; i < singleResponseDer.length; i++) {
-            SingleResponse singleResponse =
-                new SingleResponse(singleResponseDer[i]);
+        for (DerValue srDer : singleResponseDer) {
+            SingleResponse singleResponse = new SingleResponse(srDer);
             singleResponseMap.put(singleResponse.getCertId(), singleResponse);
         }
 
         // responseExtensions
-        byte[] nonce = null;
+        Map tmpExtMap = new HashMap<>();
         if (seqDerIn.available() > 0) {
             seq = seqDerIn.getDerValue();
             if (seq.isContextSpecific((byte)1)) {
-                DerValue[] responseExtDer = seq.data.getSequence(3);
-                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());
-                    }
-                }
+                tmpExtMap = parseExtensions(seq);
             }
         }
-        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
         sigAlgId = AlgorithmId.parse(seqTmp[1]);
@@ -387,8 +373,9 @@ public final class OCSPResponse {
         }
     }
 
-    void verify(List certIds, X509Certificate issuerCert,
-                X509Certificate responderCert, Date date, byte[] nonce)
+    void verify(List certIds, IssuerInfo issuerInfo,
+            X509Certificate responderCert, Date date, byte[] nonce,
+            String variant)
         throws CertPathValidatorException
     {
         switch (responseStatus) {
@@ -428,7 +415,9 @@ public final class OCSPResponse {
             // Add the Issuing CA cert and/or Trusted Responder cert to the list
             // of certs from the OCSP response
             try {
-                certs.add(X509CertImpl.toImpl(issuerCert));
+                if (issuerInfo.getCertificate() != null) {
+                    certs.add(X509CertImpl.toImpl(issuerInfo.getCertificate()));
+                }
                 if (responderCert != null) {
                     certs.add(X509CertImpl.toImpl(responderCert));
                 }
@@ -437,20 +426,22 @@ public final class OCSPResponse {
                     "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) {
-                    if (cert.getSubjectX500Principal().equals(responderName)) {
+                    if (cert.getSubjectX500Principal().equals(rName)) {
                         signerCert = cert;
                         break;
                     }
                 }
-            } else if (responderKeyId != null) {
+            } else if (respId.getType() == ResponderId.Type.BY_KEY) {
+                KeyIdentifier ridKeyId = respId.getKeyIdentifier();
                 for (X509CertImpl cert : certs) {
                     // Match responder's key identifier against the cert's SKID
                     // This will match if the SKID is encoded using the 160-bit
                     // SHA-1 hash method as defined in RFC 5280.
                     KeyIdentifier certKeyId = cert.getSubjectKeyId();
-                    if (certKeyId != null && responderKeyId.equals(certKeyId)) {
+                    if (certKeyId != null && ridKeyId.equals(certKeyId)) {
                         signerCert = cert;
                         break;
                     } else {
@@ -464,7 +455,7 @@ public final class OCSPResponse {
                         } catch (IOException e) {
                             // ignore
                         }
-                        if (responderKeyId.equals(certKeyId)) {
+                        if (ridKeyId.equals(certKeyId)) {
                             signerCert = cert;
                             break;
                         }
@@ -476,7 +467,10 @@ public final class OCSPResponse {
         // Check whether the signer cert returned by the responder is trusted
         if (signerCert != null) {
             // 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) {
                     debug.println("OCSP response is signed by the target's " +
                         "Issuing CA");
@@ -493,7 +487,7 @@ public final class OCSPResponse {
 
             // Check if the response is signed by an authorized responder
             } else if (signerCert.getIssuerX500Principal().equals(
-                       issuerCert.getSubjectX500Principal())) {
+                    issuerInfo.getName())) {
 
                 // Check for the OCSPSigning key purpose
                 try {
@@ -513,8 +507,9 @@ public final class OCSPResponse {
 
                 // Check algorithm constraints specified in security property
                 // "jdk.certpath.disabledAlgorithms".
-                AlgorithmChecker algChecker = new AlgorithmChecker(
-                                    new TrustAnchor(issuerCert, null));
+                AlgorithmChecker algChecker =
+                        new AlgorithmChecker(issuerInfo.getAnchor(), date,
+                                variant);
                 algChecker.init(false);
                 algChecker.check(signerCert, Collections.emptySet());
 
@@ -552,7 +547,7 @@ public final class OCSPResponse {
 
                 // verify the signature
                 try {
-                    signerCert.verify(issuerCert.getPublicKey());
+                    signerCert.verify(issuerInfo.getPublicKey());
                     if (debug != null) {
                         debug.println("OCSP response is signed by an " +
                             "Authorized Responder");
@@ -574,7 +569,7 @@ public final class OCSPResponse {
         if (signerCert != null) {
             // Check algorithm constraints specified in security property
             // "jdk.certpath.disabledAlgorithms".
-            AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId);
+            AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId, variant);
 
             if (!verifySignature(signerCert)) {
                 throw new CertPathValidatorException(
@@ -593,7 +588,6 @@ public final class OCSPResponse {
         }
 
         // Check freshness of OCSPResponse
-
         long now = (date == null) ? System.currentTimeMillis() : date.getTime();
         Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
         Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
@@ -604,16 +598,16 @@ public final class OCSPResponse {
                     until = " until " + sr.nextUpdate;
                 }
                 debug.println("OCSP response validity interval is from " +
-                              sr.thisUpdate + until);
+                        sr.thisUpdate + until);
                 debug.println("Checking validity of OCSP response on: " +
-                    new Date(now));
+                        new Date(now));
             }
 
             // Check that the test date is within the validity interval:
             //   [ thisUpdate - MAX_CLOCK_SKEW,
             //     MAX(thisUpdate, nextUpdate) + MAX_CLOCK_SKEW ]
             if (nowPlusSkew.before(sr.thisUpdate) ||
-                nowMinusSkew.after(
+                    nowMinusSkew.after(
                     sr.nextUpdate != null ? sr.nextUpdate : sr.thisUpdate))
             {
                 throw new CertPathValidatorException(
@@ -625,8 +619,10 @@ public final class OCSPResponse {
 
     /**
      * Returns the OCSP ResponseStatus.
+     *
+     * @return the {@code ResponseStatus} for this OCSP response
      */
-    ResponseStatus getResponseStatus() {
+    public ResponseStatus getResponseStatus() {
         return responseStatus;
     }
 
@@ -664,11 +660,27 @@ public final class OCSPResponse {
     /**
      * Returns the SingleResponse of the specified CertId, or null if
      * 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 a set of all CertIds in this {@code OCSPResponse}
+     *
+     * @return an unmodifiable set containing every {@code CertId} in this
+     *      response.
+     */
+    public Set getCertIds() {
+        return Collections.unmodifiableSet(singleResponseMap.keySet());
+    }
+
     /*
      * Returns the certificate for the authority that signed the OCSP response.
      */
@@ -676,10 +688,86 @@ public final class OCSPResponse {
         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
+        parseExtensions(DerValue derVal) throws IOException {
+        DerValue[] extDer = derVal.data.getSequence(3);
+        Map 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.
      */
-    final static class SingleResponse implements OCSP.RevocationStatus {
+    public static final class SingleResponse implements OCSP.RevocationStatus {
         private final CertId certId;
         private final CertStatus certStatus;
         private final Date thisUpdate;
@@ -724,7 +812,7 @@ public final class OCSPResponse {
                 }
             } else {
                 revocationTime = null;
-                revocationReason = CRLReason.UNSPECIFIED;
+                revocationReason = null;
                 if (tag == CERT_STATUS_GOOD) {
                     certStatus = CertStatus.GOOD;
                 } else if (tag == CERT_STATUS_UNKNOWN) {
@@ -735,77 +823,131 @@ public final class OCSPResponse {
             }
 
             thisUpdate = tmp.getGeneralizedTime();
+            if (debug != null) {
+                debug.println("thisUpdate: " + thisUpdate);
+            }
 
-            if (tmp.available() == 0)  {
-                // we are done
-                nextUpdate = null;
-            } else {
+            // Parse optional fields like nextUpdate and singleExtensions
+            Date tmpNextUpdate = null;
+            Map tmpMap = null;
+
+            // Check for the first optional item, it could be nextUpdate
+            // [CONTEXT 0] or singleExtensions [CONTEXT 1]
+            if (tmp.available() > 0) {
                 derVal = tmp.getDerValue();
-                tag = (byte)(derVal.tag & 0x1f);
-                if (tag == 0) {
-                    // next update
-                    nextUpdate = derVal.data.getGeneralizedTime();
 
-                    if (tmp.available() == 0)  {
-                        // we are done
-                    } else {
-                        derVal = tmp.getDerValue();
-                        tag = (byte)(derVal.tag & 0x1f);
+                // nextUpdate processing
+                if (derVal.isContextSpecific((byte)0)) {
+                    tmpNextUpdate = derVal.data.getGeneralizedTime();
+                    if (debug != null) {
+                        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
-            if (tmp.available() > 0) {
-                derVal = tmp.getDerValue();
-                if (derVal.isContextSpecific((byte)1)) {
-                    DerValue[] singleExtDer = derVal.data.getSequence(3);
-                    singleExtensions =
-                        new HashMap
-                            (singleExtDer.length);
-                    for (int i = 0; i < singleExtDer.length; i++) {
-                        Extension ext = new Extension(singleExtDer[i]);
-                        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 processing
+                if (derVal != null) {
+                    if (derVal.isContextSpecific((byte)1)) {
+                        tmpMap = parseExtensions(derVal);
+
+                        // There should not be any other items in the
+                        // singleResponse at this point.
+                        if (tmp.available() > 0) {
+                            throw new IOException(tmp.available() +
+                                " bytes of additional data in singleResponse");
                         }
-                        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
          */
-        @Override public CertStatus getCertStatus() {
+        @Override
+        public CertStatus getCertStatus() {
             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;
         }
 
-        @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;
         }
 
+        /**
+         * 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
         public Map getSingleExtensions() {
             return Collections.unmodifiableMap(singleExtensions);
@@ -816,17 +958,116 @@ public final class OCSPResponse {
          */
         @Override public String toString() {
             StringBuilder sb = new StringBuilder();
-            sb.append("SingleResponse:  \n");
+            sb.append("SingleResponse:\n");
             sb.append(certId);
-            sb.append("\nCertStatus: "+ certStatus + "\n");
+            sb.append("\nCertStatus: ").append(certStatus).append("\n");
             if (certStatus == CertStatus.REVOKED) {
-                sb.append("revocationTime is " + revocationTime + "\n");
-                sb.append("revocationReason is " + revocationReason + "\n");
+                sb.append("revocationTime is ");
+                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) {
-                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();
         }
     }
diff --git a/src/share/classes/sun/security/provider/certpath/PKIX.java b/src/share/classes/sun/security/provider/certpath/PKIX.java
index e33d4a21a5c9ff7945ac9f77bcdfcb5678d8a4f9..8a177c04fc12f89e02b9f48fbc48ed164e4b66ce 100644
--- a/src/share/classes/sun/security/provider/certpath/PKIX.java
+++ b/src/share/classes/sun/security/provider/certpath/PKIX.java
@@ -1,5 +1,5 @@
 /*
- * 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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@ package sun.security.provider.certpath;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.PublicKey;
+import java.security.Timestamp;
 import java.security.cert.*;
 import java.security.interfaces.DSAPublicKey;
 import java.util.*;
@@ -85,6 +86,8 @@ class PKIX {
         private CertSelector constraints;
         private Set anchors;
         private List certs;
+        private Timestamp timestamp;
+        private String variant;
 
         ValidatorParams(CertPath cp, PKIXParameters params)
             throws InvalidAlgorithmParameterException
@@ -100,6 +103,11 @@ class PKIX {
         ValidatorParams(PKIXParameters params)
             throws InvalidAlgorithmParameterException
         {
+            if (params instanceof PKIXExtendedParameters) {
+                timestamp = ((PKIXExtendedParameters) params).getTimestamp();
+                variant = ((PKIXExtendedParameters) params).getVariant();
+            }
+
             this.anchors = params.getTrustAnchors();
             // Make sure that none of the trust anchors include name constraints
             // (not supported).
@@ -189,6 +197,14 @@ class PKIX {
         PKIXParameters getPKIXParameters() {
             return params;
         }
+
+        Timestamp timestamp() {
+            return timestamp;
+        }
+
+        String variant() {
+            return variant;
+        }
     }
 
     static class BuilderParams extends ValidatorParams {
diff --git a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
index 98816f779e3173665d979165ca1877da8d93b240..53ae439baf3d262b342e437ca0725159d8c9607c 100644
--- a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
+++ b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
@@ -1,5 +1,5 @@
 /*
- * 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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -172,7 +172,8 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
         List certPathCheckers = new ArrayList<>();
         // add standard checkers that we will be using
         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,
                                             params.targetCertConstraints()));
         certPathCheckers.add(new ConstraintsChecker(certPathLen));
@@ -189,8 +190,11 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
                                              rootNode);
         certPathCheckers.add(pc);
         // default value for date is current time
-        BasicChecker bc = new BasicChecker(anchor, params.date(),
-                                           params.sigProvider(), false);
+        BasicChecker bc;
+        bc = new BasicChecker(anchor,
+                (params.timestamp() == null ? params.date() :
+                        params.timestamp().getTimestamp()),
+                params.sigProvider(), false);
         certPathCheckers.add(bc);
 
         boolean revCheckerAdded = false;
diff --git a/src/share/classes/sun/security/provider/certpath/PKIXExtendedParameters.java b/src/share/classes/sun/security/provider/certpath/PKIXExtendedParameters.java
new file mode 100644
index 0000000000000000000000000000000000000000..42c2d1f9c4fb7fe2f282b4e2a930342f4cc6f02e
--- /dev/null
+++ b/src/share/classes/sun/security/provider/certpath/PKIXExtendedParameters.java
@@ -0,0 +1,226 @@
+/*
+ * 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 getTrustAnchors() {
+        return p.getTrustAnchors();
+    }
+
+    @Override
+    public void setTrustAnchors(Set trustAnchors)
+            throws InvalidAlgorithmParameterException {
+        // To avoid problems with PKIXBuilderParameter's constructors
+        if (p == null) {
+            return;
+        }
+        p.setTrustAnchors(trustAnchors);
+    }
+
+    @Override
+    public Set getInitialPolicies() {
+        return p.getInitialPolicies();
+    }
+
+    @Override
+    public void setInitialPolicies(Set initialPolicies) {
+        p.setInitialPolicies(initialPolicies);
+    }
+
+    @Override
+    public void setCertStores(List stores) {
+        p.setCertStores(stores);
+    }
+
+    @Override
+    public void addCertStore(CertStore store) {
+        p.addCertStore(store);
+    }
+
+    @Override
+    public List 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 checkers) {
+        p.setCertPathCheckers(checkers);
+    }
+
+    @Override
+    public List 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);
+    }
+
+}
diff --git a/src/share/classes/sun/security/provider/certpath/ResponderId.java b/src/share/classes/sun/security/provider/certpath/ResponderId.java
new file mode 100644
index 0000000000000000000000000000000000000000..14d3152925f7c607517227e626c10f74c5488af6
--- /dev/null
+++ b/src/share/classes/sun/security/provider/certpath/ResponderId.java
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ * 

+ * The RFC 6960 defines a ResponderID structure as: + *

+ * 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.
+ * 
+ * + * @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(); + } + +} diff --git a/src/share/classes/sun/security/provider/certpath/RevocationChecker.java b/src/share/classes/sun/security/provider/certpath/RevocationChecker.java index 7445ade98260d37a2e37d3eddf26125dfc4b3903..a67969047754b070a6dc9adc911bedf3c02a0bc2 100644 --- a/src/share/classes/sun/security/provider/certpath/RevocationChecker.java +++ b/src/share/classes/sun/security/provider/certpath/RevocationChecker.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,6 @@ import javax.security.auth.x500.X500Principal; import static sun.security.provider.certpath.OCSP.*; import static sun.security.provider.certpath.PKIX.*; -import sun.security.action.GetPropertyAction; import sun.security.x509.*; import static sun.security.x509.PKIXExtensions.*; import sun.security.util.Debug; @@ -62,12 +61,12 @@ class RevocationChecker extends PKIXRevocationChecker { private List certStores; private Map ocspResponses; private List ocspExtensions; - private boolean legacy; + private final boolean legacy; private LinkedList softFailExceptions = new LinkedList<>(); // state variables - private X509Certificate issuerCert; + private OCSPResponse.IssuerInfo issuerInfo; private PublicKey prevPubKey; private boolean crlSignFlag; private int certIndex; @@ -302,9 +301,9 @@ class RevocationChecker extends PKIXRevocationChecker { CertPathValidatorException("forward checking not supported"); } if (anchor != null) { - issuerCert = anchor.getTrustedCert(); - prevPubKey = (issuerCert != null) ? issuerCert.getPublicKey() - : anchor.getCAPublicKey(); + issuerInfo = new OCSPResponse.IssuerInfo(anchor); + prevPubKey = issuerInfo.getPublicKey(); + } crlSignFlag = true; if (params != null && params.certPath() != null) { @@ -438,7 +437,7 @@ class RevocationChecker extends PKIXRevocationChecker { private void updateState(X509Certificate cert) throws CertPathValidatorException { - issuerCert = cert; + issuerInfo = new OCSPResponse.IssuerInfo(anchor, cert); // Make new public key if parameters are missing PublicKey pubKey = cert.getPublicKey(); @@ -466,6 +465,34 @@ class RevocationChecker extends PKIXRevocationChecker { 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, X509Certificate prevCert, boolean signFlag, boolean allowSeparateKey, @@ -478,9 +505,9 @@ class RevocationChecker extends PKIXRevocationChecker { " ---checking revocation status ..."); } - // reject circular dependencies - RFC 3280 is not explicit on how - // to handle this, so we feel it is safest to reject them until - // the issue is resolved in the PKIX WG. + // Reject circular dependencies - RFC 5280 is not explicit on how + // to handle this, but does suggest that they can be a security + // risk and can create unresolvable dependencies if (stackedCerts != null && stackedCerts.contains(cert)) { if (debug != null) { debug.println("RevocationChecker.checkCRLs()" + @@ -510,7 +537,7 @@ class RevocationChecker extends PKIXRevocationChecker { "CertStoreException: " + e.getMessage()); } if (networkFailureException == null && - CertStoreHelper.isCausedByNetworkIssue(store.getType(),e)) { + isCausedByNetworkIssue(store.getType(),e)) { // save this exception, we may need to throw it later networkFailureException = new CertPathValidatorException( "Unable to determine revocation status due to " + @@ -550,15 +577,14 @@ class RevocationChecker extends PKIXRevocationChecker { try { if (crlDP) { approvedCRLs.addAll(DistributionPointFetcher.getCRLs( - sel, signFlag, prevKey, prevCert, - params.sigProvider(), certStores, - reasonsMask, anchors, null)); + sel, signFlag, prevKey, prevCert, + params.sigProvider(), certStores, reasonsMask, + anchors, null, params.variant())); } } catch (CertStoreException e) { if (e instanceof CertStoreTypeException) { CertStoreTypeException cste = (CertStoreTypeException)e; - if (CertStoreHelper.isCausedByNetworkIssue(cste.getType(), - e)) { + if (isCausedByNetworkIssue(cste.getType(), e)) { throw new CertPathValidatorException( "Unable to determine revocation status due to " + "network error", e, null, -1, @@ -634,7 +660,7 @@ class RevocationChecker extends PKIXRevocationChecker { /* * Abort CRL validation and throw exception if there are any * unrecognized critical CRL entry extensions (see section - * 5.3 of RFC 3280). + * 5.3 of RFC 5280). */ Set unresCritExts = entry.getCriticalExtensionOIDs(); if (unresCritExts != null && !unresCritExts.isEmpty()) { @@ -682,14 +708,8 @@ class RevocationChecker extends PKIXRevocationChecker { OCSPResponse response = null; CertId certId = null; try { - if (issuerCert != null) { - certId = new CertId(issuerCert, - currCert.getSerialNumberObject()); - } else { - // must be an anchor name and key - certId = new CertId(anchor.getCA(), anchor.getCAPublicKey(), - currCert.getSerialNumberObject()); - } + certId = new CertId(issuerInfo.getName(), issuerInfo.getPublicKey(), + currCert.getSerialNumberObject()); // check if there is a cached OCSP response available byte[] responseBytes = ocspResponses.get(cert); @@ -706,8 +726,8 @@ class RevocationChecker extends PKIXRevocationChecker { nonce = ext.getValue(); } } - response.verify(Collections.singletonList(certId), issuerCert, - responderCert, params.date(), nonce); + response.verify(Collections.singletonList(certId), issuerInfo, + responderCert, params.date(), nonce, params.variant()); } else { URI responderURI = (this.responderURI != null) @@ -720,8 +740,8 @@ class RevocationChecker extends PKIXRevocationChecker { } response = OCSP.check(Collections.singletonList(certId), - responderURI, issuerCert, responderCert, - null, ocspExtensions); + responderURI, issuerInfo, responderCert, null, + ocspExtensions, params.variant()); } } catch (IOException e) { throw new CertPathValidatorException( @@ -833,7 +853,7 @@ class RevocationChecker extends PKIXRevocationChecker { if (DistributionPointFetcher.verifyCRL( certImpl, point, crl, reasonsMask, signFlag, prevKey, null, params.sigProvider(), anchors, - certStores, params.date())) + certStores, params.date(), params.variant())) { results.add(crl); } @@ -886,9 +906,9 @@ class RevocationChecker extends PKIXRevocationChecker { " ---checking " + msg + "..."); } - // reject circular dependencies - RFC 3280 is not explicit on how - // to handle this, so we feel it is safest to reject them until - // the issue is resolved in the PKIX WG. + // Reject circular dependencies - RFC 5280 is not explicit on how + // to handle this, but does suggest that they can be a security + // risk and can create unresolvable dependencies if ((stackedCerts != null) && stackedCerts.contains(cert)) { if (debug != null) { debug.println( diff --git a/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java b/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java index 3e6155cb19bcda7225e0d0b9037ddcd90a249dfc..11d8a0673296a03d8e8f13f03e49d3979a660a89 100644 --- a/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java +++ b/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ import sun.security.util.Debug; *

If successful, it returns a certification path which has successfully * satisfied all the constraints and requirements specified in the * PKIXBuilderParameters object and has been validated according to the PKIX - * path validation algorithm defined in RFC 3280. + * path validation algorithm defined in RFC 5280. * *

This implementation uses a depth-first search approach to finding * certification paths. If it comes to a point in which it cannot find @@ -343,7 +343,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { checkers.add(policyChecker); // add the algorithm checker - checkers.add(new AlgorithmChecker(builder.trustAnchor)); + checkers.add(new AlgorithmChecker(builder.trustAnchor, + buildParams.date(), null)); BasicChecker basicChecker = null; if (nextState.keyParamsNeeded()) { diff --git a/src/share/classes/sun/security/ssl/SSLContextImpl.java b/src/share/classes/sun/security/ssl/SSLContextImpl.java index c0cab217ce4eaf8fcf1a3c8b240b78cd49dba23b..b471337f5fa3f0c41464afb3f35e7578b84fad81 100644 --- a/src/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/src/share/classes/sun/security/ssl/SSLContextImpl.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import javax.net.ssl.*; import sun.security.provider.certpath.AlgorithmChecker; import sun.security.action.GetPropertyAction; +import sun.security.validator.Validator; public abstract class SSLContextImpl extends SSLContextSpi { @@ -1040,7 +1041,7 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager constraints = new SSLAlgorithmConstraints(sslSocket, true); } - checkAlgorithmConstraints(chain, constraints); + checkAlgorithmConstraints(chain, constraints, isClient); } } @@ -1082,12 +1083,12 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager constraints = new SSLAlgorithmConstraints(engine, true); } - checkAlgorithmConstraints(chain, constraints); + checkAlgorithmConstraints(chain, constraints, isClient); } } private void checkAlgorithmConstraints(X509Certificate[] chain, - AlgorithmConstraints constraints) throws CertificateException { + AlgorithmConstraints constraints, boolean isClient) throws CertificateException { try { // Does the certificate chain end with a trusted certificate? @@ -1105,7 +1106,9 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager // A forward checker, need to check from trust to target 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); for (int i = checkedLength; i >= 0; i--) { Certificate cert = chain[i]; diff --git a/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java b/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java index b6a5034cad8bb335e2a881e5f7929e78dd68610a..c5c16c46638fe86b249c027d46e2d682cca2e3af 100644 --- a/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java +++ b/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import java.security.cert.Certificate; import javax.net.ssl.*; import sun.security.provider.certpath.AlgorithmChecker; +import sun.security.validator.Validator; /** * The new X509 key manager implementation. The main differences to the @@ -62,7 +63,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager private static final Debug debug = Debug.getInstance("ssl"); - private final static boolean useDebug = + private static final boolean useDebug = (debug != null) && Debug.isOn("keymanager"); // for unit testing only, set via privileged reflection @@ -661,6 +662,15 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager 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 @@ -774,7 +784,8 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager // check the algorithm constraints if (constraints != null && - !conformsToAlgorithmConstraints(constraints, chain)) { + !conformsToAlgorithmConstraints(constraints, chain, + checkType.getValidator())) { if (useDebug) { debug.println("Ignoring alias " + alias + @@ -811,13 +822,19 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager } 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 { checker.init(false); } catch (CertPathValidatorException cpve) { // unlikely to happen + if (useDebug) { + debug.println( + "Cannot initialize algorithm constraints checker: " + cpve); + } + return false; } @@ -828,6 +845,11 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager // We don't care about the unresolved critical extensions. checker.check(cert, Collections.emptySet()); } catch (CertPathValidatorException cpve) { + if (useDebug) { + debug.println("Certificate (" + cert + + ") does not conform to algorithm constraints: " + cpve); + } + return false; } } diff --git a/src/share/classes/sun/security/util/AnchorCertificates.java b/src/share/classes/sun/security/util/AnchorCertificates.java index 849834278025d6f76271c8a2333328fef0cbf415..e260dd44ac047ad641f6da509b49100f5cabaac7 100644 --- a/src/share/classes/sun/security/util/AnchorCertificates.java +++ b/src/share/classes/sun/security/util/AnchorCertificates.java @@ -31,8 +31,10 @@ import java.security.AccessController; import java.security.KeyStore; import java.security.PrivilegedAction; import java.security.cert.X509Certificate; +import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; +import java.util.Set; import sun.security.x509.X509CertImpl; @@ -44,7 +46,7 @@ public class AnchorCertificates { private static final Debug debug = Debug.getInstance("certpath"); private static final String HASH = "SHA-256"; - private static HashSet certs; + private static Set certs = Collections.emptySet(); static { AccessController.doPrivileged(new PrivilegedAction() { diff --git a/src/share/classes/sun/security/util/CertConstraintParameters.java b/src/share/classes/sun/security/util/CertConstraintParameters.java deleted file mode 100644 index 9f7a938dedecfc49b6ef0149b1d158fe12667abd..0000000000000000000000000000000000000000 --- a/src/share/classes/sun/security/util/CertConstraintParameters.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.security.util; - -import java.security.cert.X509Certificate; - -/** - * This class is a wrapper for keeping state and passing objects between PKIX, - * AlgorithmChecker, and DisabledAlgorithmConstraints. - */ -public class CertConstraintParameters { - // A certificate being passed to check against constraints. - private final X509Certificate cert; - - // This is true if the trust anchor in the certificate chain matches a cert - // in AnchorCertificates - private final boolean trustedMatch; - - public CertConstraintParameters(X509Certificate c, boolean match) { - cert = c; - trustedMatch = match; - } - - public CertConstraintParameters(X509Certificate c) { - this(c, false); - } - - // Returns if the trust anchor has a match if anchor checking is enabled. - public boolean isTrustedMatch() { - return trustedMatch; - } - - public X509Certificate getCertificate() { - return cert; - } -} diff --git a/src/share/classes/sun/security/util/ConstraintsParameters.java b/src/share/classes/sun/security/util/ConstraintsParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..8431865455790a3055dd02a20740cc19a2b2aa81 --- /dev/null +++ b/src/share/classes/sun/security/util/ConstraintsParameters.java @@ -0,0 +1,135 @@ +/* + * 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.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.util.Date; + +/** + * This class contains parameters for checking against constraints that extend + * past the publicly available parameters in java.security.AlgorithmConstraints. + + * This is currently on passed between between PKIX, AlgorithmChecker, + * and DisabledAlgorithmConstraints. + */ +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. + private final X509Certificate cert; + // This is true if the trust anchor in the certificate chain matches a cert + // in AnchorCertificates + private final boolean trustedMatch; + // PKIXParameter date + private final Date pkixDate; + // Timestamp of the signed JAR file + private final Timestamp jarTimestamp; + private final String variant; + + public ConstraintsParameters(X509Certificate c, boolean match, + Date pkixdate, Timestamp jarTime, String variant) { + cert = c; + trustedMatch = match; + pkixDate = pkixdate; + jarTimestamp = jarTime; + this.variant = (variant == null ? Validator.VAR_GENERIC : variant); + algorithm = null; + algParams = null; + 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 AlgorithmParameters getAlgParams() { + return algParams; + } + + public Key getPublicKey() { + return publicKey; + } + // Returns if the trust anchor has a match if anchor checking is enabled. + public boolean isTrustedMatch() { + return trustedMatch; + } + + public X509Certificate getCertificate() { + return cert; + } + + public Date getPKIXParamDate() { + return pkixDate; + } + + public Timestamp getJARTimestamp() { + return jarTimestamp; + } + + public String getVariant() { + return variant; + } +} diff --git a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index af1f99b854f3446ea6f170b3e8fa6586567c1423..9051b3929706d739f5c6c3e94ba8af7b0a07edb2 100644 --- a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,28 @@ package sun.security.util; +import sun.security.validator.Validator; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.security.CryptoPrimitive; import java.security.AlgorithmParameters; import java.security.Key; import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException.BasicReason; 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.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.StringTokenizer; +import java.util.TimeZone; import java.util.regex.Pattern; import java.util.regex.Matcher; @@ -49,11 +60,11 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { private static final Debug debug = Debug.getInstance("certpath"); // 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"; // 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"; // the known security property, jdk.jar.disabledAlgorithms @@ -93,14 +104,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { * there are keysize or other limit, this method allow the algorithm. */ @Override - final public boolean permits(Set primitives, + public final boolean permits(Set primitives, String algorithm, AlgorithmParameters parameters) { - - if (primitives == null || primitives.isEmpty()) { - throw new IllegalArgumentException( - "No cryptographic primitive specified"); - } - return checkAlgorithm(disabledAlgorithms, algorithm, decomposer); } @@ -109,7 +114,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { * placed on the key. */ @Override - final public boolean permits(Set primitives, Key key) { + public final boolean permits(Set primitives, Key key) { return checkConstraints(primitives, "", key, null); } @@ -118,7 +123,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { * been placed on the key. */ @Override - final public boolean permits(Set primitives, + public final boolean permits(Set primitives, String algorithm, Key key, AlgorithmParameters parameters) { if (algorithm == null || algorithm.length() == 0) { @@ -128,6 +133,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return checkConstraints(primitives, algorithm, key, parameters); } + public final void permits(ConstraintsParameters cp) + throws CertPathValidatorException { + permits(cp.getAlgorithm(), cp); + } + + public final void permits(String algorithm, 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 * algorithms are allowed, certificate constraints, and the @@ -135,18 +152,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { * * Uses new style permit() which throws exceptions. */ - public final void permits(Set primitives, - CertConstraintParameters cp) throws CertPathValidatorException { - checkConstraints(primitives, cp); - } - /* - * Check if Certificate object is within the constraints. - * Uses new style permit() which throws exceptions. - */ - public final void permits(Set primitives, - X509Certificate cert) throws CertPathValidatorException { - checkConstraints(primitives, new CertConstraintParameters(cert)); + public final void permits(String algorithm, ConstraintsParameters cp) + throws CertPathValidatorException { + algorithmConstraints.permits(algorithm, cp); } // Check if a string is contained inside the property @@ -169,7 +178,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { 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 (!permits(primitives, algorithm, parameters)) { return false; @@ -185,36 +194,6 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return algorithmConstraints.permits(key); } - /* - * Check algorithm constraints with Certificate - * Uses new style permit() which throws exceptions. - */ - private void checkConstraints(Set 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 @@ -229,15 +208,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { * 'true' means the operation is allowed. * '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 * disallowed. */ private static class Constraints { - private Map> constraintsMap = new HashMap<>(); - private static final Pattern keySizePattern = Pattern.compile( - "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); + private Map> constraintsMap = new HashMap<>(); + + 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) { for (String constraintEntry : constraintArray) { @@ -252,39 +234,47 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { // Check if constraint is a complete disabling of an // algorithm or has conditions. - String algorithm; - String policy; int space = constraintEntry.indexOf(' '); - if (space > 0) { - algorithm = AlgorithmDecomposer.hashName( - constraintEntry.substring(0, space). - toUpperCase(Locale.ENGLISH)); - policy = constraintEntry.substring(space + 1); - } else { - constraintsMap.putIfAbsent( - constraintEntry.toUpperCase(Locale.ENGLISH), - new HashSet<>()); + String algorithm = AlgorithmDecomposer.hashName( + ((space > 0 ? constraintEntry.substring(0, space) : + constraintEntry). + toUpperCase(Locale.ENGLISH))); + List constraintList = + constraintsMap.getOrDefault(algorithm, + new ArrayList<>(1)); + constraintsMap.putIfAbsent(algorithm, constraintList); + if (space <= 0) { + constraintList.add(new DisabledConstraint(algorithm)); continue; } + String policy = constraintEntry.substring(space + 1); + // Convert constraint conditions into Constraint classes - Constraint c = null; - Constraint lastConstraint = null; + Constraint c, lastConstraint = null; // Allow only one jdkCA entry per constraint entry boolean jdkCALimit = false; + // Allow only one denyAfter entry per constraint entry + boolean denyAfterLimit = false; for (String entry : policy.split("&")) { entry = entry.trim(); - Matcher matcher = keySizePattern.matcher(entry); - if (matcher.matches()) { + Matcher matcher; + if (entry.startsWith("keySize")) { if (debug != null) { debug.println("Constraints set to keySize: " + 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, - KeySizeConstraint.Operator.of(matcher.group(1)), - Integer.parseInt(matcher.group(2))); + KeySizeConstraint.Operator.of(tokens.nextToken()), + Integer.parseInt(tokens.nextToken())); } else if (entry.equalsIgnoreCase("jdkCA")) { if (debug != null) { @@ -297,18 +287,39 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { } c = new jdkCAConstraint(algorithm); 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 // into a linked list. if (lastConstraint == null) { - if (!constraintsMap.containsKey(algorithm)) { - constraintsMap.putIfAbsent(algorithm, - new HashSet<>()); - } - if (c != null) { - constraintsMap.get(algorithm).add(c); - } + constraintList.add(c); } else { lastConstraint.nextConstraint = c; } @@ -318,61 +329,73 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { } // Get applicable constraints based off the signature algorithm - private Set getConstraints(String algorithm) { + private List getConstraints(String algorithm) { return constraintsMap.get(algorithm); } // Check if KeySizeConstraints permit the specified key public boolean permits(Key key) { - Set set = getConstraints(key.getAlgorithm()); - if (set == null) { + List list = getConstraints(key.getAlgorithm()); + if (list == null) { return true; } - for (Constraint constraint : set) { + for (Constraint constraint : list) { if (!constraint.permits(key)) { if (debug != null) { debug.println("keySizeConstraint: failed key " + "constraint check " + KeyUtil.getKeySize(key)); } - return false; - } + return false; + } } - return true; - } + return true; + } // Check if constraints permit this cert. - public void permits(CertConstraintParameters cp) + public void permits(String algorithm, ConstraintsParameters cp) throws CertPathValidatorException { X509Certificate cert = cp.getCertificate(); 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 - Set algorithms = - AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName()); - if (algorithms == null || algorithms.isEmpty()) { - return; - } - - // Attempt to add the public key algorithm to the set - algorithms.add(cert.getPublicKey().getAlgorithm()); + Set algorithms = new HashSet<>(); + if (algorithm != null) { + algorithms.addAll(AlgorithmDecomposer.decomposeOneHash(algorithm)); + } + // 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 - for (String algorithm : algorithms) { - Set set = getConstraints(algorithm); - if (set == null) { + for (String alg : algorithms) { + List list = getConstraints(alg); + if (list == null) { continue; } - for (Constraint constraint : set) { + for (Constraint constraint : list) { 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 { String algorithm; Constraint nextConstraint = null; @@ -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 - * @return true if constraints do not match + * @return 'true' if constraint is allowed, 'false' if disallowed. */ public boolean permits(Key key) { return true; } /** - * Check if an algorithm constraint is permit this certificate to - * be used. - * @param cp CertificateParameter containing certificate and state info - * @return true if constraints do not match + * Check if an algorithm constraint is permitted with a given + * ConstraintsParameters. + * + * 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; + + /** + * 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 { } /* - * Check if each constraint fails and check if there is a linked - * constraint Any permitted constraint will exit the linked list - * to allow the operation. + * Check if ConstraintsParameters has a trusted match, if it does + * call next() for any following constraints. If it does not, exit + * as this constraint(s) does not restrict the operation. */ - public void permits(CertConstraintParameters cp) + public void permits(ConstraintsParameters cp) throws CertPathValidatorException { if (debug != null) { 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 (nextConstraint != null) { - nextConstraint.permits(cp); + if (next(cp)) { return; } throw new CertPathValidatorException( "Algorithm constraints check failed on certificate " + - "anchor limits", + "anchor limits. " + algorithm + extendedMsg(cp), 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 @@ -470,6 +703,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { private int minSize; // the minimal available key size private int maxSize; // the maximal available key size private int prohibitedSize = -1; // unavailable key sizes + private int size; public KeySizeConstraint(String algo, Operator operator, int length) { algorithm = algo; @@ -513,15 +747,22 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { * constraint Any permitted constraint will exit the linked list * to allow the operation. */ - public void permits(CertConstraintParameters cp) + public void permits(ConstraintsParameters cp) 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) { nextConstraint.permits(cp); return; } 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); } } @@ -548,7 +789,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return true; } - int size = KeyUtil.getKeySize(key); + size = KeyUtil.getKeySize(key); if (size == 0) { return false; // we don't allow any key of size 0. } else if (size > 0) { @@ -559,6 +800,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { 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; } } +} diff --git a/src/share/classes/sun/security/util/SignatureFileVerifier.java b/src/share/classes/sun/security/util/SignatureFileVerifier.java index ed563dc7b2d6473d9a881ff9beec26610680234c..0663f0573ae35823427a3abbc503151bb292a354 100644 --- a/src/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/src/share/classes/sun/security/util/SignatureFileVerifier.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -28,25 +28,23 @@ package sun.security.util; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.CodeSigner; -import java.security.CryptoPrimitive; +import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; +import java.security.Timestamp; import java.security.cert.CertPath; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.util.ArrayList; import java.util.Base64; -import java.util.Collections; -import java.util.EnumSet; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarException; import java.util.jar.JarFile; @@ -61,9 +59,6 @@ public class SignatureFileVerifier { /* Are we debugging ? */ private static final Debug debug = Debug.getInstance("jar"); - private static final Set DIGEST_PRIMITIVE_SET = - Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST)); - private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK = new DisabledAlgorithmConstraints( DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS); @@ -78,7 +73,7 @@ public class SignatureFileVerifier { private PKCS7 block; /** the raw bytes of the .SF file */ - private byte sfBytes[]; + private byte[] sfBytes; /** the name of the signature block file, uppercased and without * the extension (.DSA/.RSA/.EC) @@ -97,6 +92,14 @@ public class SignatureFileVerifier { /* for generating certpath objects */ private CertificateFactory certificateFactory = null; + /** Algorithms that have been checked if they are weak. */ + private Map 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. * @@ -107,7 +110,7 @@ public class SignatureFileVerifier { public SignatureFileVerifier(ArrayList signerCache, ManifestDigester md, String name, - byte rawBytes[]) + byte[] rawBytes) throws IOException, CertificateException { // new PKCS7() calls CertificateFactory.getInstance() @@ -121,7 +124,7 @@ public class SignatureFileVerifier { } finally { Providers.stopJarVerification(obj); } - this.name = name.substring(0, name.lastIndexOf(".")) + this.name = name.substring(0, name.lastIndexOf('.')) .toUpperCase(Locale.ENGLISH); this.md = md; this.signerCache = signerCache; @@ -152,7 +155,7 @@ public class SignatureFileVerifier { * used to set the raw bytes of the .SF file when it * is external to the signature block file. */ - public void setSignatureFile(byte sfBytes[]) + public void setSignatureFile(byte[] sfBytes) { this.sfBytes = sfBytes; } @@ -168,11 +171,10 @@ public class SignatureFileVerifier { */ public static boolean isBlockOrSF(String s) { // we currently only support DSA and RSA PKCS7 blocks - if (s.endsWith(".SF") || s.endsWith(".DSA") || - s.endsWith(".RSA") || s.endsWith(".EC")) { - return true; - } - return false; + return s.endsWith(".SF") + || s.endsWith(".DSA") + || s.endsWith(".RSA") + || s.endsWith(".EC"); } /** @@ -182,7 +184,7 @@ public class SignatureFileVerifier { * unknown signature related files (those starting with SIG- with * 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 */ public static boolean isSigningRelated(String name) { @@ -198,7 +200,7 @@ public class SignatureFileVerifier { return true; } else if (name.startsWith("SIG-")) { // 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 int extIndex = name.lastIndexOf('.'); if (extIndex != -1) { @@ -223,17 +225,10 @@ public class SignatureFileVerifier { /** get digest from cache */ - private MessageDigest getDigest(String algorithm) throws SignatureException { - // check that algorithm is not restricted - if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, algorithm, null)) { - SignatureException e = - new SignatureException("SignatureFile check failed. " + - "Disabled algorithm used: " + algorithm); - throw e; - } - + private MessageDigest getDigest(String algorithm) + throws SignatureException { if (createdDigests == null) - createdDigests = new HashMap(); + createdDigests = new HashMap<>(); MessageDigest digest = createdDigests.get(algorithm); @@ -303,6 +298,27 @@ public class SignatureFileVerifier { if (newSigners == null) return; + /* + * Look for the latest timestamp in the signature block. If an entry + * has no timestamp, use current time (aka null). + */ + for (CodeSigner s: newSigners) { + if (debug != null) { + debug.println("Gathering timestamp for: " + s.toString()); + } + if (s.getTimestamp() == null) { + timestamp = null; + break; + } else if (timestamp == null) { + timestamp = s.getTimestamp(); + } else { + if (timestamp.getTimestamp().before( + s.getTimestamp().getTimestamp())) { + timestamp = s.getTimestamp(); + } + } + } + Iterator> entries = sf.getEntries().entrySet().iterator(); @@ -345,6 +361,68 @@ public class SignatureFileVerifier { 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. */ @@ -355,6 +433,10 @@ public class SignatureFileVerifier { { Attributes mattr = sf.getMainAttributes(); 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 for (Map.Entry se : mattr.entrySet()) { @@ -364,6 +446,16 @@ public class SignatureFileVerifier { if (key.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST-MANIFEST")) { // 16 is length of "-Digest-Manifest" 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(se.getValue()); @@ -374,15 +466,14 @@ public class SignatureFileVerifier { Base64.getMimeDecoder().decode((String)se.getValue()); if (debug != null) { - debug.println("Signature File: Manifest digest " + - digest.getAlgorithm()); - debug.println( " sigfile " + toHex(expectedHash)); - debug.println( " computed " + toHex(computedHash)); - debug.println(); + debug.println("Signature File: Manifest digest " + + algorithm); + debug.println( " sigfile " + toHex(expectedHash)); + debug.println( " computed " + toHex(computedHash)); + debug.println(); } - if (MessageDigest.isEqual(computedHash, - expectedHash)) { + if (MessageDigest.isEqual(computedHash, expectedHash)) { manifestSigned = true; } else { //XXX: we will continue and verify each section @@ -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; } - private boolean verifyManifestMainAttrs(Manifest sf, - ManifestDigester md) + private boolean verifyManifestMainAttrs(Manifest sf, ManifestDigester md) throws IOException, SignatureException { Attributes mattr = sf.getMainAttributes(); 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 // digest entries for the manifest main attributes @@ -408,6 +517,16 @@ public class SignatureFileVerifier { if (key.toUpperCase(Locale.ENGLISH).endsWith(ATTR_DIGEST)) { String algorithm = 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); if (digest != null) { @@ -426,8 +545,7 @@ public class SignatureFileVerifier { debug.println(); } - if (MessageDigest.isEqual(computedHash, - expectedHash)) { + if (MessageDigest.isEqual(computedHash, expectedHash)) { // good } else { // we will *not* continue and verify each section @@ -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: // . manifest main attributes were not signed, or // . manifest main attributes were signed and verified @@ -465,6 +599,10 @@ public class SignatureFileVerifier { { boolean oneDigestVerified = false; 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) { throw new SecurityException( @@ -472,8 +610,7 @@ public class SignatureFileVerifier { } if (sfAttr != null) { - - //sun.misc.HexDumpEncoder hex = new sun.misc.HexDumpEncoder(); + //sun.security.util.HexDumpEncoder hex = new sun.security.util.HexDumpEncoder(); //hex.encodeBuffer(data, System.out); // go through all the attributes and process *-Digest entries @@ -483,6 +620,16 @@ public class SignatureFileVerifier { if (key.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST")) { // 7 is length of "-Digest" 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); @@ -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; } @@ -541,7 +704,7 @@ public class SignatureFileVerifier { * CodeSigner objects. We do this only *once* for a given * signature block file. */ - private CodeSigner[] getSigners(SignerInfo infos[], PKCS7 block) + private CodeSigner[] getSigners(SignerInfo[] infos, PKCS7 block) throws IOException, NoSuchAlgorithmException, SignatureException, CertificateException { @@ -553,7 +716,7 @@ public class SignatureFileVerifier { ArrayList chain = info.getCertificateChain(block); CertPath certChain = certificateFactory.generateCertPath(chain); if (signers == null) { - signers = new ArrayList(); + signers = new ArrayList<>(); } // Append the new code signer signers.add(new CodeSigner(certChain, info.getTimestamp())); @@ -582,7 +745,7 @@ public class SignatureFileVerifier { static String toHex(byte[] data) { - StringBuffer sb = new StringBuffer(data.length*2); + StringBuilder sb = new StringBuilder(data.length*2); for (int i=0; i>4) & 0x0f]); diff --git a/src/share/classes/sun/security/validator/PKIXValidator.java b/src/share/classes/sun/security/validator/PKIXValidator.java index 51761e1bd172313c0baba006950fadfbc52a9a91..9be502626e6e3d54e229e05c93fe3b2f6f94b01f 100644 --- a/src/share/classes/sun/security/validator/PKIXValidator.java +++ b/src/share/classes/sun/security/validator/PKIXValidator.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,11 @@ import java.security.cert.*; import javax.security.auth.x500.X500Principal; import sun.security.action.GetBooleanAction; import sun.security.provider.certpath.AlgorithmChecker; +import sun.security.provider.certpath.PKIXExtendedParameters; /** * Validator implementation built on the PKIX CertPath API. This - * implementation will be emphasized going forward.

+ * implementation will be emphasized going forward. *

* Note that the validate() implementation tries to use a PKIX validator * if that appears possible and a PKIX builder otherwise. This increases @@ -208,13 +209,22 @@ public final class PKIXValidator extends Validator { ("null or zero-length certificate chain"); } - // add new algorithm constraints checker - PKIXBuilderParameters pkixParameters = - (PKIXBuilderParameters) parameterTemplate.clone(); - AlgorithmChecker algorithmChecker = null; + // Use PKIXExtendedParameters for timestamp and variant additions + PKIXBuilderParameters pkixParameters = null; + try { + 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) { - algorithmChecker = new AlgorithmChecker(constraints); - pkixParameters.addCertPathChecker(algorithmChecker); + pkixParameters.addCertPathChecker( + new AlgorithmChecker(constraints, null, variant)); } if (TRY_VALIDATOR) { diff --git a/src/share/classes/sun/security/validator/SimpleValidator.java b/src/share/classes/sun/security/validator/SimpleValidator.java index f041a8c6d9bce5114c76c56e505682cb2baea49a..97d6fd1413604c022f4eec94b5677cb0185c90ba 100644 --- a/src/share/classes/sun/security/validator/SimpleValidator.java +++ b/src/share/classes/sun/security/validator/SimpleValidator.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import java.security.cert.*; import javax.security.auth.x500.X500Principal; import sun.security.x509.X509CertImpl; +import sun.security.x509.KeyIdentifier; import sun.security.x509.NetscapeCertTypeExtension; import sun.security.util.DerValue; import sun.security.util.DerInputStream; @@ -153,12 +154,14 @@ public final class SimpleValidator extends Validator { // create default algorithm constraints checker TrustAnchor anchor = new TrustAnchor(anchorCert, null); - AlgorithmChecker defaultAlgChecker = new AlgorithmChecker(anchor); + AlgorithmChecker defaultAlgChecker = + new AlgorithmChecker(anchor, variant); // create application level algorithm constraints checker AlgorithmChecker appAlgChecker = 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 diff --git a/src/share/classes/sun/security/x509/PKIXExtensions.java b/src/share/classes/sun/security/x509/PKIXExtensions.java index 3c7696327afc3dc5742d4a098f9ccfbcccb314a7..838843f6f80a83e3a6f6ac2592bf7bf30f42d4b8 100644 --- a/src/share/classes/sun/security/x509/PKIXExtensions.java +++ b/src/share/classes/sun/security/x509/PKIXExtensions.java @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -49,34 +49,39 @@ import sun.security.util.*; */ public class PKIXExtensions { // The object identifiers - private static final int AuthorityKey_data [] = { 2, 5, 29, 35 }; - private static final int SubjectKey_data [] = { 2, 5, 29, 14 }; - private static final int KeyUsage_data [] = { 2, 5, 29, 15 }; - private static final int PrivateKeyUsage_data [] = { 2, 5, 29, 16 }; - private static final int CertificatePolicies_data [] = { 2, 5, 29, 32 }; - private static final int PolicyMappings_data [] = { 2, 5, 29, 33 }; - private static final int SubjectAlternativeName_data [] = { 2, 5, 29, 17 }; - private static final int IssuerAlternativeName_data [] = { 2, 5, 29, 18 }; - private static final int SubjectDirectoryAttributes_data [] = { 2, 5, 29, 9 }; - private static final int BasicConstraints_data [] = { 2, 5, 29, 19 }; - private static final int NameConstraints_data [] = { 2, 5, 29, 30 }; - private static final int PolicyConstraints_data [] = { 2, 5, 29, 36 }; - private static final int CRLDistributionPoints_data [] = { 2, 5, 29, 31 }; - private static final int CRLNumber_data [] = { 2, 5, 29, 20 }; - private static final int IssuingDistributionPoint_data [] = { 2, 5, 29, 28 }; - private static final int DeltaCRLIndicator_data [] = { 2, 5, 29, 27 }; - private static final int ReasonCode_data [] = { 2, 5, 29, 21 }; - private static final int HoldInstructionCode_data [] = { 2, 5, 29, 23 }; - private static final int InvalidityDate_data [] = { 2, 5, 29, 24 }; - private static final int ExtendedKeyUsage_data [] = { 2, 5, 29, 37 }; - private static final int InhibitAnyPolicy_data [] = { 2, 5, 29, 54 }; - 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 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 OCSPNoCheck_data [] = { 1, 3, 6, 1, 5, 5, 7, + private static final int[] AuthorityKey_data = { 2, 5, 29, 35 }; + private static final int[] SubjectKey_data = { 2, 5, 29, 14 }; + private static final int[] KeyUsage_data = { 2, 5, 29, 15 }; + private static final int[] PrivateKeyUsage_data = { 2, 5, 29, 16 }; + private static final int[] CertificatePolicies_data = { 2, 5, 29, 32 }; + private static final int[] PolicyMappings_data = { 2, 5, 29, 33 }; + private static final int[] SubjectAlternativeName_data = { 2, 5, 29, 17 }; + private static final int[] IssuerAlternativeName_data = { 2, 5, 29, 18 }; + private static final int[] SubjectDirectoryAttributes_data = { 2, 5, 29, 9 }; + private static final int[] BasicConstraints_data = { 2, 5, 29, 19 }; + private static final int[] NameConstraints_data = { 2, 5, 29, 30 }; + private static final int[] PolicyConstraints_data = { 2, 5, 29, 36 }; + private static final int[] CRLDistributionPoints_data = { 2, 5, 29, 31 }; + private static final int[] CRLNumber_data = { 2, 5, 29, 20 }; + private static final int[] IssuingDistributionPoint_data = { 2, 5, 29, 28 }; + private static final int[] DeltaCRLIndicator_data = { 2, 5, 29, 27 }; + private static final int[] ReasonCode_data = { 2, 5, 29, 21 }; + private static final int[] HoldInstructionCode_data = { 2, 5, 29, 23 }; + private static final int[] InvalidityDate_data = { 2, 5, 29, 24 }; + private static final int[] ExtendedKeyUsage_data = { 2, 5, 29, 37 }; + private static final int[] InhibitAnyPolicy_data = { 2, 5, 29, 54 }; + 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[] 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[] OCSPNoCheck_data = { 1, 3, 6, 1, 5, 5, 7, 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. */ @@ -104,18 +109,20 @@ public class PKIXExtensions { public static final ObjectIdentifier CertificatePolicies_Id; /** - * Lists pairs of objectidentifiers of policies considered equivalent by the - * issuing CA to the subject CA. + * Lists pairs of object identifiers of policies considered equivalent by + * the issuing CA to the subject CA. */ 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; /** - * 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; @@ -224,6 +231,12 @@ public class PKIXExtensions { */ 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 { AuthorityKey_Id = ObjectIdentifier.newInternal(AuthorityKey_data); SubjectKey_Id = ObjectIdentifier.newInternal(SubjectKey_data); @@ -266,5 +279,6 @@ public class PKIXExtensions { ObjectIdentifier.newInternal(SubjectInfoAccess_data); FreshestCRL_Id = ObjectIdentifier.newInternal(FreshestCRL_data); OCSPNoCheck_Id = ObjectIdentifier.newInternal(OCSPNoCheck_data); + OCSPNonce_Id = ObjectIdentifier.newInternal(OCSPNonce_data); } } diff --git a/src/share/lib/security/java.security-aix b/src/share/lib/security/java.security-aix index 609644a6929f83ec3b4bb97d2f8e569e39dadbdd..4e68eaf9627c22ae56762dce96f0a4bfe995f431 100644 --- a/src/share/lib/security/java.security-aix +++ b/src/share/lib/security/java.security-aix @@ -422,9 +422,7 @@ krb5.kdc.bad.policy = tryLast # describes the mechanism for disabling algorithms based on algorithm name # and/or key length. This includes algorithms used in certificates, as well # as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: +# The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # @@ -435,25 +433,26 @@ krb5.kdc.bad.policy = tryLast # (see below) # # Constraint: -# KeySizeConstraint, CertConstraint +# KeySizeConstraint | CAConstraint | DenyAfterConstraint | +# UsageConstraint # # KeySizeConstraint: -# keySize Operator DecimalInteger +# keySize Operator KeyLength # # Operator: # <= | < | == | != | >= | > # -# DecimalInteger: -# DecimalDigits +# KeyLength: +# Integer value of the algorithm's key length in bits # -# DecimalDigits: -# DecimalDigit {DecimalDigit} +# CAConstraint: +# jdkCA # -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD # -# CertConstraint -# jdkCA +# UsageConstraint: +# usage [TLSServer] [TLSClient] [SignedJAR] # # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name @@ -467,27 +466,55 @@ krb5.kdc.bad.policy = tryLast # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # will not disable algorithms related to "ECDSA". # -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# "CertConstraint" specifies additional constraints for -# certificates that contain algorithms that are restricted: -# -# "jdkCA" prohibits the specified algorithm only if the algorithm is used -# in a certificate chain that terminates at a marked trust anchor in the -# lib/security/cacerts keystore. All other chains are not affected. -# If the jdkCA constraint is not set, then all chains using the -# specified algorithm 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" +# A "Constraint" defines restrictions on the keys and/or certificates for +# a specified AlgorithmName: +# +# KeySizeConstraint: +# keySize Operator KeyLength +# The constraint requires a key of a valid size range if the +# "AlgorithmName" is of a key algorithm. The "KeyLength" indicates +# the key size specified in number of bits. For example, +# "RSA keySize <= 1024" indicates that any RSA key with key size less +# than or equal to 1024 bits should be disabled, and +# "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key +# 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. +# +# CAConstraint: +# jdkCA +# This constraint prohibits the specified algorithm only if the +# algorithm is used in a certificate chain that terminates at a marked +# trust anchor in the lib/security/cacerts keystore. If the jdkCA +# constraint is not set, then all chains using the specified algorithm +# 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 # delimited by an ampersand '&'. For example, to restrict certificates in a @@ -500,6 +527,9 @@ krb5.kdc.bad.policy = tryLast # before larger keysize constraints of the same algorithm. For example: # "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 # is not guaranteed to be examined and used by other implementations. # @@ -507,9 +537,10 @@ krb5.kdc.bad.policy = tryLast # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ - DSA keySize < 1024, EC keySize < 224 +jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ + RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 +# # Algorithm restrictions for signed JAR files # # In some environments, certain algorithms or key lengths may be undesirable @@ -524,17 +555,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint | DenyAfterConstraint # # KeySizeConstraint: # keySize Operator KeyLength # +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD +# # Operator: # <= | < | == | != | >= | > # @@ -545,8 +579,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # implementation. It is not guaranteed to be examined and used by other # implementations. # +# See "jdk.certpath.disabledAlgorithms" for syntax descriptions. +# jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +# # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing # @@ -568,6 +605,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 # See the specification of "jdk.certpath.disabledAlgorithms" for the # 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. # It is not guaranteed to be examined and used by other implementations. # diff --git a/src/share/lib/security/java.security-linux b/src/share/lib/security/java.security-linux index acef8f0b41e03b4be7f3d07d86c6fb066abf1984..4e68eaf9627c22ae56762dce96f0a4bfe995f431 100644 --- a/src/share/lib/security/java.security-linux +++ b/src/share/lib/security/java.security-linux @@ -422,9 +422,7 @@ krb5.kdc.bad.policy = tryLast # describes the mechanism for disabling algorithms based on algorithm name # and/or key length. This includes algorithms used in certificates, as well # as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: +# The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # @@ -435,25 +433,26 @@ krb5.kdc.bad.policy = tryLast # (see below) # # Constraint: -# KeySizeConstraint, CertConstraint +# KeySizeConstraint | CAConstraint | DenyAfterConstraint | +# UsageConstraint # # KeySizeConstraint: -# keySize Operator DecimalInteger +# keySize Operator KeyLength # # Operator: # <= | < | == | != | >= | > # -# DecimalInteger: -# DecimalDigits +# KeyLength: +# Integer value of the algorithm's key length in bits # -# DecimalDigits: -# DecimalDigit {DecimalDigit} +# CAConstraint: +# jdkCA # -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD # -# CertConstraint -# jdkCA +# UsageConstraint: +# usage [TLSServer] [TLSClient] [SignedJAR] # # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name @@ -467,27 +466,55 @@ krb5.kdc.bad.policy = tryLast # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # will not disable algorithms related to "ECDSA". # -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# "CertConstraint" specifies additional constraints for -# certificates that contain algorithms that are restricted: -# -# "jdkCA" prohibits the specified algorithm only if the algorithm is used -# in a certificate chain that terminates at a marked trust anchor in the -# lib/security/cacerts keystore. All other chains are not affected. -# If the jdkCA constraint is not set, then all chains using the -# specified algorithm 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" +# A "Constraint" defines restrictions on the keys and/or certificates for +# a specified AlgorithmName: +# +# KeySizeConstraint: +# keySize Operator KeyLength +# The constraint requires a key of a valid size range if the +# "AlgorithmName" is of a key algorithm. The "KeyLength" indicates +# the key size specified in number of bits. For example, +# "RSA keySize <= 1024" indicates that any RSA key with key size less +# than or equal to 1024 bits should be disabled, and +# "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key +# 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. +# +# CAConstraint: +# jdkCA +# This constraint prohibits the specified algorithm only if the +# algorithm is used in a certificate chain that terminates at a marked +# trust anchor in the lib/security/cacerts keystore. If the jdkCA +# constraint is not set, then all chains using the specified algorithm +# 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 # delimited by an ampersand '&'. For example, to restrict certificates in a @@ -500,6 +527,9 @@ krb5.kdc.bad.policy = tryLast # before larger keysize constraints of the same algorithm. For example: # "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 # is not guaranteed to be examined and used by other implementations. # @@ -507,9 +537,10 @@ krb5.kdc.bad.policy = tryLast # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ - DSA keySize < 1024, EC keySize < 224 +jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ + RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 +# # Algorithm restrictions for signed JAR files # # In some environments, certain algorithms or key lengths may be undesirable @@ -524,17 +555,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint | DenyAfterConstraint # # KeySizeConstraint: # keySize Operator KeyLength # +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD +# # Operator: # <= | < | == | != | >= | > # @@ -545,8 +579,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # implementation. It is not guaranteed to be examined and used by other # implementations. # +# See "jdk.certpath.disabledAlgorithms" for syntax descriptions. +# jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +# # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing # @@ -568,6 +605,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 # See the specification of "jdk.certpath.disabledAlgorithms" for the # 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. # It is not guaranteed to be examined and used by other implementations. # diff --git a/src/share/lib/security/java.security-macosx b/src/share/lib/security/java.security-macosx index 42aff370b38876f1bda5469c6c6d5c72577a69fe..140e0526bbfe2f30192bca6e64482e40038628ff 100644 --- a/src/share/lib/security/java.security-macosx +++ b/src/share/lib/security/java.security-macosx @@ -425,9 +425,7 @@ krb5.kdc.bad.policy = tryLast # describes the mechanism for disabling algorithms based on algorithm name # and/or key length. This includes algorithms used in certificates, as well # as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: +# The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # @@ -438,25 +436,26 @@ krb5.kdc.bad.policy = tryLast # (see below) # # Constraint: -# KeySizeConstraint, CertConstraint +# KeySizeConstraint | CAConstraint | DenyAfterConstraint | +# UsageConstraint # # KeySizeConstraint: -# keySize Operator DecimalInteger +# keySize Operator KeyLength # # Operator: # <= | < | == | != | >= | > # -# DecimalInteger: -# DecimalDigits +# KeyLength: +# Integer value of the algorithm's key length in bits # -# DecimalDigits: -# DecimalDigit {DecimalDigit} +# CAConstraint: +# jdkCA # -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD # -# CertConstraint -# jdkCA +# UsageConstraint: +# usage [TLSServer] [TLSClient] [SignedJAR] # # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name @@ -470,27 +469,55 @@ krb5.kdc.bad.policy = tryLast # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # will not disable algorithms related to "ECDSA". # -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# "CertConstraint" specifies additional constraints for -# certificates that contain algorithms that are restricted: -# -# "jdkCA" prohibits the specified algorithm only if the algorithm is used -# in a certificate chain that terminates at a marked trust anchor in the -# lib/security/cacerts keystore. All other chains are not affected. -# If the jdkCA constraint is not set, then all chains using the -# specified algorithm 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" +# A "Constraint" defines restrictions on the keys and/or certificates for +# a specified AlgorithmName: +# +# KeySizeConstraint: +# keySize Operator KeyLength +# The constraint requires a key of a valid size range if the +# "AlgorithmName" is of a key algorithm. The "KeyLength" indicates +# the key size specified in number of bits. For example, +# "RSA keySize <= 1024" indicates that any RSA key with key size less +# than or equal to 1024 bits should be disabled, and +# "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key +# 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. +# +# CAConstraint: +# jdkCA +# This constraint prohibits the specified algorithm only if the +# algorithm is used in a certificate chain that terminates at a marked +# trust anchor in the lib/security/cacerts keystore. If the jdkCA +# constraint is not set, then all chains using the specified algorithm +# 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 # delimited by an ampersand '&'. For example, to restrict certificates in a @@ -503,6 +530,9 @@ krb5.kdc.bad.policy = tryLast # before larger keysize constraints of the same algorithm. For example: # "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 # is not guaranteed to be examined and used by other implementations. # @@ -510,9 +540,10 @@ krb5.kdc.bad.policy = tryLast # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ - DSA keySize < 1024, EC keySize < 224 +jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ + RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 +# # Algorithm restrictions for signed JAR files # # In some environments, certain algorithms or key lengths may be undesirable @@ -527,17 +558,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint | DenyAfterConstraint # # KeySizeConstraint: # keySize Operator KeyLength # +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD +# # Operator: # <= | < | == | != | >= | > # @@ -548,8 +582,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # implementation. It is not guaranteed to be examined and used by other # implementations. # +# See "jdk.certpath.disabledAlgorithms" for syntax descriptions. +# jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +# # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing # @@ -571,6 +608,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 # See the specification of "jdk.certpath.disabledAlgorithms" for the # 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. # It is not guaranteed to be examined and used by other implementations. # diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris index f4e58665a8bd0649b208d2f8456518ccca46ace8..ab16edf8540886e0c5550198d164df1ce53ba835 100644 --- a/src/share/lib/security/java.security-solaris +++ b/src/share/lib/security/java.security-solaris @@ -424,9 +424,7 @@ krb5.kdc.bad.policy = tryLast # describes the mechanism for disabling algorithms based on algorithm name # and/or key length. This includes algorithms used in certificates, as well # as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: +# The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # @@ -437,25 +435,26 @@ krb5.kdc.bad.policy = tryLast # (see below) # # Constraint: -# KeySizeConstraint, CertConstraint +# KeySizeConstraint | CAConstraint | DenyAfterConstraint | +# UsageConstraint # # KeySizeConstraint: -# keySize Operator DecimalInteger +# keySize Operator KeyLength # # Operator: # <= | < | == | != | >= | > # -# DecimalInteger: -# DecimalDigits +# KeyLength: +# Integer value of the algorithm's key length in bits # -# DecimalDigits: -# DecimalDigit {DecimalDigit} +# CAConstraint: +# jdkCA # -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD # -# CertConstraint -# jdkCA +# UsageConstraint: +# usage [TLSServer] [TLSClient] [SignedJAR] # # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name @@ -469,27 +468,55 @@ krb5.kdc.bad.policy = tryLast # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # will not disable algorithms related to "ECDSA". # -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# "CertConstraint" specifies additional constraints for -# certificates that contain algorithms that are restricted: -# -# "jdkCA" prohibits the specified algorithm only if the algorithm is used -# in a certificate chain that terminates at a marked trust anchor in the -# lib/security/cacerts keystore. All other chains are not affected. -# If the jdkCA constraint is not set, then all chains using the -# specified algorithm 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" +# A "Constraint" defines restrictions on the keys and/or certificates for +# a specified AlgorithmName: +# +# KeySizeConstraint: +# keySize Operator KeyLength +# The constraint requires a key of a valid size range if the +# "AlgorithmName" is of a key algorithm. The "KeyLength" indicates +# the key size specified in number of bits. For example, +# "RSA keySize <= 1024" indicates that any RSA key with key size less +# than or equal to 1024 bits should be disabled, and +# "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key +# 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. +# +# CAConstraint: +# jdkCA +# This constraint prohibits the specified algorithm only if the +# algorithm is used in a certificate chain that terminates at a marked +# trust anchor in the lib/security/cacerts keystore. If the jdkCA +# constraint is not set, then all chains using the specified algorithm +# 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 # delimited by an ampersand '&'. For example, to restrict certificates in a @@ -502,6 +529,9 @@ krb5.kdc.bad.policy = tryLast # before larger keysize constraints of the same algorithm. For example: # "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 # is not guaranteed to be examined and used by other implementations. # @@ -509,9 +539,10 @@ krb5.kdc.bad.policy = tryLast # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ - DSA keySize < 1024, EC keySize < 224 +jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ + RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 +# # Algorithm restrictions for signed JAR files # # In some environments, certain algorithms or key lengths may be undesirable @@ -526,17 +557,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint | DenyAfterConstraint # # KeySizeConstraint: # keySize Operator KeyLength # +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD +# # Operator: # <= | < | == | != | >= | > # @@ -547,8 +581,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # implementation. It is not guaranteed to be examined and used by other # implementations. # +# See "jdk.certpath.disabledAlgorithms" for syntax descriptions. +# jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +# # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing # @@ -570,6 +607,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 # See the specification of "jdk.certpath.disabledAlgorithms" for the # 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. # It is not guaranteed to be examined and used by other implementations. # diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows index 8405da5533a2b26ada2619ac52e129ea6c5a5120..404a61e0fa956781f4a0ae316ceb42da3dcbd3df 100644 --- a/src/share/lib/security/java.security-windows +++ b/src/share/lib/security/java.security-windows @@ -425,9 +425,7 @@ krb5.kdc.bad.policy = tryLast # describes the mechanism for disabling algorithms based on algorithm name # and/or key length. This includes algorithms used in certificates, as well # as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: +# The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # @@ -438,25 +436,26 @@ krb5.kdc.bad.policy = tryLast # (see below) # # Constraint: -# KeySizeConstraint, CertConstraint +# KeySizeConstraint | CAConstraint | DenyAfterConstraint | +# UsageConstraint # # KeySizeConstraint: -# keySize Operator DecimalInteger +# keySize Operator KeyLength # # Operator: # <= | < | == | != | >= | > # -# DecimalInteger: -# DecimalDigits +# KeyLength: +# Integer value of the algorithm's key length in bits # -# DecimalDigits: -# DecimalDigit {DecimalDigit} +# CAConstraint: +# jdkCA # -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD # -# CertConstraint -# jdkCA +# UsageConstraint: +# usage [TLSServer] [TLSClient] [SignedJAR] # # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name @@ -470,27 +469,55 @@ krb5.kdc.bad.policy = tryLast # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # will not disable algorithms related to "ECDSA". # -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# "CertConstraint" specifies additional constraints for -# certificates that contain algorithms that are restricted: -# -# "jdkCA" prohibits the specified algorithm only if the algorithm is used -# in a certificate chain that terminates at a marked trust anchor in the -# lib/security/cacerts keystore. All other chains are not affected. -# If the jdkCA constraint is not set, then all chains using the -# specified algorithm 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" +# A "Constraint" defines restrictions on the keys and/or certificates for +# a specified AlgorithmName: +# +# KeySizeConstraint: +# keySize Operator KeyLength +# The constraint requires a key of a valid size range if the +# "AlgorithmName" is of a key algorithm. The "KeyLength" indicates +# the key size specified in number of bits. For example, +# "RSA keySize <= 1024" indicates that any RSA key with key size less +# than or equal to 1024 bits should be disabled, and +# "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key +# 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. +# +# CAConstraint: +# jdkCA +# This constraint prohibits the specified algorithm only if the +# algorithm is used in a certificate chain that terminates at a marked +# trust anchor in the lib/security/cacerts keystore. If the jdkCA +# constraint is not set, then all chains using the specified algorithm +# 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 # delimited by an ampersand '&'. For example, to restrict certificates in a @@ -503,6 +530,9 @@ krb5.kdc.bad.policy = tryLast # before larger keysize constraints of the same algorithm. For example: # "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 # is not guaranteed to be examined and used by other implementations. # @@ -510,9 +540,10 @@ krb5.kdc.bad.policy = tryLast # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ - DSA keySize < 1024, EC keySize < 224 +jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ + RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 +# # Algorithm restrictions for signed JAR files # # In some environments, certain algorithms or key lengths may be undesirable @@ -527,17 +558,20 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint | DenyAfterConstraint # # KeySizeConstraint: # keySize Operator KeyLength # +# DenyAfterConstraint: +# denyAfter YYYY-MM-DD +# # Operator: # <= | < | == | != | >= | > # @@ -548,8 +582,11 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # implementation. It is not guaranteed to be examined and used by other # implementations. # +# See "jdk.certpath.disabledAlgorithms" for syntax descriptions. +# jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +# # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing # @@ -571,6 +608,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 # See the specification of "jdk.certpath.disabledAlgorithms" for the # 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. # It is not guaranteed to be examined and used by other implementations. # diff --git a/test/ProblemList.txt b/test/ProblemList.txt index 37b3bca0ee693a5928d47cf0e7546c30d4355d5f..2f9a8cec0bd11b40d0ea7740ad2931ff580d623e 100644 --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -240,6 +240,9 @@ sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java generic-all # 8158827 sun/security/krb5/auto/tools/KinitConfPlusProps.java windows-all +# 8160071 ClientJSSEServerJSSE.java test failure +sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java linux-all + ############################################################################ # jdk_sound diff --git a/test/sun/security/tools/jarsigner/TimestampCheck.java b/test/sun/security/tools/jarsigner/TimestampCheck.java index 029afdc883cd44e159009717b903343fb84b8a63..2d4760283722405787fe16b465965a77258a36de 100644 --- a/test/sun/security/tools/jarsigner/TimestampCheck.java +++ b/test/sun/security/tools/jarsigner/TimestampCheck.java @@ -463,7 +463,7 @@ public class TimestampCheck { .shouldMatch("Timestamp signature algorithm: .*key.*weak"); verify(file, "-J-Djava.security.debug=jar") .shouldHaveExitValue(0) - .shouldMatch("SignatureException:.*Disabled"); + .shouldMatch("SignatureException:.*disabled"); } static void checkHalfWeak(String file) throws Throwable {