8154015: Apply algorithm constraints to timestamped code
authorascarpino
Tue, 05 Jul 2016 15:37:42 -0700
changeset 39465 8c06651d9138
parent 39464 f49988e2d982
child 39477 584070257500
8154015: Apply algorithm constraints to timestamped code Reviewed-by: mullan
jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java
jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java
jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java
jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
jdk/src/java.base/share/classes/sun/security/validator/PKIXValidator.java
jdk/src/java.base/share/classes/sun/security/validator/Validator.java
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Tue Jul 05 10:11:42 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Tue Jul 05 15:37:42 2016 -0700
@@ -27,6 +27,7 @@
 
 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 @@
     private final PublicKey trustedPubKey;
     private final Date pkixdate;
     private PublicKey prevPubKey;
+    private final Timestamp jarTimestamp;
 
     private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
         Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
@@ -142,6 +144,29 @@
         this.trustedPubKey = null;
         this.constraints = constraints;
         this.pkixdate = null;
+        this.jarTimestamp = null;
+    }
+
+    /**
+     * Create a new {@code AlgorithmChecker} with the given
+     * {@code Timestamp}.
+     * <p>
+     * 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 @@
 
         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 @@
         this.prevPubKey = trustedPubKey;
         this.constraints = constraints;
         this.pkixdate = pkixdate;
+        this.jarTimestamp = null;
     }
 
     /**
@@ -209,6 +235,10 @@
         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 @@
         // 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 @@
      * 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 {
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java	Tue Jul 05 10:11:42 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java	Tue Jul 05 15:37:42 2016 -0700
@@ -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 @@
 
 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 @@
         private CertSelector constraints;
         private Set<TrustAnchor> anchors;
         private List<X509Certificate> certs;
+        private Timestamp timestamp;
 
         ValidatorParams(CertPath cp, PKIXParameters params)
             throws InvalidAlgorithmParameterException
@@ -100,6 +102,10 @@
         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 @@
         PKIXParameters getPKIXParameters() {
             return params;
         }
+
+        Timestamp timestamp() {
+            return timestamp;
+        }
     }
 
     static class BuilderParams extends ValidatorParams {
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Tue Jul 05 10:11:42 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Tue Jul 05 15:37:42 2016 -0700
@@ -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 @@
         List<PKIXCertPathChecker> 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 @@
                                              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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java	Tue Jul 05 15:37:42 2016 -0700
@@ -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<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);
+    }
+
+}
--- a/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java	Tue Jul 05 10:11:42 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java	Tue Jul 05 15:37:42 2016 -0700
@@ -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 @@
     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 @@
         return pkixDate;
     }
 
+    public Timestamp getJARTimestamp() {
+        return jarTimestamp;
+    }
+
 }
--- a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Tue Jul 05 10:11:42 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Tue Jul 05 15:37:42 2016 -0700
@@ -594,7 +594,9 @@
                  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();
--- a/jdk/src/java.base/share/classes/sun/security/validator/PKIXValidator.java	Tue Jul 05 10:11:42 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/validator/PKIXValidator.java	Tue Jul 05 15:37:42 2016 -0700
@@ -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 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 @@
                 ("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.
--- a/jdk/src/java.base/share/classes/sun/security/validator/Validator.java	Tue Jul 05 10:11:42 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/validator/Validator.java	Tue Jul 05 15:37:42 2016 -0700
@@ -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 @@
      * Validate the given certificate chain. If otherCerts is non-null, it is
      * a Collection of additional X509Certificates that could be helpful for
      * path building.
-     * <p>
-     * 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 @@
      *        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.
      */