Mercurial > hg > openjdk > jdk6 > jdk
changeset 1720:7cb359c0e53c
8176536: Improved algorithm constraints checking
Reviewed-by: mullan
line wrap: on
line diff
--- a/src/share/classes/sun/security/pkcs/SignerInfo.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/pkcs/SignerInfo.java Thu Mar 23 08:44:17 2017 -0700 @@ -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 @@ -36,6 +36,7 @@ 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 sun.misc.HexDumpEncoder; import sun.security.timestamp.TimestampToken; import sun.security.util.CryptoPrimitive; +import sun.security.util.ConstraintsParameters; import sun.security.util.Debug; import sun.security.util.DerEncoder; import sun.security.util.DerInputStream; @@ -209,7 +211,7 @@ /** * DER encode this object onto an output stream. - * Implements the <code>DerEncoder</code> interface. + * Implements the {@code DerEncoder} interface. * * @param out * the output stream on which to write the DER encoding. @@ -321,6 +323,8 @@ data = content.getContentBytes(); } + ConstraintsParameters cparams = + new ConstraintsParameters(timestamp); String digestAlgname = getDigestAlgorithmId().getName(); byte[] dataSigned; @@ -347,11 +351,11 @@ 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( @@ -386,17 +390,18 @@ 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)) { @@ -520,7 +525,7 @@ * Extracts a timestamp from a PKCS7 SignerInfo. * * Examines the signer's unsigned attributes for a - * <tt>signatureTimestampToken</tt> attribute. If present, + * {@code signatureTimestampToken} attribute. If present, * then it is parsed to extract the date and time at which the * timestamp was generated. *
--- a/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Thu Mar 23 08:44:17 2017 -0700 @@ -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 @@ -25,15 +25,13 @@ package sun.security.provider.certpath; -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import java.util.EnumSet; +import java.util.*; import java.math.BigInteger; import java.security.PublicKey; import java.security.KeyFactory; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; +import java.security.Timestamp; import java.security.cert.Certificate; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; @@ -42,22 +40,19 @@ import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; +import java.security.cert.CertPathValidator; import java.io.IOException; import java.security.interfaces.*; import java.security.spec.*; -import sun.security.util.AnchorCertificates; -import sun.security.util.CertConstraintParameters; -import sun.security.util.AlgorithmConstraints; -import sun.security.util.CryptoPrimitive; -import sun.security.util.Debug; -import sun.security.util.DisabledAlgorithmConstraints; +import sun.security.util.*; +import sun.security.validator.Validator; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; import sun.security.x509.AlgorithmId; /** - * A <code>PKIXCertPathChecker</code> implementation to check whether a + * A A {@code PKIXCertPathChecker} implementation to check whether a * specified certificate contains the required algorithm constraints. * <p> * Certificate fields such as the subject public key, the signature @@ -67,24 +62,27 @@ * @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<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET = + private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET = EnumSet.of(CryptoPrimitive.SIGNATURE); - private final static Set<CryptoPrimitive> KU_PRIMITIVE_SET = + private static final Set<CryptoPrimitive> 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); @@ -97,64 +95,99 @@ private boolean trustedMatch = false; /** - * Create a new <code>AlgorithmChecker</code> 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 <code>AlgorithmChecker</code> with the - * given {@code AlgorithmConstraints}. - * <p> - * 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 <code>AlgorithmChecker</code> with the - * given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>. + * 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 <code>anchor</code> 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 != 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 = null; + if (debug != null) { + debug.println("TrustAnchor is null, trustedMatch is false."); + } } - if (anchor.getTrustedCert() != null) { - this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); - // Check for anchor certificate restrictions - trustedMatch = checkFingerprint(anchor.getTrustedCert()); - if (trustedMatch && debug != null) { - debug.println("trustedMatch = true"); - } - } else { - this.trustedPubKey = anchor.getCAPublicKey(); - } + this.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); + } - this.prevPubKey = trustedPubKey; - this.constraints = constraints; + /** + * 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 @@ -215,6 +248,27 @@ "incorrect KeyUsage extension"); } + 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); + } + // Assume all key usage bits are set if key usage is not present Set<CryptoPrimitive> primitives = KU_PRIMITIVE_SET; @@ -250,100 +304,74 @@ } } - PublicKey currPubKey = cert.getPublicKey(); + ConstraintsParameters cp = + new ConstraintsParameters((X509Certificate)cert, + trustedMatch, pkixdate, jarTimestamp, variant); + // Check against local constraints if it is DisabledAlgorithmConstrain 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; + ((DisabledAlgorithmConstraints) constraints).permits(currSigAlg, cp); + // DisabledAlgorithmsConstraints does not check primitives, so key + // additional key check. + } 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 key " + + currPubKey.getAlgorithm() + " with size of " + + sun.security.util.KeyUtil.getKeySize(currPubKey) + + "bits"); } } - 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(); - 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)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed on signature " + - "algorithm: " + currSigAlg); - } - - if (!constraints.permits(primitives, currPubKey)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed on keysize: " + - sun.security.util.KeyUtil.getKeySize(currPubKey)); - - } + // 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); + "signature algorithm: " + currSigAlg); + } + + // Inherit key parameters from previous key + if (currPubKey instanceof DSAPublicKey && + ((DSAPublicKey)currPubKey).getParams() == null) { + // Inherit DSA parameters from previous key + if (!(prevPubKey instanceof DSAPublicKey)) { + throw new CertPathValidatorException("Input key is not " + + "of a appropriate type for inheriting parameters"); } - // Inherit key parameters from previous key - if (currPubKey instanceof DSAPublicKey && - ((DSAPublicKey)currPubKey).getParams() == null) { - // 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<String> extendedKeyUsages = x509Cert.getExtendedKeyUsage(); - - // DO NOT remove any unresolved critical extensions } /** @@ -383,8 +411,10 @@ * * @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; @@ -395,26 +425,23 @@ } 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"); - } + certPathDefaultConstraints.permits(new ConstraintsParameters( + sigAlgName, sigAlgParams, key, variant)); } - }
--- a/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java Thu Mar 23 08:44:17 2017 -0700 @@ -310,7 +310,7 @@ // all CRLs returned by the DP Fetcher have also been verified mApprovedCRLs.addAll(DistributionPointFetcher.getCRLs(sel, signFlag, prevKey, mSigProvider, mStores, reasonsMask, trustAnchors, - mParams.getDate())); + mParams.getDate(), null)); } catch (Exception e) { if (debug != null) { debug.println("CrlRevocationChecker.verifyRevocationStatus() " @@ -783,9 +783,13 @@ t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) { DistributionPoint point = t.next(); for (X509CRL crl : crls) { + String variant = null; + if (mParams instanceof PKIXExtendedParameters) { + variant = ((PKIXExtendedParameters)mParams).getVariant(); + } if (DistributionPointFetcher.verifyCRL(certImpl, point, crl, reasonsMask, signFlag, prevKey, mSigProvider, - trustAnchors, mStores, mParams.getDate())) { + trustAnchors, mStores, mParams.getDate(), variant)) { results.add(crl); } }
--- a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Thu Mar 23 08:44:17 2017 -0700 @@ -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 @@ -35,6 +35,7 @@ import sun.security.action.GetBooleanAction; import sun.security.util.Debug; import sun.security.util.DerOutputStream; +import sun.security.validator.Validator; import sun.security.x509.*; /** @@ -84,7 +85,8 @@ List<CertStore> certStores, boolean[] reasonsMask, Set<TrustAnchor> trustAnchors, - Date validity) + Date validity, + String variant) throws CertStoreException { if (USE_CRLDP == false) { @@ -116,7 +118,7 @@ DistributionPoint point = t.next(); Collection<X509CRL> crls = getCRLs(selector, certImpl, point, reasonsMask, signFlag, prevKey, provider, - certStores, trustAnchors, validity); + certStores, trustAnchors, validity, variant); results.addAll(crls); } if (debug != null) { @@ -138,7 +140,7 @@ X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask, boolean signFlag, PublicKey prevKey, String provider, List<CertStore> certStores, Set<TrustAnchor> trustAnchors, - Date validity) { + Date validity, String variant) { // check for full name GeneralNames fullName = point.getFullName(); @@ -191,7 +193,7 @@ selector.setIssuerNames(null); if (selector.match(crl) && verifyCRL(certImpl, point, crl, reasonsMask, signFlag, prevKey, provider, trustAnchors, - certStores, validity)) { + certStores, validity, variant)) { crls.add(crl); } } catch (Exception e) { @@ -283,7 +285,7 @@ X509CRL crl, boolean[] reasonsMask, boolean signFlag, PublicKey prevKey, String provider, Set<TrustAnchor> trustAnchors, List<CertStore> certStores, - Date validity) throws CRLException, IOException { + Date validity, String variant) throws CRLException, IOException { boolean indirectCRL = false; X509CRLImpl crlImpl = X509CRLImpl.toImpl(crl); @@ -401,7 +403,7 @@ } 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 " + @@ -616,7 +618,7 @@ // 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);
--- a/src/share/classes/sun/security/provider/certpath/OCSP.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/OCSP.java Thu Mar 23 08:44:17 2017 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 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 @@ -33,6 +33,7 @@ import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; import java.security.cert.X509Certificate; +import java.security.cert.TrustAnchor; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -41,6 +42,7 @@ import static sun.security.provider.certpath.OCSPResponse.*; import sun.security.util.Debug; +import sun.security.validator.Validator; import sun.security.x509.AccessDescription; import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.GeneralName; @@ -67,45 +69,6 @@ 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 ce) { - throw new CertPathValidatorException - ("Exception while encoding OCSPRequest", ce); - } catch (IOException ioe) { - throw new CertPathValidatorException - ("Exception while encoding OCSPRequest", ioe); - } - OCSPResponse ocspResponse = check(Collections.singletonList(certId), - responderURI, issuerCert, null); - return (RevocationStatus) ocspResponse.getSingleResponse(certId); - } - - /** * Obtains the revocation status of a certificate using OCSP. * * @param cert the certificate to be checked @@ -122,8 +85,16 @@ */ public static RevocationStatus check(X509Certificate cert, X509Certificate issuerCert, URI responderURI, X509Certificate - responderCert, Date date) + responderCert, Date date, String variant) throws IOException, CertPathValidatorException { + return check(cert, responderURI, null, issuerCert, responderCert, date, variant); + } + + public static RevocationStatus check(X509Certificate cert, URI responderURI, + TrustAnchor anchor, X509Certificate issuerCert, + X509Certificate responderCert, Date date, + String variant) + throws IOException, CertPathValidatorException { CertId certId = null; try { X509CertImpl certImpl = X509CertImpl.toImpl(cert); @@ -136,15 +107,17 @@ ("Exception while encoding OCSPRequest", ioe); } OCSPResponse ocspResponse = check(Collections.singletonList(certId), - responderURI, responderCert, date); + responderURI, new OCSPResponse.IssuerInfo(anchor, issuerCert), + responderCert, date, 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 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. @@ -155,21 +128,41 @@ * encoding the OCSP Request or validating the OCSP Response */ static OCSPResponse check(List<CertId> certIds, URI responderURI, - X509Certificate responderCert, Date date) + OCSPResponse.IssuerInfo issuerInfo, + X509Certificate responderCert, Date date, String variant) throws IOException, CertPathValidatorException { - byte[] bytes = null; + OCSPResponse ocspResponse = null; try { - OCSPRequest request = new OCSPRequest(certIds); - bytes = request.encodeBytes(); + byte[] response = getOCSPBytes(certIds, responderURI); + ocspResponse = new OCSPResponse(response, date, responderCert, 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); } + 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 + * + * @return the OCSP response bytes + * + * @throws IOException if there is an exception connecting to or + * communicating with the OCSP responder + */ + public static byte[] getOCSPBytes(List<CertId> certIds, URI responderURI) throws IOException { + OCSPRequest request = new OCSPRequest(certIds); + byte[] bytes = request.encodeBytes(); InputStream in = null; OutputStream out = null; byte[] response = null; + try { URL url = responderURI.toURL(); if (debug != null) { @@ -229,36 +222,7 @@ } } - OCSPResponse ocspResponse = null; - try { - ocspResponse = new OCSPResponse(response, date, responderCert); - } catch (IOException ioe) { - // response decoding exception - throw new CertPathValidatorException(ioe); - } - if (ocspResponse.getResponseStatus() != ResponseStatus.SUCCESSFUL) { - throw new CertPathValidatorException - ("OCSP response error: " + ocspResponse.getResponseStatus()); - } - - // Check that the response includes a response for all of the - // certs that were supplied in the request - for (CertId certId : certIds) { - SingleResponse sr = ocspResponse.getSingleResponse(certId); - if (sr == null) { - if (debug != null) { - debug.println("No response found for CertId: " + certId); - } - throw new CertPathValidatorException( - "OCSP response does not include a response for a " + - "certificate supplied in the OCSP request"); - } - if (debug != null) { - debug.println("Status of certificate (with serial number " + - certId.getSerialNumber() + ") is: " + sr.getCertStatus()); - } - } - return ocspResponse; + return response; } /**
--- a/src/share/classes/sun/security/provider/certpath/OCSPChecker.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/OCSPChecker.java Thu Mar 23 08:44:17 2017 -0700 @@ -336,8 +336,12 @@ try { certId = new CertId (issuerCert, currCertImpl.getSerialNumberObject()); - response = OCSP.check(Collections.singletonList(certId), uri, - responderCert, pkixParams.getDate()); + String variant = null; + if (pkixParams instanceof PKIXExtendedParameters) { + variant = ((PKIXExtendedParameters)pkixParams).getVariant(); + } + response = OCSP.check(Collections.singletonList(certId), uri, null, + responderCert, pkixParams.getDate(), variant); } catch (Exception e) { if (e instanceof CertPathValidatorException) { throw (CertPathValidatorException) e;
--- a/src/share/classes/sun/security/provider/certpath/OCSPRequest.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/OCSPRequest.java Thu Mar 23 08:44:17 2017 -0700 @@ -30,10 +30,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: * <pre>
--- a/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Thu Mar 23 08:44:17 2017 -0700 @@ -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 @@ -33,11 +33,15 @@ import java.security.cert.CertPathValidatorException; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.Collections; 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; import sun.security.action.GetIntegerAction; import sun.security.x509.*; @@ -124,7 +128,7 @@ 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 = false; @@ -174,12 +178,17 @@ return tmp * 1000; } + private final byte[] responseNonce; + private final ResponderId respId; + private Date producedAtDate = null; + private final Map<String, Extension> responseExtensions; + /* * Create an OCSP response from its ASN.1 DER encoding. */ // used by OCSPChecker OCSPResponse(byte[] bytes, Date dateCheckedAgainst, - X509Certificate responderCert) + X509Certificate responderCert, String variant) throws IOException, CertPathValidatorException { // OCSPResponse @@ -209,6 +218,9 @@ if (responseStatus != ResponseStatus.SUCCESSFUL) { // no need to continue, responseBytes are not set. singleResponseMap = Collections.emptyMap(); + responseNonce = null; + responseExtensions = Collections.emptyMap(); + respId = null; return; } @@ -277,23 +289,15 @@ } // responderID - short tag = (byte)(seq.tag & 0x1f); - if (tag == NAME_TAG) { - if (DEBUG != null) { - X500Name responderName = new X500Name(seq.getData()); - DEBUG.println("OCSP Responder name: " + responderName); - } - } else if (tag == KEY_TAG) { - // Ignore, for now - } 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); } @@ -305,37 +309,29 @@ 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 + Map<String, Extension> tmpExtMap = new HashMap<String, Extension>(); 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 responseExtension = - new Extension(responseExtDer[i]); - if (DEBUG != null) { - DEBUG.println("OCSP extension: " + responseExtension); - } - if (responseExtension.getExtensionId().equals( - OCSP_NONCE_EXTENSION_OID)) { - /* - ocspNonce = - responseExtension[i].getExtensionValue(); - */ - } else if (responseExtension.isCritical()) { - throw new IOException( - "Unsupported OCSP critical extension: " + - responseExtension.getExtensionId()); - } - } + tmpExtMap = parseExtensions(seq); } } + responseExtensions = tmpExtMap; + + // Attach the nonce value if found in the extension map + Extension nonceExt = 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 AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]); @@ -396,7 +392,7 @@ // Check algorithm constraints specified in security property // "jdk.certpath.disabledAlgorithms". AlgorithmChecker algChecker = new AlgorithmChecker( - new TrustAnchor(responderCert, null)); + new TrustAnchor(responderCert, null), variant); algChecker.init(false); algChecker.check(cert, Collections.<String>emptySet()); @@ -417,7 +413,7 @@ if (responderCert != null) { // Check algorithm constraints specified in security property // "jdk.certpath.disabledAlgorithms". - AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId); + AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId, variant); if (!verifyResponse(responseDataDer, responderCert, sigAlgId, signature)) { @@ -433,8 +429,10 @@ /** * Returns the OCSP ResponseStatus. + * + * @return the {@code ResponseStatus} for this OCSP response */ - ResponseStatus getResponseStatus() { + public ResponseStatus getResponseStatus() { return responseStatus; } @@ -476,15 +474,107 @@ /** * 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<CertId> getCertIds() { + return Collections.unmodifiableSet(singleResponseMap.keySet()); + } + + /** + * Get the {@code ResponderId} from this {@code OCSPResponse} + * + * @return the {@code ResponderId} from this response or {@code null} + * if no responder ID is in the body of the response (e.g. a + * response with a status other than SUCCESS. + */ + public ResponderId getResponderId() { + return respId; + } + + /** + * Provide a String representation of an OCSPResponse + * + * @return a human-readable representation of the OCSPResponse + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("OCSP Response:\n"); + sb.append("Response Status: ").append(responseStatus).append("\n"); + sb.append("Responder ID: ").append(respId).append("\n"); + sb.append("Produced at: ").append(producedAtDate).append("\n"); + int count = singleResponseMap.size(); + sb.append(count).append(count == 1 ? + " response:\n" : " responses:\n"); + for (SingleResponse sr : singleResponseMap.values()) { + sb.append(sr).append("\n"); + } + if (responseExtensions != null && responseExtensions.size() > 0) { + count = responseExtensions.size(); + sb.append(count).append(count == 1 ? + " extension:\n" : " extensions:\n"); + for (String extId : responseExtensions.keySet()) { + sb.append(responseExtensions.get(extId)).append("\n"); + } + } + + return sb.toString(); + } + + /** + * Build a String-Extension map from DER encoded data. + * @param derVal A {@code DerValue} object built from a SEQUENCE of + * extensions + * + * @return a {@code Map} using the OID in string form as the keys. If no + * extensions are found or an empty SEQUENCE is passed in, then + * an empty {@code Map} will be returned. + * + * @throws IOException if any decoding errors occur. + */ + private static Map<String, Extension> + parseExtensions(DerValue derVal) throws IOException { + DerValue[] extDer = derVal.data.getSequence(3); + Map<String, Extension> extMap = + new HashMap<String, Extension>(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.toString(), 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; @@ -530,7 +620,7 @@ } } else { revocationTime = null; - revocationReason = Reason.UNSPECIFIED; + revocationReason = null; if (tag == CERT_STATUS_GOOD) { certStatus = CertStatus.GOOD; } else if (tag == CERT_STATUS_UNKNOWN) { @@ -627,18 +717,113 @@ */ @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"); } 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(); + } + } }
--- a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Thu Mar 23 08:44:17 2017 -0700 @@ -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 @@ -314,7 +314,14 @@ int certPathLen = certList.size(); basicChecker = new BasicChecker(anchor, testDate, sigProvider, false); - AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor); + String variant = null; + if (pkixParam instanceof PKIXExtendedParameters) { + variant = ((PKIXExtendedParameters)pkixParam).getVariant(); + } + if (debug != null) { + debug.println("PKIXCertPathValidator.doValidate(): create AlgorithmChecker for variant: " + variant); + } + AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor, variant); KeyChecker keyChecker = new KeyChecker(certPathLen, pkixParam.getTargetCertConstraints()); ConstraintsChecker constraintsChecker =
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/provider/certpath/PKIXExtendedParameters.java Thu Mar 23 08:44:17 2017 -0700 @@ -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<TrustAnchor> getTrustAnchors() { + return p.getTrustAnchors(); + } + + @Override + public void setTrustAnchors(Set<TrustAnchor> trustAnchors) + throws InvalidAlgorithmParameterException { + // To avoid problems with PKIXBuilderParameter's constructors + if (p == null) { + return; + } + p.setTrustAnchors(trustAnchors); + } + + @Override + public Set<String> getInitialPolicies() { + return p.getInitialPolicies(); + } + + @Override + public void setInitialPolicies(Set<String> initialPolicies) { + p.setInitialPolicies(initialPolicies); + } + + @Override + public void setCertStores(List<CertStore> stores) { + p.setCertStores(stores); + } + + @Override + public void addCertStore(CertStore store) { + p.addCertStore(store); + } + + @Override + public List<CertStore> getCertStores() { + return p.getCertStores(); + } + + @Override + public void setRevocationEnabled(boolean val) { + p.setRevocationEnabled(val); + } + + @Override + public boolean isRevocationEnabled() { + return p.isRevocationEnabled(); + } + + @Override + public void setExplicitPolicyRequired(boolean val) { + p.setExplicitPolicyRequired(val); + } + + @Override + public boolean isExplicitPolicyRequired() { + return p.isExplicitPolicyRequired(); + } + + @Override + public void setPolicyMappingInhibited(boolean val) { + p.setPolicyMappingInhibited(val); + } + + @Override + public boolean isPolicyMappingInhibited() { + return p.isPolicyMappingInhibited(); + } + + @Override + public void setAnyPolicyInhibited(boolean val) { + p.setAnyPolicyInhibited(val); + } + + @Override + public boolean isAnyPolicyInhibited() { + return p.isAnyPolicyInhibited(); + } + + @Override + public void setPolicyQualifiersRejected(boolean qualifiersRejected) { + p.setPolicyQualifiersRejected(qualifiersRejected); + } + + @Override + public boolean getPolicyQualifiersRejected() { + return p.getPolicyQualifiersRejected(); + } + + @Override + public Date getDate() { + return p.getDate(); + } + + @Override + public void setCertPathCheckers(List<PKIXCertPathChecker> checkers) { + p.setCertPathCheckers(checkers); + } + + @Override + public List<PKIXCertPathChecker> getCertPathCheckers() { + return p.getCertPathCheckers(); + } + + @Override + public String getSigProvider() { + return p.getSigProvider(); + } + + @Override + public void setSigProvider(String sigProvider) { + p.setSigProvider(sigProvider); + } + + @Override + public CertSelector getTargetCertConstraints() { + return p.getTargetCertConstraints(); + } + + @Override + public void setTargetCertConstraints(CertSelector selector) { + // To avoid problems with PKIXBuilderParameter's constructors + if (p == null) { + return; + } + p.setTargetCertConstraints(selector); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/provider/certpath/ResponderId.java Thu Mar 23 08:44:17 2017 -0700 @@ -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. + * <p> + * The RFC 6960 defines a ResponderID structure as: + * <pre> + * ResponderID ::= CHOICE { + * byName [1] Name, + * byKey [2] KeyHash } + * + * KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key + * (excluding the tag and length fields) + * + * Name is defined in RFC 5280. + * </pre> + * + * @see ResponderId.Type + * @since 9 + */ +public final class ResponderId { + + /** + * A {@code ResponderId} enumeration describing the accepted forms for a + * {@code ResponderId}. + * + * @see ResponderId + * @since 9 + */ + public static enum Type { + /** + * A BY_NAME {@code ResponderId} will be built from a subject name, + * either as an {@code X500Principal} or a DER-encoded byte array. + */ + BY_NAME(1, "byName"), + + /** + * A BY_KEY {@code ResponderId} will be built from a public key + * identifier, either derived from a {@code PublicKey} or directly + * from a DER-encoded byte array containing the key identifier. + */ + BY_KEY(2, "byKey"); + + private final int tagNumber; + private final String ridTypeName; + + private Type(int value, String name) { + this.tagNumber = value; + this.ridTypeName = name; + } + + public int value() { + return tagNumber; + } + + @Override + public String toString() { + return ridTypeName; + } + } + + private Type type; + private X500Principal responderName; + private KeyIdentifier responderKeyId; + private byte[] encodedRid; + + /** + * Constructs a {@code ResponderId} object using an {@code X500Principal}. + * When encoded in DER this object will use the BY_NAME option. + * + * @param subjectName the subject name of the certificate used + * to sign OCSP responses. + * + * @throws IOException if the internal DER-encoding of the + * {@code X500Principal} fails. + */ + public ResponderId(X500Principal subjectName) throws IOException { + responderName = subjectName; + responderKeyId = null; + encodedRid = principalToBytes(); + type = Type.BY_NAME; + } + + /** + * Constructs a {@code ResponderId} object using a {@code PublicKey}. + * When encoded in DER this object will use the byKey option, a + * SHA-1 hash of the responder's public key. + * + * @param pubKey the the OCSP responder's public key + * + * @throws IOException if the internal DER-encoding of the + * {@code KeyIdentifier} fails. + */ + public ResponderId(PublicKey pubKey) throws IOException { + responderKeyId = new KeyIdentifier(pubKey); + responderName = null; + encodedRid = keyIdToBytes(); + type = Type.BY_KEY; + } + + /** + * Constructs a {@code ResponderId} object from its DER-encoding. + * + * @param encodedData the DER-encoded bytes + * + * @throws IOException if the encodedData is not properly DER encoded + */ + public ResponderId(byte[] encodedData) throws IOException { + DerValue outer = new DerValue(encodedData); + + if (outer.isContextSpecific((byte)Type.BY_NAME.value()) + && outer.isConstructed()) { + // Use the X500Principal constructor as a way to sanity + // check the incoming data. + responderName = new X500Principal(outer.getDataBytes()); + encodedRid = principalToBytes(); + type = Type.BY_NAME; + } else if (outer.isContextSpecific((byte)Type.BY_KEY.value()) + && outer.isConstructed()) { + // Use the KeyIdentifier constructor as a way to sanity + // check the incoming data. + responderKeyId = + new KeyIdentifier(new DerValue(outer.getDataBytes())); + encodedRid = keyIdToBytes(); + type = Type.BY_KEY; + } else { + throw new IOException("Invalid ResponderId content"); + } + } + + /** + * Encode a {@code ResponderId} in DER form + * + * @return a byte array containing the DER-encoded representation for this + * {@code ResponderId} + */ + public byte[] getEncoded() { + return encodedRid.clone(); + } + + /** + * Return the type of {@ResponderId} + * + * @return a number corresponding to the context-specific tag number + * used in the DER-encoding for a {@code ResponderId} + */ + public ResponderId.Type getType() { + return type; + } + + /** + * Get the length of the encoded {@code ResponderId} (including the tag and + * length of the explicit tagging from the outer ASN.1 CHOICE). + * + * @return the length of the encoded {@code ResponderId} + */ + public int length() { + return encodedRid.length; + } + + /** + * Obtain the underlying {@code X500Principal} from a {@code ResponderId} + * + * @return the {@code X500Principal} for this {@code ResponderId} if it + * is a BY_NAME variant. If the {@code ResponderId} is a BY_KEY + * variant, this routine will return {@code null}. + */ + public X500Principal getResponderName() { + return responderName; + } + + /** + * Obtain the underlying key identifier from a {@code ResponderId} + * + * @return the {@code KeyIdentifier} for this {@code ResponderId} if it + * is a BY_KEY variant. If the {@code ResponderId} is a BY_NAME + * variant, this routine will return {@code null}. + */ + public KeyIdentifier getKeyIdentifier() { + return responderKeyId; + } + + /** + * Compares the specified object with this {@code ResponderId} for equality. + * A ResponderId will only be considered equivalent if both the type and + * data value are equal. Two ResponderIds initialized by name and + * key ID, respectively, will not be equal even if the + * ResponderId objects are created from the same source certificate. + * + * @param obj the object to be compared against + * + * @return true if the specified object is equal to this {@code Responderid} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (this == obj) { + return true; + } + + if (obj instanceof ResponderId) { + ResponderId respObj = (ResponderId)obj; + return Arrays.equals(encodedRid, respObj.getEncoded()); + } + + return false; + } + + /** + * Returns the hash code value for this {@code ResponderId} + * + * @return the hash code value for this {@code ResponderId} + */ + @Override + public int hashCode() { + return Arrays.hashCode(encodedRid); + } + + /** + * Create a String representation of this {@code ResponderId} + * + * @return a String representation of this {@code ResponderId} + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + switch (type) { + case BY_NAME: + sb.append(type).append(": ").append(responderName); + break; + case BY_KEY: + sb.append(type).append(": "); + for (byte keyIdByte : responderKeyId.getIdentifier()) { + sb.append(String.format("%02X", keyIdByte)); + } + break; + default: + sb.append("Unknown ResponderId Type: ").append(type); + } + return sb.toString(); + } + + /** + * Convert the responderName data member into its DER-encoded form + * + * @return the DER encoding for a responder ID byName option, including + * explicit context-specific tagging. + * + * @throws IOException if any encoding error occurs + */ + private byte[] principalToBytes() throws IOException { + DerValue dv = new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, + true, (byte)Type.BY_NAME.value()), + responderName.getEncoded()); + return dv.toByteArray(); + } + + /** + * Convert the responderKeyId data member into its DER-encoded form + * + * @return the DER encoding for a responder ID byKey option, including + * explicit context-specific tagging. + * + * @throws IOException if any encoding error occurs + */ + private byte[] keyIdToBytes() throws IOException { + // Place the KeyIdentifier bytes into an OCTET STRING + DerValue inner = new DerValue(DerValue.tag_OctetString, + responderKeyId.getIdentifier()); + + // Mark the OCTET STRING-wrapped KeyIdentifier bytes + // as EXPLICIT CONTEXT 2 + DerValue outer = new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, + true, (byte)Type.BY_KEY.value()), inner.toByteArray()); + + return outer.toByteArray(); + } + +}
--- a/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java Thu Mar 23 08:44:17 2017 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, 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 @@ -58,7 +58,7 @@ * <p> If successful, it returns a certification path which has succesfully * 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. * * <p> This implementation uses a depth-first search approach to finding * certification paths. If it comes to a point in which it cannot find @@ -304,7 +304,7 @@ // init the crl checker currentState.crlChecker = new CrlRevocationChecker(null, buildParams, null, onlyEECert); - currentState.algorithmChecker = new AlgorithmChecker(anchor); + currentState.algorithmChecker = new AlgorithmChecker(anchor, null); currentState.untrustedChecker = new UntrustedChecker(); try { depthFirstSearchReverse(null, currentState, @@ -484,7 +484,7 @@ // add the algorithm checker userCheckers.add(mustCheck, - new AlgorithmChecker(builder.trustAnchor)); + new AlgorithmChecker(builder.trustAnchor, buildParams.getDate(), null)); mustCheck++; if (nextState.keyParamsNeeded()) {
--- a/src/share/classes/sun/security/ssl/SSLContextImpl.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/ssl/SSLContextImpl.java Thu Mar 23 08:44:17 2017 -0700 @@ -43,6 +43,7 @@ import sun.security.util.AlgorithmConstraints; import sun.security.util.CryptoPrimitive; +import sun.security.validator.Validator; public abstract class SSLContextImpl extends SSLContextSpi {
--- a/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java Thu Mar 23 08:44:17 2017 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2007, 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 @@ -38,6 +38,8 @@ import javax.net.ssl.*; +import sun.security.validator.Validator; + /** * The new X509 key manager implementation. The main differences to the * old SunX509 key manager are: @@ -60,7 +62,7 @@ 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 @@ -497,6 +499,15 @@ return CheckResult.EXPIRED; } } + + 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
--- a/src/share/classes/sun/security/util/AnchorCertificates.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/util/AnchorCertificates.java Thu Mar 23 08:44:17 2017 -0700 @@ -31,8 +31,10 @@ 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 @@ private static final Debug debug = Debug.getInstance("certpath"); private static final String HASH = "SHA-256"; - private static HashSet<String> certs; + private static Set<String> certs = Collections.emptySet(); static { AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/share/classes/sun/security/util/CertConstraintParameters.java Tue Aug 15 11:46:02 2017 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/util/ConstraintsParameters.java Thu Mar 23 08:44:17 2017 -0700 @@ -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; + } +}
--- a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Thu Mar 23 08:44:17 2017 -0700 @@ -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,15 +25,16 @@ package sun.security.util; +import sun.security.validator.Validator; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.security.AlgorithmParameters; import java.security.Key; import java.security.cert.CertPathValidatorException; import java.security.cert.X509Certificate; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.text.SimpleDateFormat; +import java.util.*; import java.util.regex.Pattern; import java.util.regex.Matcher; @@ -47,11 +48,11 @@ 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 @@ -90,14 +91,9 @@ * This only checks if the algorithm has been completely disabled. If * there are keysize or other limit, this method allow the algorithm. */ - final public boolean permits(Set<CryptoPrimitive> primitives, + @Override + public final boolean permits(Set<CryptoPrimitive> primitives, String algorithm, AlgorithmParameters parameters) { - - if (primitives == null || primitives.isEmpty()) { - throw new IllegalArgumentException( - "No cryptographic primitive specified"); - } - return checkAlgorithm(disabledAlgorithms, algorithm, decomposer); } @@ -105,7 +101,8 @@ * Checks if the key algorithm has been disabled or constraints have been * placed on the key. */ - final public boolean permits(Set<CryptoPrimitive> primitives, Key key) { + @Override + public final boolean permits(Set<CryptoPrimitive> primitives, Key key) { return checkConstraints(primitives, "", key, null); } @@ -113,7 +110,8 @@ * Checks if the key algorithm has been disabled or if constraints have * been placed on the key. */ - final public boolean permits(Set<CryptoPrimitive> primitives, + @Override + public final boolean permits(Set<CryptoPrimitive> primitives, String algorithm, Key key, AlgorithmParameters parameters) { if (algorithm == null || algorithm.length() == 0) { @@ -123,6 +121,18 @@ 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 @@ -130,18 +140,10 @@ * * Uses new style permit() which throws exceptions. */ - public final void permits(Set<CryptoPrimitive> 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<CryptoPrimitive> 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 @@ -164,7 +166,7 @@ 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; @@ -180,35 +182,6 @@ return algorithmConstraints.permits(key); } - /* - * Check algorithm constraints with Certificate - * Uses new style permit() which throws exceptions. - */ - private void checkConstraints(Set<CryptoPrimitive> primitives, - CertConstraintParameters cp) throws CertPathValidatorException { - - X509Certificate cert = cp.getCertificate(); - String algorithm = cert.getSigAlgName(); - - // Check signature algorithm is not disabled - if (!permits(primitives, algorithm, null)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed on disabled "+ - "signature algorithm: " + algorithm); - } - - // 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); - } - - // Check the certificate and key constraints - algorithmConstraints.permits(cp); - - } - /** * Key and Certificate Constraints * @@ -222,15 +195,18 @@ * '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<String, Set<Constraint>> constraintsMap = new HashMap<String, Set<Constraint>>(); - private static final Pattern keySizePattern = Pattern.compile( - "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); + private Map<String, List<Constraint>> constraintsMap = new HashMap<String, List<Constraint>>(); + + 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) { @@ -245,41 +221,49 @@ // 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 { - final String key = constraintEntry.toUpperCase(Locale.ENGLISH); - if (constraintsMap.get(key) == null) { - constraintsMap.put(key, new HashSet<Constraint>()); - } + String algorithm = AlgorithmDecomposer.hashName( + ((space > 0 ? constraintEntry.substring(0, space) : + constraintEntry). + toUpperCase(Locale.ENGLISH))); + + List<Constraint> constraintList = constraintsMap.get(algorithm); + if (constraintList == null) { + constraintList = new ArrayList<Constraint>(1); + constraintsMap.put(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) { debug.println("Constraints set to jdkCA."); @@ -291,18 +275,39 @@ } 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.put(algorithm, - new HashSet<Constraint>()); - } - if (c != null) { - constraintsMap.get(algorithm).add(c); - } + constraintList.add(c); } else { lastConstraint.nextConstraint = c; } @@ -312,61 +317,73 @@ } // Get applicable constraints based off the signature algorithm - private Set<Constraint> getConstraints(String algorithm) { + private List<Constraint> getConstraints(String algorithm) { return constraintsMap.get(algorithm); } // Check if KeySizeConstraints permit the specified key public boolean permits(Key key) { - Set<Constraint> set = getConstraints(key.getAlgorithm()); - if (set == null) { + List<Constraint> 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<String> algorithms = - AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName()); - if (algorithms == null || algorithms.isEmpty()) { - return; - } + Set<String> algorithms = new HashSet<String>(); + if (algorithm != null) { + algorithms.addAll(AlgorithmDecomposer.decomposeOneHash(algorithm)); + } - // Attempt to add the public key algorithm to the set - algorithms.add(cert.getPublicKey().getAlgorithm()); - + // Attempt to add the public key algorithm if cert provided + if (cert != null) { + algorithms.add(cert.getPublicKey().getAlgorithm()); + } + if (cp.getPublicKey() != null) { + algorithms.add(cp.getPublicKey().getAlgorithm()); + } // Check all applicable constraints - for (String algorithm : algorithms) { - Set<Constraint> set = getConstraints(algorithm); - if (set == null) { + for (String alg : algorithms) { + List<Constraint> 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; @@ -400,22 +417,87 @@ } /** - * 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(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. */ - public abstract void permits(CertConstraintParameters cp) - throws CertPathValidatorException; + 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() : ".")); + } } /* @@ -428,29 +510,172 @@ } /* - * 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)); } } } + /* + * 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 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + c.set(year, month - 1, day); + + 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)); + } + } + + /* + * 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)); + } + } + } + } /* * This class contains constraints dealing with the key size @@ -461,6 +686,7 @@ 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; @@ -504,15 +730,22 @@ * 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)); } } @@ -537,7 +770,7 @@ 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) { @@ -551,5 +784,25 @@ } + /* + * 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)); + } + + public boolean permits(Key key) { + return false; + } + } + }
--- a/src/share/classes/sun/security/util/SignatureFileVerifier.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/util/SignatureFileVerifier.java Thu Mar 23 08:44:17 2017 -0700 @@ -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 @@ -31,11 +31,8 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; -import java.security.cert.CertPath; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.io.ByteArrayOutputStream; +import java.security.Timestamp; +import java.security.cert.*; import java.util.ArrayList; import java.util.Collections; @@ -65,9 +62,6 @@ /* Are we debugging ? */ private static final Debug debug = Debug.getInstance("jar"); - private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = - Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST)); - private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK = new DisabledAlgorithmConstraints( DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS); @@ -82,7 +76,7 @@ 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) @@ -101,6 +95,14 @@ /* for generating certpath objects */ private CertificateFactory certificateFactory = null; + /** Algorithms that have been checked if they are weak. */ + private Map<String, Boolean> permittedAlgs= new HashMap<String, Boolean>(); + + /** 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. * @@ -111,7 +113,7 @@ public SignatureFileVerifier(ArrayList<CodeSigner[]> signerCache, ManifestDigester md, String name, - byte rawBytes[]) + byte[] rawBytes) throws IOException, CertificateException { // new PKCS7() calls CertificateFactory.getInstance() @@ -125,7 +127,7 @@ } 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; @@ -156,7 +158,7 @@ * 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; } @@ -172,11 +174,10 @@ */ 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"); } /** @@ -186,7 +187,7 @@ * 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) { @@ -227,15 +228,8 @@ /** 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<String, MessageDigest>(); @@ -308,6 +302,27 @@ 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<Map.Entry<String,Attributes>> entries = sf.getEntries().entrySet().iterator(); @@ -348,6 +363,68 @@ } /** + * 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(CertPathValidatorException 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. */ private boolean verifyManifestHash(Manifest sf, @@ -358,6 +435,10 @@ { 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<Object,Object> se : mattr.entrySet()) { @@ -367,6 +448,16 @@ 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()); @@ -377,15 +468,14 @@ decoder.decodeBuffer((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 @@ -393,6 +483,21 @@ } } } + + 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; } @@ -403,6 +508,10 @@ { 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 @@ -412,6 +521,16 @@ 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) { @@ -430,8 +549,7 @@ debug.println(); } - if (MessageDigest.isEqual(computedHash, - expectedHash)) { + if (MessageDigest.isEqual(computedHash, expectedHash)) { // good } else { // we will *not* continue and verify each section @@ -447,6 +565,22 @@ } } + 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 @@ -470,6 +604,10 @@ { 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( @@ -477,8 +615,7 @@ } 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 @@ -488,6 +625,16 @@ 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); @@ -538,6 +685,22 @@ } } } + + 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; } @@ -546,7 +709,7 @@ * 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 { @@ -587,7 +750,7 @@ static String toHex(byte[] data) { - StringBuffer sb = new StringBuffer(data.length*2); + StringBuilder sb = new StringBuilder(data.length*2); for (int i=0; i<data.length; i++) { sb.append(hexc[(data[i] >>4) & 0x0f]);
--- a/src/share/classes/sun/security/validator/PKIXValidator.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/validator/PKIXValidator.java Thu Mar 23 08:44:17 2017 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, 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,10 +34,11 @@ import sun.security.action.GetBooleanAction; import sun.security.provider.certpath.AlgorithmChecker; import sun.security.util.AlgorithmConstraints; +import sun.security.provider.certpath.PKIXExtendedParameters; /** * Validator implementation built on the PKIX CertPath API. This - * implementation will be emphasized going forward.<p> + * implementation will be emphasized going forward. * <p> * Note that the validate() implementation tries to use a PKIX validator * if that appears possible and a PKIX builder otherwise. This increases @@ -209,13 +210,22 @@ ("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) {
--- a/src/share/classes/sun/security/validator/SimpleValidator.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/validator/SimpleValidator.java Thu Mar 23 08:44:17 2017 -0700 @@ -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 javax.security.auth.x500.X500Principal; import sun.security.x509.X509CertImpl; +import sun.security.x509.KeyIdentifier; import sun.security.x509.NetscapeCertTypeExtension; import sun.security.util.AlgorithmConstraints; import sun.security.util.DerValue; @@ -153,12 +154,14 @@ // 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
--- a/src/share/classes/sun/security/x509/PKIXExtensions.java Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/classes/sun/security/x509/PKIXExtensions.java Thu Mar 23 08:44:17 2017 -0700 @@ -49,32 +49,37 @@ */ 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[] 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. */ @@ -102,18 +107,20 @@ 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; @@ -216,6 +223,18 @@ */ public static final ObjectIdentifier FreshestCRL_Id; + /** + * Identifies the OCSP client can trust the responder for the + * lifetime of the responder's certificate. + */ + 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); @@ -257,5 +276,7 @@ SubjectInfoAccess_Id = ObjectIdentifier.newInternal(SubjectInfoAccess_data); FreshestCRL_Id = ObjectIdentifier.newInternal(FreshestCRL_data); + OCSPNoCheck_Id = ObjectIdentifier.newInternal(OCSPNoCheck_data); + OCSPNonce_Id = ObjectIdentifier.newInternal(OCSPNonce_data); } }
--- a/src/share/lib/security/java.security-linux Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/lib/security/java.security-linux Thu Mar 23 08:44:17 2017 -0700 @@ -368,9 +368,7 @@ # 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 } " # @@ -381,25 +379,26 @@ # (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 @@ -413,27 +412,55 @@ # 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. +# 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" # -# "CertConstraint" specifies additional constraints for -# certificates that contain algorithms that are restricted: +# 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" # -# "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" +# 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 @@ -446,6 +473,9 @@ # 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. # @@ -453,9 +483,10 @@ # 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 @@ -470,17 +501,20 @@ # " 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: # <= | < | == | != | >= | > # @@ -491,8 +525,11 @@ # 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 # @@ -514,6 +551,9 @@ # 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. #
--- a/src/share/lib/security/java.security-solaris Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/lib/security/java.security-solaris Thu Mar 23 08:44:17 2017 -0700 @@ -328,9 +328,7 @@ # 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 } " # @@ -341,25 +339,26 @@ # (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 @@ -373,27 +372,55 @@ # 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. +# 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" # -# "CertConstraint" specifies additional constraints for -# certificates that contain algorithms that are restricted: +# 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" # -# "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" +# 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 @@ -406,6 +433,9 @@ # 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. # @@ -413,9 +443,10 @@ # 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 @@ -430,17 +461,20 @@ # " 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: # <= | < | == | != | >= | > # @@ -451,8 +485,11 @@ # 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 # @@ -474,6 +511,9 @@ # 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. #
--- a/src/share/lib/security/java.security-windows Tue Aug 15 11:46:02 2017 -0700 +++ b/src/share/lib/security/java.security-windows Thu Mar 23 08:44:17 2017 -0700 @@ -345,9 +345,7 @@ # 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 } " # @@ -358,25 +356,26 @@ # (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 @@ -390,27 +389,55 @@ # 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. +# 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" # -# "CertConstraint" specifies additional constraints for -# certificates that contain algorithms that are restricted: +# 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" # -# "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" +# 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 @@ -423,6 +450,9 @@ # 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. # @@ -430,9 +460,10 @@ # 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 @@ -447,17 +478,20 @@ # " 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: # <= | < | == | != | >= | > # @@ -468,8 +502,11 @@ # 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 # @@ -491,6 +528,9 @@ # 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. #
--- a/test/ProblemList.txt Tue Aug 15 11:46:02 2017 -0700 +++ b/test/ProblemList.txt Thu Mar 23 08:44:17 2017 -0700 @@ -595,6 +595,9 @@ # Only print test left, excluding just because all print tests have been javax/print/attribute/MediaMappingsTest.java generic-all +# 8160071 ClientJSSEServerJSSE.java test failure +sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java linux-all + ############################################################################ # jdk_net