From 26f45543e5b56f0c7aa2085b3ef6636e91aed73c Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Tue, 5 Jul 2016 15:37:42 -0700 Subject: [PATCH] 8154015: Apply algorithm constraints to timestamped code Reviewed-by: mullan --- .../provider/certpath/AlgorithmChecker.java | 37 ++- .../sun/security/provider/certpath/PKIX.java | 12 +- .../certpath/PKIXCertPathValidator.java | 18 +- .../certpath/PKIXTimestampParameters.java | 218 ++++++++++++++++++ .../util/CertConstraintParameters.java | 12 +- .../util/DisabledAlgorithmConstraints.java | 4 +- .../sun/security/validator/PKIXValidator.java | 23 +- .../sun/security/validator/Validator.java | 21 +- 8 files changed, 313 insertions(+), 32 deletions(-) create mode 100644 jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java index 4562f4d0250..d8f64cb7897 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java @@ -27,6 +27,7 @@ package sun.security.provider.certpath; import java.security.AlgorithmConstraints; import java.security.CryptoPrimitive; +import java.security.Timestamp; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -77,6 +78,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { private final PublicKey trustedPubKey; private final Date pkixdate; private PublicKey prevPubKey; + private final Timestamp jarTimestamp; private static final Set SIGNATURE_PRIMITIVE_SET = Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); @@ -142,6 +144,29 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { this.trustedPubKey = null; this.constraints = constraints; this.pkixdate = null; + this.jarTimestamp = null; + } + + /** + * Create a new {@code AlgorithmChecker} with the given + * {@code Timestamp}. + *

+ * Note that this constructor will be used to check a certification + * path for signed JAR files that are timestamped. + * + * @param jarTimestamp Timestamp passed for JAR timestamp constraint + * checking. Set to null if not applicable. + */ + public AlgorithmChecker(Timestamp jarTimestamp) { + this.prevPubKey = null; + this.trustedPubKey = null; + this.constraints = certPathDefaultConstraints; + if (jarTimestamp == null) { + throw new IllegalArgumentException( + "Timestamp cannot be null"); + } + this.pkixdate = jarTimestamp.getTimestamp(); + this.jarTimestamp = jarTimestamp; } /** @@ -162,7 +187,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { if (anchor == null) { throw new IllegalArgumentException( - "The trust anchor cannot be null"); + "The trust anchor cannot be null"); } if (anchor.getTrustedCert() != null) { @@ -179,6 +204,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { this.prevPubKey = trustedPubKey; this.constraints = constraints; this.pkixdate = pkixdate; + this.jarTimestamp = null; } /** @@ -209,6 +235,10 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { return AnchorCertificates.contains(cert); } + Timestamp getJarTimestamp() { + return jarTimestamp; + } + @Override public void init(boolean forward) throws CertPathValidatorException { // Note that this class does not support forward mode. @@ -296,8 +326,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { // permits() will throw exception on failure. certPathDefaultConstraints.permits(primitives, new CertConstraintParameters((X509Certificate)cert, - trustedMatch, pkixdate)); - // new CertConstraintParameters(x509Cert, trustedMatch)); + trustedMatch, pkixdate, jarTimestamp)); // If there is no previous key, set one and exit if (prevPubKey == null) { prevPubKey = currPubKey; @@ -442,7 +471,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { * 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 */ static void check(PublicKey key, AlgorithmId algorithmId) throws CertPathValidatorException { diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java index e33d4a21a5c..f6b0b2ed6f3 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -26,6 +26,7 @@ package sun.security.provider.certpath; import java.security.InvalidAlgorithmParameterException; import java.security.PublicKey; +import java.security.Timestamp; import java.security.cert.*; import java.security.interfaces.DSAPublicKey; import java.util.*; @@ -85,6 +86,7 @@ class PKIX { private CertSelector constraints; private Set anchors; private List certs; + private Timestamp timestamp; ValidatorParams(CertPath cp, PKIXParameters params) throws InvalidAlgorithmParameterException @@ -100,6 +102,10 @@ class PKIX { ValidatorParams(PKIXParameters params) throws InvalidAlgorithmParameterException { + if (params instanceof PKIXTimestampParameters) { + timestamp = ((PKIXTimestampParameters) params).getTimestamp(); + } + this.anchors = params.getTrustAnchors(); // Make sure that none of the trust anchors include name constraints // (not supported). @@ -189,6 +195,10 @@ class PKIX { PKIXParameters getPKIXParameters() { return params; } + + Timestamp timestamp() { + return timestamp; + } } static class BuilderParams extends ValidatorParams { diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java index 934fc10b560..ac12fab75ab 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -172,7 +172,11 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi { List certPathCheckers = new ArrayList<>(); // add standard checkers that we will be using certPathCheckers.add(untrustedChecker); - certPathCheckers.add(new AlgorithmChecker(anchor, params.date())); + if (params.timestamp() == null) { + certPathCheckers.add(new AlgorithmChecker(anchor, params.date())); + } else { + certPathCheckers.add(new AlgorithmChecker(params.timestamp())); + } certPathCheckers.add(new KeyChecker(certPathLen, params.targetCertConstraints())); certPathCheckers.add(new ConstraintsChecker(certPathLen)); @@ -189,8 +193,14 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi { rootNode); certPathCheckers.add(pc); // default value for date is current time - BasicChecker bc = new BasicChecker(anchor, params.date(), - params.sigProvider(), false); + BasicChecker bc; + if (params.timestamp() == null) { + bc = new BasicChecker(anchor, params.date(), params.sigProvider(), + false); + } else { + bc = new BasicChecker(anchor, params.timestamp().getTimestamp(), + params.sigProvider(), false); + } certPathCheckers.add(bc); boolean revCheckerAdded = false; diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java new file mode 100644 index 00000000000..34b497188e0 --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java @@ -0,0 +1,218 @@ +/* + * 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.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 + * can be passed alone when PKIXCertPath is checking signed jar files. + */ + +public class PKIXTimestampParameters extends PKIXBuilderParameters { + + private final PKIXBuilderParameters p; + private Timestamp jarTimestamp; + + public PKIXTimestampParameters(PKIXBuilderParameters params, + Timestamp timestamp) throws InvalidAlgorithmParameterException { + super(params.getTrustAnchors(), null); + p = params; + jarTimestamp = timestamp; + } + + public Timestamp getTimestamp() { + return jarTimestamp; + } + public void setTimestamp(Timestamp t) { + jarTimestamp = t; + } + + @Override + public void setDate(Date d) { + p.setDate(d); + } + + @Override + public void addCertPathChecker(PKIXCertPathChecker c) { + p.addCertPathChecker(c); + } + + @Override + public void setMaxPathLength(int maxPathLength) { + p.setMaxPathLength(maxPathLength); + } + + @Override + public int getMaxPathLength() { + return p.getMaxPathLength(); + } + + @Override + public String toString() { + return p.toString(); + } + + @Override + public Set getTrustAnchors() { + return p.getTrustAnchors(); + } + + @Override + public void setTrustAnchors(Set trustAnchors) + throws InvalidAlgorithmParameterException { + // To avoid problems with PKIXBuilderParameter's constructors + if (p == null) { + return; + } + p.setTrustAnchors(trustAnchors); + } + + @Override + public Set getInitialPolicies() { + return p.getInitialPolicies(); + } + + @Override + public void setInitialPolicies(Set initialPolicies) { + p.setInitialPolicies(initialPolicies); + } + + @Override + public void setCertStores(List stores) { + p.setCertStores(stores); + } + + @Override + public void addCertStore(CertStore store) { + p.addCertStore(store); + } + + @Override + public List getCertStores() { + return p.getCertStores(); + } + + @Override + public void setRevocationEnabled(boolean val) { + p.setRevocationEnabled(val); + } + + @Override + public boolean isRevocationEnabled() { + return p.isRevocationEnabled(); + } + + @Override + public void setExplicitPolicyRequired(boolean val) { + p.setExplicitPolicyRequired(val); + } + + @Override + public boolean isExplicitPolicyRequired() { + return p.isExplicitPolicyRequired(); + } + + @Override + public void setPolicyMappingInhibited(boolean val) { + p.setPolicyMappingInhibited(val); + } + + @Override + public boolean isPolicyMappingInhibited() { + return p.isPolicyMappingInhibited(); + } + + @Override + public void setAnyPolicyInhibited(boolean val) { + p.setAnyPolicyInhibited(val); + } + + @Override + public boolean isAnyPolicyInhibited() { + return p.isAnyPolicyInhibited(); + } + + @Override + public void setPolicyQualifiersRejected(boolean qualifiersRejected) { + p.setPolicyQualifiersRejected(qualifiersRejected); + } + + @Override + public boolean getPolicyQualifiersRejected() { + return p.getPolicyQualifiersRejected(); + } + + @Override + public Date getDate() { + return p.getDate(); + } + + @Override + public void setCertPathCheckers(List checkers) { + p.setCertPathCheckers(checkers); + } + + @Override + public List getCertPathCheckers() { + return p.getCertPathCheckers(); + } + + @Override + public String getSigProvider() { + return p.getSigProvider(); + } + + @Override + public void setSigProvider(String sigProvider) { + p.setSigProvider(sigProvider); + } + + @Override + public CertSelector getTargetCertConstraints() { + return p.getTargetCertConstraints(); + } + + @Override + public void setTargetCertConstraints(CertSelector selector) { + // To avoid problems with PKIXBuilderParameter's constructors + if (p == null) { + return; + } + p.setTargetCertConstraints(selector); + } + +} diff --git a/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java b/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java index 00a94c53950..23880f7c6aa 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java +++ b/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java @@ -25,6 +25,7 @@ package sun.security.util; +import java.security.Timestamp; import java.security.cert.X509Certificate; import java.util.Date; @@ -40,16 +41,19 @@ public class CertConstraintParameters { private final boolean trustedMatch; // PKIXParameter date private final Date pkixDate; + // Timestamp of the signed JAR file + private final Timestamp jarTimestamp; public CertConstraintParameters(X509Certificate c, boolean match, - Date pkixdate) { + Date pkixdate, Timestamp jarTime) { cert = c; trustedMatch = match; pkixDate = pkixdate; + jarTimestamp = jarTime; } public CertConstraintParameters(X509Certificate c) { - this(c, false, null); + this(c, false, null, null); } // Returns if the trust anchor has a match if anchor checking is enabled. @@ -65,4 +69,8 @@ public class CertConstraintParameters { return pkixDate; } + public Timestamp getJARTimestamp() { + return jarTimestamp; + } + } diff --git a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index f0b89564094..6f8d6d4757f 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -594,7 +594,9 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { throws CertPathValidatorException { Date currentDate; - if (cp.getPKIXParamDate() != null) { + if (cp.getJARTimestamp() != null) { + currentDate = cp.getJARTimestamp().getTimestamp(); + } else if (cp.getPKIXParamDate() != null) { currentDate = cp.getPKIXParamDate(); } else { currentDate = new Date(); diff --git a/jdk/src/java.base/share/classes/sun/security/validator/PKIXValidator.java b/jdk/src/java.base/share/classes/sun/security/validator/PKIXValidator.java index 2846b2234d0..8d63ea2b8f5 100644 --- a/jdk/src/java.base/share/classes/sun/security/validator/PKIXValidator.java +++ b/jdk/src/java.base/share/classes/sun/security/validator/PKIXValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -33,6 +33,7 @@ import java.security.cert.*; import javax.security.auth.x500.X500Principal; import sun.security.action.GetBooleanAction; import sun.security.provider.certpath.AlgorithmChecker; +import sun.security.provider.certpath.PKIXTimestampParameters; /** * Validator implementation built on the PKIX CertPath API. This @@ -194,13 +195,23 @@ public final class PKIXValidator extends Validator { ("null or zero-length certificate chain"); } + // Check if 'parameter' affects 'pkixParameters' + PKIXBuilderParameters pkixParameters = null; + if (parameter instanceof Timestamp && plugin) { + try { + pkixParameters = new PKIXTimestampParameters( + (PKIXBuilderParameters) parameterTemplate.clone(), + (Timestamp) parameter); + } catch (InvalidAlgorithmParameterException e) { + // ignore exception + } + } else { + pkixParameters = (PKIXBuilderParameters) parameterTemplate.clone(); + } + // add new algorithm constraints checker - PKIXBuilderParameters pkixParameters = - (PKIXBuilderParameters) parameterTemplate.clone(); - AlgorithmChecker algorithmChecker = null; if (constraints != null) { - algorithmChecker = new AlgorithmChecker(constraints); - pkixParameters.addCertPathChecker(algorithmChecker); + pkixParameters.addCertPathChecker(new AlgorithmChecker(constraints)); } // attach it to the PKIXBuilderParameters. diff --git a/jdk/src/java.base/share/classes/sun/security/validator/Validator.java b/jdk/src/java.base/share/classes/sun/security/validator/Validator.java index c6b43aba837..c57c9711bea 100644 --- a/jdk/src/java.base/share/classes/sun/security/validator/Validator.java +++ b/jdk/src/java.base/share/classes/sun/security/validator/Validator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -221,13 +221,6 @@ public abstract class Validator { * Validate the given certificate chain. If otherCerts is non-null, it is * a Collection of additional X509Certificates that could be helpful for * path building. - *

- * Parameter is an additional parameter with variant specific meaning. - * Currently, it is only defined for TLS_SERVER variant validators, where - * it must be non null and the name of the TLS key exchange algorithm being - * used (see JSSE X509TrustManager specification). In the future, it - * could be used to pass in a PKCS#7 object for code signing to check time - * stamps. * * @return a non-empty chain that was used to validate the path. The * end entity cert is at index 0, the trust anchor at index n-1. @@ -254,12 +247,12 @@ public abstract class Validator { * represented with a zero-length byte array. * @param constraints algorithm constraints for certification path * processing - * @param parameter an additional parameter with variant specific meaning. - * Currently, it is only defined for TLS_SERVER variant validators, - * where it must be non null and the name of the TLS key exchange - * algorithm being used (see JSSE X509TrustManager specification). - * In the future, it could be used to pass in a PKCS#7 object for - * code signing to check time stamps. + * @param parameter an additional parameter object to pass specific data. + * This parameter object maybe one of the two below: + * 1) TLS_SERVER variant validators, where it must be non null and + * the name of the TLS key exchange algorithm being used + * (see JSSE X509TrustManager specification). + * 2) {@code Timestamp} object from a signed JAR file. * @return a non-empty chain that was used to validate the path. The * end entity cert is at index 0, the trust anchor at index n-1. */