--- a/jdk/src/share/classes/java/security/cert/CertPathBuilder.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/java/security/cert/CertPathBuilder.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -45,15 +45,28 @@
* one of the static <code>getInstance</code> methods, passing in the
* algorithm name of the <code>CertPathBuilder</code> desired and optionally
* the name of the provider desired.
- * <p>
- * Once a <code>CertPathBuilder</code> object has been created, certification
+ *
+ * <p>Once a <code>CertPathBuilder</code> object has been created, certification
* paths can be constructed by calling the {@link #build build} method and
* passing it an algorithm-specific set of parameters. If successful, the
* result (including the <code>CertPath</code> that was built) is returned
* in an object that implements the <code>CertPathBuilderResult</code>
* interface.
*
- * <p> Every implementation of the Java platform is required to support the
+ * <p>The {@link #getRevocationChecker} method allows an application to specify
+ * additional algorithm-specific parameters and options used by the
+ * {@code CertPathBuilder} when checking the revocation status of certificates.
+ * Here is an example demonstrating how it is used with the PKIX algorithm:
+ *
+ * <pre>
+ * CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
+ * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
+ * rc.setOptions(EnumSet.of(Option.PREFER_CRLS));
+ * params.addCertPathChecker(rc);
+ * CertPathBuilderResult cpbr = cpb.build(params);
+ * </pre>
+ *
+ * <p>Every implementation of the Java platform is required to support the
* following standard <code>CertPathBuilder</code> algorithm:
* <ul>
* <li><tt>PKIX</tt></li>
@@ -96,10 +109,9 @@
* </pre>
*/
private static final String CPB_TYPE = "certpathbuilder.type";
- private static final Debug debug = Debug.getInstance("certpath");
- private CertPathBuilderSpi builderSpi;
- private Provider provider;
- private String algorithm;
+ private final CertPathBuilderSpi builderSpi;
+ private final Provider provider;
+ private final String algorithm;
/**
* Creates a <code>CertPathBuilder</code> object of the given algorithm,
@@ -290,15 +302,30 @@
* if no such property exists.
*/
public final static String getDefaultType() {
- String cpbtype;
- cpbtype = AccessController.doPrivileged(new PrivilegedAction<String>() {
- public String run() {
- return Security.getProperty(CPB_TYPE);
- }
- });
- if (cpbtype == null) {
- cpbtype = "PKIX";
- }
- return cpbtype;
+ String cpbtype =
+ AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return Security.getProperty(CPB_TYPE);
+ }
+ });
+ return (cpbtype == null) ? "PKIX" : cpbtype;
+ }
+
+ /**
+ * Returns a {@code CertPathChecker} that the encapsulated
+ * {@code CertPathBuilderSpi} implementation uses to check the revocation
+ * status of certificates. A PKIX implementation returns objects of
+ * type {@code PKIXRevocationChecker}.
+ *
+ * <p>The primary purpose of this method is to allow callers to specify
+ * additional input parameters and options specific to revocation checking.
+ * See the class description for an example.
+ *
+ * @throws UnsupportedOperationException if the service provider does not
+ * support this method
+ * @since 1.8
+ */
+ public final CertPathChecker getRevocationChecker() {
+ return builderSpi.engineGetRevocationChecker();
}
}
--- a/jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -72,4 +72,25 @@
*/
public abstract CertPathBuilderResult engineBuild(CertPathParameters params)
throws CertPathBuilderException, InvalidAlgorithmParameterException;
+
+ /**
+ * Returns a {@code CertPathChecker} that this implementation uses to
+ * check the revocation status of certificates. A PKIX implementation
+ * returns objects of type {@code PKIXRevocationChecker}.
+ *
+ * <p>The primary purpose of this method is to allow callers to specify
+ * additional input parameters and options specific to revocation checking.
+ * See the class description of {@code CertPathBuilder} for an example.
+ *
+ * <p>This method was added to version 1.8 of the Java Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method cannot be abstract and by default throws
+ * an {@code UnsupportedOperationException}.
+ *
+ * @throws UnsupportedOperationException if this method is not supported
+ * @since 1.8
+ */
+ public CertPathChecker engineGetRevocationChecker() {
+ throw new UnsupportedOperationException();
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/cert/CertPathChecker.java Thu May 31 17:07:28 2012 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 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 java.security.cert;
+
+/**
+ * <p>Performs one or more checks on each {@code Certificate} of a
+ * {@code CertPath}.
+ *
+ * <p>A {@code CertPathChecker} implementation is typically created to extend
+ * a certification path validation algorithm. For example, an implementation
+ * may check for and process a critical private extension of each certificate
+ * in a certification path.
+ *
+ * @since 1.8
+ */
+public interface CertPathChecker {
+
+ /**
+ * Initializes the internal state of this {@code CertPathChecker}.
+ *
+ * <p>The {@code forward} flag specifies the order that certificates will
+ * be passed to the {@link #check check} method (forward or reverse).
+ *
+ * @param forward the order that certificates are presented to the
+ * {@code check} method. If {@code true}, certificates are
+ * presented from target to trust anchor (forward); if
+ * {@code false}, from trust anchor to target (reverse).
+ * @throws CertPathValidatorException if this {@code CertPathChecker} is
+ * unable to check certificates in the specified order
+ */
+ void init(boolean forward) throws CertPathValidatorException;
+
+ /**
+ * Indicates if forward checking is supported. Forward checking refers
+ * to the ability of the {@code CertPathChecker} to perform its checks
+ * when certificates are presented to the {@code check} method in the
+ * forward direction (from target to trust anchor).
+ *
+ * @return {@code true} if forward checking is supported, {@code false}
+ * otherwise
+ */
+ boolean isForwardCheckingSupported();
+
+ /**
+ * Performs the check(s) on the specified certificate using its internal
+ * state. The certificates are presented in the order specified by the
+ * {@code init} method.
+ *
+ * @param cert the {@code Certificate} to be checked
+ * @throws CertPathValidatorException if the specified certificate does
+ * not pass the check
+ */
+ void check(Certificate cert) throws CertPathValidatorException;
+}
--- a/jdk/src/share/classes/java/security/cert/CertPathValidator.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/java/security/cert/CertPathValidator.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -46,15 +46,29 @@
* call one of the static <code>getInstance</code> methods, passing in the
* algorithm name of the <code>CertPathValidator</code> desired and
* optionally the name of the provider desired.
- * <p>
- * Once a <code>CertPathValidator</code> object has been created, it can
+ *
+ * <p>Once a <code>CertPathValidator</code> object has been created, it can
* be used to validate certification paths by calling the {@link #validate
* validate} method and passing it the <code>CertPath</code> to be validated
* and an algorithm-specific set of parameters. If successful, the result is
* returned in an object that implements the
* <code>CertPathValidatorResult</code> interface.
*
- * <p> Every implementation of the Java platform is required to support the
+ * <p>The {@link #getRevocationChecker} method allows an application to specify
+ * additional algorithm-specific parameters and options used by the
+ * {@code CertPathValidator} when checking the revocation status of
+ * certificates. Here is an example demonstrating how it is used with the PKIX
+ * algorithm:
+ *
+ * <pre>
+ * CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+ * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpv.getRevocationChecker();
+ * rc.setOptions(EnumSet.of(Option.SOFT_FAIL));
+ * params.addCertPathChecker(rc);
+ * CertPathValidatorResult cpvr = cpv.validate(path, params);
+ * </pre>
+ *
+ * <p>Every implementation of the Java platform is required to support the
* following standard <code>CertPathValidator</code> algorithm:
* <ul>
* <li><tt>PKIX</tt></li>
@@ -96,10 +110,9 @@
* </pre>
*/
private static final String CPV_TYPE = "certpathvalidator.type";
- private static final Debug debug = Debug.getInstance("certpath");
- private CertPathValidatorSpi validatorSpi;
- private Provider provider;
- private String algorithm;
+ private final CertPathValidatorSpi validatorSpi;
+ private final Provider provider;
+ private final String algorithm;
/**
* Creates a <code>CertPathValidator</code> object of the given algorithm,
@@ -301,15 +314,30 @@
* if no such property exists.
*/
public final static String getDefaultType() {
- String cpvtype;
- cpvtype = AccessController.doPrivileged(new PrivilegedAction<String>() {
- public String run() {
- return Security.getProperty(CPV_TYPE);
- }
- });
- if (cpvtype == null) {
- cpvtype = "PKIX";
- }
- return cpvtype;
+ String cpvtype =
+ AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return Security.getProperty(CPV_TYPE);
+ }
+ });
+ return (cpvtype == null) ? "PKIX" : cpvtype;
+ }
+
+ /**
+ * Returns a {@code CertPathChecker} that the encapsulated
+ * {@code CertPathValidatorSpi} implementation uses to check the revocation
+ * status of certificates. A PKIX implementation returns objects of
+ * type {@code PKIXRevocationChecker}.
+ *
+ * <p>The primary purpose of this method is to allow callers to specify
+ * additional input parameters and options specific to revocation checking.
+ * See the class description for an example.
+ *
+ * @throws UnsupportedOperationException if the service provider does not
+ * support this method
+ * @since 1.8
+ */
+ public final CertPathChecker getRevocationChecker() {
+ return validatorSpi.engineGetRevocationChecker();
}
}
--- a/jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -82,4 +82,25 @@
public abstract CertPathValidatorResult
engineValidate(CertPath certPath, CertPathParameters params)
throws CertPathValidatorException, InvalidAlgorithmParameterException;
+
+ /**
+ * Returns a {@code CertPathChecker} that this implementation uses to
+ * check the revocation status of certificates. A PKIX implementation
+ * returns objects of type {@code PKIXRevocationChecker}.
+ *
+ * <p>The primary purpose of this method is to allow callers to specify
+ * additional input parameters and options specific to revocation checking.
+ * See the class description of {@code CertPathValidator} for an example.
+ *
+ * <p>This method was added to version 1.8 of the Java Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method cannot be abstract and by default throws
+ * an {@code UnsupportedOperationException}.
+ *
+ * @throws UnsupportedOperationException if this method is not supported
+ * @since 1.8
+ */
+ public CertPathChecker engineGetRevocationChecker() {
+ throw new UnsupportedOperationException();
+ }
}
--- a/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -87,7 +87,8 @@
* @author Yassir Elley
* @author Sean Mullan
*/
-public abstract class PKIXCertPathChecker implements Cloneable {
+public abstract class PKIXCertPathChecker
+ implements CertPathChecker, Cloneable {
/**
* Default constructor.
@@ -111,6 +112,7 @@
* the specified order; it should never be thrown if the forward flag
* is false since reverse checking must be supported
*/
+ @Override
public abstract void init(boolean forward)
throws CertPathValidatorException;
@@ -123,6 +125,7 @@
* @return <code>true</code> if forward checking is supported,
* <code>false</code> otherwise
*/
+ @Override
public abstract boolean isForwardCheckingSupported();
/**
@@ -163,6 +166,17 @@
throws CertPathValidatorException;
/**
+ * {@inheritDoc}
+ *
+ * <p>This implementation calls
+ * {@code check(cert, java.util.Collections.<String>emptySet())}.
+ */
+ @Override
+ public void check(Certificate cert) throws CertPathValidatorException {
+ check(cert, java.util.Collections.<String>emptySet());
+ }
+
+ /**
* Returns a clone of this object. Calls the <code>Object.clone()</code>
* method.
* All subclasses which maintain state must support and
@@ -170,6 +184,7 @@
*
* @return a copy of this <code>PKIXCertPathChecker</code>
*/
+ @Override
public Object clone() {
try {
return super.clone();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java Thu May 31 17:07:28 2012 -0400
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2012, 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 java.security.cert;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * A {@code PKIXCertPathChecker} for checking the revocation status of
+ * certificates with the PKIX algorithm.
+ *
+ * <p>A {@code PKIXRevocationChecker} checks the revocation status of
+ * certificates with the Online Certificate Status Protocol (OCSP) or
+ * Certificate Revocation Lists (CRLs). OCSP is described in RFC 2560 and
+ * is a network protocol for determining the status of a certificate. A CRL
+ * is a time-stamped list identifying revoked certificates, and RFC 5280
+ * describes an algorithm for determining the revocation status of certificates
+ * using CRLs.
+ *
+ * <p>Each {@code PKIXRevocationChecker} must be able to check the revocation
+ * status of certificates with OCSP and CRLs. By default, OCSP is the
+ * preferred mechanism for checking revocation status, with CRLs as the
+ * fallback mechanism. However, this preference can be switched to CRLs with
+ * the {@link Option.PREFER_CRLS} option.
+ *
+ * <p>A {@code PKIXRevocationChecker} is obtained by calling the
+ * {@link CertPathValidator#getRevocationChecker getRevocationChecker} method
+ * of a PKIX {@code CertPathValidator}. Additional parameters and options
+ * specific to revocation can be set (by calling {@link #setOCSPResponder}
+ * method for instance). The {@code PKIXRevocationChecker} is added to
+ * a {@code PKIXParameters} object using the
+ * {@link PKIXParameters#addCertPathChecker addCertPathChecker}
+ * or {@link PKIXParameters#setCertPathCheckers setCertPathCheckers} method,
+ * and then the {@code PKIXParameters} is passed along with the {@code CertPath}
+ * to be validated to the {@link CertPathValidator#validate validate} method
+ * of a PKIX {@code CertPathValidator}. When supplying a revocation checker in
+ * this manner, do not enable the default revocation checking mechanism (by
+ * calling {@link PKIXParameters#setRevocationEnabled}.
+ *
+ * <p>Note that when a {@code PKIXRevocationChecker} is added to
+ * {@code PKIXParameters}, it clones the {@code PKIXRevocationChecker};
+ * thus any subsequent modifications to the {@code PKIXRevocationChecker}
+ * have no effect.
+ *
+ * <p>Any parameter that is not set (or is set to {@code null}) will be set to
+ * the default value for that parameter.
+ *
+ * <p><b>Concurrent Access</b>
+ *
+ * <p>Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single object
+ * concurrently should synchronize amongst themselves and provide the
+ * necessary locking. Multiple threads each manipulating separate objects
+ * need not synchronize.
+ *
+ * @since 1.8
+ */
+public abstract class PKIXRevocationChecker extends PKIXCertPathChecker {
+ private URI ocspResponder;
+ private X509Certificate ocspResponderCert;
+ private List<Extension> ocspExtensions = Collections.<Extension>emptyList();
+ private Map<X509Certificate, byte[]> ocspStapled = Collections.emptyMap();
+ private Set<Option> options = Collections.emptySet();
+
+ protected PKIXRevocationChecker() {}
+
+ /**
+ * Sets the URI that identifies the location of the OCSP responder. This
+ * overrides the {@code ocsp.responderURL} security property and any
+ * responder specified in a certificate's Authority Information Access
+ * Extension, as defined in RFC 5280.
+ *
+ * @param uri the responder URI
+ */
+ public void setOCSPResponder(URI uri) {
+ this.ocspResponder = uri;
+ }
+
+ /**
+ * Gets the URI that identifies the location of the OCSP responder. This
+ * overrides the {@code ocsp.responderURL} security property. If this
+ * parameter or the {@code ocsp.responderURL} property is not set, the
+ * location is determined from the certificate's Authority Information
+ * Access Extension, as defined in RFC 5280.
+ *
+ * @return the responder URI, or {@code null} if not set
+ */
+ public URI getOCSPResponder() {
+ return ocspResponder;
+ }
+
+ /**
+ * Sets the OCSP responder's certificate. This overrides the
+ * {@code ocsp.responderCertSubjectName},
+ * {@code ocsp.responderCertIssuerName},
+ * and {@code ocsp.responderCertSerialNumber} security properties.
+ *
+ * @param cert the responder's certificate
+ */
+ public void setOCSPResponderCert(X509Certificate cert) {
+ this.ocspResponderCert = cert;
+ }
+
+ /**
+ * Gets the OCSP responder's certificate. This overrides the
+ * {@code ocsp.responderCertSubjectName},
+ * {@code ocsp.responderCertIssuerName},
+ * and {@code ocsp.responderCertSerialNumber} security properties. If this
+ * parameter or the aforementioned properties are not set, then the
+ * responder's certificate is determined as specified in RFC 2560.
+ *
+ * @return the responder's certificate, or {@code null} if not set
+ */
+ public X509Certificate getOCSPResponderCert() {
+ return ocspResponderCert;
+ }
+
+ // request extensions; single extensions not supported
+ /**
+ * Sets the optional OCSP request extensions.
+ *
+ * @param extensions a list of extensions. The list is copied to protect
+ * against subsequent modification.
+ */
+ public void setOCSPExtensions(List<Extension> extensions)
+ {
+ this.ocspExtensions = (extensions == null)
+ ? Collections.<Extension>emptyList()
+ : new ArrayList<Extension>(extensions);
+ }
+
+ /**
+ * Gets the optional OCSP request extensions.
+ *
+ * @return an unmodifiable list of extensions. Returns an empty list if no
+ * extensions have been specified.
+ */
+ public List<Extension> getOCSPExtensions() {
+ return Collections.unmodifiableList(ocspExtensions);
+ }
+
+ /**
+ * Sets the stapled OCSP responses. These responses are used to determine
+ * the revocation status of the specified certificates when OCSP is used.
+ *
+ * @param responses a map of stapled OCSP responses. Each key is an
+ * {@code X509Certificate} that maps to the corresponding
+ * DER-encoded OCSP response for that certificate. A deep copy of
+ * the map is performed to protect against subsequent modification.
+ */
+ public void setOCSPStapledResponses(Map<X509Certificate, byte[]> responses)
+ {
+ if (responses == null) {
+ this.ocspStapled = Collections.<X509Certificate, byte[]>emptyMap();
+ } else {
+ Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size());
+ for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) {
+ copy.put(e.getKey(), e.getValue().clone());
+ }
+ this.ocspStapled = copy;
+ }
+ }
+
+ /**
+ * Gets the stapled OCSP responses. These responses are used to determine
+ * the revocation status of the specified certificates when OCSP is used.
+ *
+ * @return a map of stapled OCSP responses. Each key is an
+ * {@code X509Certificate} that maps to the corresponding
+ * DER-encoded OCSP response for that certificate. A deep copy of
+ * the map is returned to protect against subsequent modification.
+ * Returns an empty map if no responses have been specified.
+ */
+ public Map<X509Certificate, byte[]> getOCSPStapledResponses() {
+ Map<X509Certificate, byte[]> copy = new HashMap<>(ocspStapled.size());
+ for (Map.Entry<X509Certificate, byte[]> e : ocspStapled.entrySet()) {
+ copy.put(e.getKey(), e.getValue().clone());
+ }
+ return copy;
+ }
+
+ /**
+ * Sets the revocation options.
+ *
+ * @param options a set of revocation options. The set is copied to protect
+ * against subsequent modification.
+ */
+ public void setOptions(Set<Option> options) {
+ this.options = (options == null)
+ ? Collections.<Option>emptySet()
+ : new HashSet<Option>(options);
+ }
+
+ /**
+ * Gets the revocation options.
+ *
+ * @return an unmodifiable set of revocation options, or an empty set if
+ * none are specified
+ */
+ public Set<Option> getOptions() {
+ return Collections.unmodifiableSet(options);
+ }
+
+ @Override
+ public Object clone() {
+ PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone();
+ copy.ocspExtensions = new ArrayList<>(ocspExtensions);
+ copy.ocspStapled = new HashMap<>(ocspStapled);
+ // deep-copy the encoded stapled responses, since they are mutable
+ for (Map.Entry<X509Certificate, byte[]> entry :
+ copy.ocspStapled.entrySet())
+ {
+ byte[] encoded = entry.getValue();
+ entry.setValue(encoded.clone());
+ }
+ copy.options = new HashSet<>(options);
+ return copy;
+ }
+
+ /**
+ * Various revocation options that can be specified for the revocation
+ * checking mechanism.
+ */
+ public enum Option {
+ /**
+ * Only check the revocation status of end-entity certificates.
+ */
+ ONLY_END_ENTITY,
+ /**
+ * Prefer CRLs to OSCP. The default behavior is to prefer OCSP. Each
+ * PKIX implementation should document further details of their
+ * specific preference rules and fallback policies.
+ */
+ PREFER_CRLS,
+ /**
+ * Ignore network failures. The default behavior is to consider it a
+ * failure if the revocation status of a certificate cannot be obtained
+ * due to a network error. This option applies to both OCSP and CRLs.
+ */
+ SOFT_FAIL
+ }
+}
--- a/jdk/src/share/classes/java/security/cert/package.html Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/java/security/cert/package.html Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
<!--
- Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1998, 2012, 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,8 +38,10 @@
<li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
Cryptography Architecture (JCA) Reference Guide</b></a>
- <li>RFC 3280: Internet X.509 Public Key Infrastructure Certificate and
+ <li>RFC 5280: Internet X.509 Public Key Infrastructure Certificate and
Certificate Revocation List (CRL) Profile
+ <li>RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate
+ Status Protocol - OCSP
<li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
Cryptography Architecture Standard Algorithm Name
@@ -50,8 +52,8 @@
For information about X.509 certificates and CRLs, please see:
<ul>
- <li><a href="http://www.ietf.org/rfc/rfc3280.txt">
- http://www.ietf.org/rfc/rfc3280.txt</a>
+ <li><a href="http://www.ietf.org/rfc/rfc5280.txt">
+ http://www.ietf.org/rfc/rfc5280.txt</a>
<li><a href=
"{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
--- a/jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -24,13 +24,11 @@
*/
package sun.security.provider.certpath;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-
/**
* An AdjacencyList is used to store the history of certification paths
* attempted in constructing a path from an initiator to a target. The
@@ -123,124 +121,117 @@
* at the start.
*/
private boolean buildList(List<List<Vertex>> theList, int index,
- BuildStep follow) {
+ BuildStep follow) {
// Each time this method is called, we're examining a new list
// from the global list. So, we have to start by getting the list
// that contains the set of Vertexes we're considering.
List<Vertex> l = theList.get(index);
- try {
- // we're interested in the case where all indexes are -1...
- boolean allNegOne = true;
- // ...and in the case where every entry has a Throwable
- boolean allXcps = true;
+ // we're interested in the case where all indexes are -1...
+ boolean allNegOne = true;
+ // ...and in the case where every entry has a Throwable
+ boolean allXcps = true;
+
+ for (Vertex v : l) {
+ if (v.getIndex() != -1) {
+ // count an empty list the same as an index of -1...this
+ // is to patch a bug somewhere in the builder
+ if (theList.get(v.getIndex()).size() != 0)
+ allNegOne = false;
+ } else {
+ if (v.getThrowable() == null)
+ allXcps = false;
+ }
+ // every entry, regardless of the final use for it, is always
+ // entered as a possible step before we take any actions
+ mStepList.add(new BuildStep(v, BuildStep.POSSIBLE));
+ }
+
+ if (allNegOne) {
+ // There are two cases that we could be looking at here. We
+ // may need to back up, or the build may have succeeded at
+ // this point. This is based on whether or not any
+ // exceptions were found in the list.
+ if (allXcps) {
+ // we need to go back...see if this is the last one
+ if (follow == null)
+ mStepList.add(new BuildStep(null, BuildStep.FAIL));
+ else
+ mStepList.add(new BuildStep(follow.getVertex(),
+ BuildStep.BACK));
+
+ return false;
+ } else {
+ // we succeeded...now the only question is which is the
+ // successful step? If there's only one entry without
+ // a throwable, then that's the successful step. Otherwise,
+ // we'll have to make some guesses...
+ List<Vertex> possibles = new ArrayList<>();
+ for (Vertex v : l) {
+ if (v.getThrowable() == null)
+ possibles.add(v);
+ }
+
+ if (possibles.size() == 1) {
+ // real easy...we've found the final Vertex
+ mStepList.add(new BuildStep(possibles.get(0),
+ BuildStep.SUCCEED));
+ } else {
+ // ok...at this point, there is more than one Cert
+ // which might be the succeed step...how do we know
+ // which it is? I'm going to assume that our builder
+ // algorithm is good enough to know which is the
+ // correct one, and put it first...but a FIXME goes
+ // here anyway, and we should be comparing to the
+ // target/initiator Cert...
+ mStepList.add(new BuildStep(possibles.get(0),
+ BuildStep.SUCCEED));
+ }
+
+ return true;
+ }
+ } else {
+ // There's at least one thing that we can try before we give
+ // up and go back. Run through the list now, and enter a new
+ // BuildStep for each path that we try to follow. If none of
+ // the paths we try produce a successful end, we're going to
+ // have to back out ourselves.
+ boolean success = false;
for (Vertex v : l) {
+
+ // Note that we'll only find a SUCCEED case when we're
+ // looking at the last possible path, so we don't need to
+ // consider success in the while loop
+
if (v.getIndex() != -1) {
- // count an empty list the same as an index of -1...this
- // is to patch a bug somewhere in the builder
- if (theList.get(v.getIndex()).size() != 0)
- allNegOne = false;
+ if (theList.get(v.getIndex()).size() != 0) {
+ // If the entry we're looking at doesn't have an
+ // index of -1, and doesn't lead to an empty list,
+ // then it's something we follow!
+ BuildStep bs = new BuildStep(v, BuildStep.FOLLOW);
+ mStepList.add(bs);
+ success = buildList(theList, v.getIndex(), bs);
+ }
}
- else
- if (v.getThrowable() == null)
- allXcps = false;
-
- // every entry, regardless of the final use for it, is always
- // entered as a possible step before we take any actions
- mStepList.add(new BuildStep(v, BuildStep.POSSIBLE));
}
- if (allNegOne) {
- // There are two cases that we could be looking at here. We
- // may need to back up, or the build may have succeeded at
- // this point. This is based on whether or not any
- // exceptions were found in the list.
- if (allXcps) {
- // we need to go back...see if this is the last one
- if (follow == null)
- mStepList.add(new BuildStep(null, BuildStep.FAIL));
- else
- mStepList.add(new BuildStep(follow.getVertex(),
- BuildStep.BACK));
-
- return false;
- } else {
- // we succeeded...now the only question is which is the
- // successful step? If there's only one entry without
- // a throwable, then that's the successful step. Otherwise,
- // we'll have to make some guesses...
- List<Vertex> possibles = new ArrayList<Vertex>();
- for (Vertex v : l) {
- if (v.getThrowable() == null)
- possibles.add(v);
- }
-
- if (possibles.size() == 1) {
- // real easy...we've found the final Vertex
- mStepList.add(new BuildStep(possibles.get(0),
- BuildStep.SUCCEED));
- } else {
- // ok...at this point, there is more than one Cert
- // which might be the succeed step...how do we know
- // which it is? I'm going to assume that our builder
- // algorithm is good enough to know which is the
- // correct one, and put it first...but a FIXME goes
- // here anyway, and we should be comparing to the
- // target/initiator Cert...
- mStepList.add(new BuildStep(possibles.get(0),
- BuildStep.SUCCEED));
- }
+ if (success) {
+ // We're already finished!
+ return true;
+ } else {
+ // We failed, and we've exhausted all the paths that we
+ // could take. The only choice is to back ourselves out.
+ if (follow == null)
+ mStepList.add(new BuildStep(null, BuildStep.FAIL));
+ else
+ mStepList.add(new BuildStep(follow.getVertex(),
+ BuildStep.BACK));
- return true;
- }
- } else {
- // There's at least one thing that we can try before we give
- // up and go back. Run through the list now, and enter a new
- // BuildStep for each path that we try to follow. If none of
- // the paths we try produce a successful end, we're going to
- // have to back out ourselves.
- boolean success = false;
-
- for (Vertex v : l) {
-
- // Note that we'll only find a SUCCEED case when we're
- // looking at the last possible path, so we don't need to
- // consider success in the while loop
-
- if (v.getIndex() != -1) {
- if (theList.get(v.getIndex()).size() != 0) {
- // If the entry we're looking at doesn't have an
- // index of -1, and doesn't lead to an empty list,
- // then it's something we follow!
- BuildStep bs = new BuildStep(v, BuildStep.FOLLOW);
- mStepList.add(bs);
- success = buildList(theList, v.getIndex(), bs);
- }
- }
- }
-
- if (success) {
- // We're already finished!
- return true;
- } else {
- // We failed, and we've exhausted all the paths that we
- // could take. The only choice is to back ourselves out.
- if (follow == null)
- mStepList.add(new BuildStep(null, BuildStep.FAIL));
- else
- mStepList.add(new BuildStep(follow.getVertex(),
- BuildStep.BACK));
-
- return false;
- }
+ return false;
}
}
- catch (Exception e) {}
-
- // we'll never get here, but you know java...
- return false;
}
/**
@@ -248,23 +239,20 @@
*
* @return String representation
*/
+ @Override
public String toString() {
- String out = "[\n";
+ StringBuilder sb = new StringBuilder("[\n");
int i = 0;
for (List<Vertex> l : mOrigList) {
- out = out + "LinkedList[" + i++ + "]:\n";
+ sb.append("LinkedList[").append(i++).append("]:\n");
for (Vertex step : l) {
- try {
- out = out + step.toString();
- out = out + "\n";
- }
- catch (Exception e) { out = out + "No Such Element\n"; }
+ sb.append(step.toString()).append("\n");
}
}
- out = out + "]\n";
+ sb.append("]\n");
- return out;
+ return sb.toString();
}
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -62,7 +62,7 @@
private static final Debug debug = Debug.getInstance("certpath");
private final PublicKey trustedPubKey;
private final X500Principal caName;
- private final Date testDate;
+ private final Date date;
private final String sigProvider;
private final boolean sigOnly;
private X500Principal prevSubject;
@@ -73,14 +73,13 @@
*
* @param anchor the anchor selected to validate the target certificate
* @param testDate the time for which the validity of the certificate
- * should be determined
+ * should be determined
* @param sigProvider the name of the signature provider
* @param sigOnly true if only signature checking is to be done;
* if false, all checks are done
*/
- BasicChecker(TrustAnchor anchor, Date testDate, String sigProvider,
- boolean sigOnly) throws CertPathValidatorException
- {
+ BasicChecker(TrustAnchor anchor, Date date, String sigProvider,
+ boolean sigOnly) {
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
this.caName = anchor.getTrustedCert().getSubjectX500Principal();
@@ -88,16 +87,16 @@
this.trustedPubKey = anchor.getCAPublicKey();
this.caName = anchor.getCA();
}
- this.testDate = testDate;
+ this.date = date;
this.sigProvider = sigProvider;
this.sigOnly = sigOnly;
- init(false);
}
/**
* Initializes the internal state of the checker from parameters
* specified in the constructor.
*/
+ @Override
public void init(boolean forward) throws CertPathValidatorException {
if (!forward) {
prevPubKey = trustedPubKey;
@@ -108,10 +107,12 @@
}
}
+ @Override
public boolean isForwardCheckingSupported() {
return false;
}
+ @Override
public Set<String> getSupportedExtensions() {
return null;
}
@@ -124,33 +125,31 @@
* @param cert the Certificate
* @param unresolvedCritExts a Collection of the unresolved critical
* extensions
- * @exception CertPathValidatorException Exception thrown if certificate
- * does not verify.
+ * @throws CertPathValidatorException if certificate does not verify
*/
+ @Override
public void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException
{
- X509Certificate currCert = (X509Certificate) cert;
+ X509Certificate currCert = (X509Certificate)cert;
if (!sigOnly) {
- verifyTimestamp(currCert, testDate);
- verifyNameChaining(currCert, prevSubject);
+ verifyTimestamp(currCert);
+ verifyNameChaining(currCert);
}
- verifySignature(currCert, prevPubKey, sigProvider);
+ verifySignature(currCert);
updateState(currCert);
}
/**
- * Verifies the signature on the certificate using the previous public key
- * @param cert the Certificate
- * @param prevPubKey the previous PublicKey
- * @param sigProvider a String containing the signature provider
- * @exception CertPathValidatorException Exception thrown if certificate
- * does not verify.
+ * Verifies the signature on the certificate using the previous public key.
+ *
+ * @param cert the X509Certificate
+ * @throws CertPathValidatorException if certificate does not verify
*/
- private void verifySignature(X509Certificate cert, PublicKey prevPubKey,
- String sigProvider) throws CertPathValidatorException
+ private void verifySignature(X509Certificate cert)
+ throws CertPathValidatorException
{
String msg = "signature";
if (debug != null)
@@ -162,7 +161,7 @@
throw new CertPathValidatorException
(msg + " check failed", e, null, -1,
BasicReason.INVALID_SIGNATURE);
- } catch (Exception e) {
+ } catch (GeneralSecurityException e) {
throw new CertPathValidatorException(msg + " check failed", e);
}
@@ -173,7 +172,7 @@
/**
* Internal method to verify the timestamp on a certificate
*/
- private void verifyTimestamp(X509Certificate cert, Date date)
+ private void verifyTimestamp(X509Certificate cert)
throws CertPathValidatorException
{
String msg = "timestamp";
@@ -197,8 +196,8 @@
/**
* Internal method to check that cert has a valid DN to be next in a chain
*/
- private void verifyNameChaining(X509Certificate cert,
- X500Principal prevSubject) throws CertPathValidatorException
+ private void verifyNameChaining(X509Certificate cert)
+ throws CertPathValidatorException
{
if (prevSubject != null) {
@@ -207,8 +206,8 @@
debug.println("---checking " + msg + "...");
X500Principal currIssuer = cert.getIssuerX500Principal();
+
// reject null or empty issuer DNs
-
if (X500Name.asX500Name(currIssuer).isEmpty()) {
throw new CertPathValidatorException
(msg + " check failed: " +
--- a/jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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,7 +25,6 @@
package sun.security.provider.certpath;
-import sun.security.util.Debug;
import java.security.cert.X509Certificate;
/**
@@ -39,7 +38,6 @@
*/
public class BuildStep {
- private static final Debug debug = Debug.getInstance("certpath");
private Vertex vertex;
private X509Certificate cert;
private Throwable throwable;
@@ -86,7 +84,7 @@
public BuildStep(Vertex vtx, int res) {
vertex = vtx;
if (vertex != null) {
- cert = (X509Certificate)vertex.getCertificate();
+ cert = vertex.getCertificate();
throwable = vertex.getThrowable();
}
result = res;
@@ -117,7 +115,7 @@
* @returns String form of issuer name or null, if no certificate.
*/
public String getIssuerName() {
- return (cert == null ? null : cert.getIssuerX500Principal().toString());
+ return getIssuerName(null);
}
/**
@@ -142,7 +140,7 @@
* @returns String form of subject name or null, if no certificate.
*/
public String getSubjectName() {
- return (cert == null ? null : cert.getSubjectX500Principal().toString());
+ return getSubjectName(null);
}
/**
@@ -191,21 +189,21 @@
public String resultToString(int res) {
String resultString = "";
switch (res) {
- case BuildStep.POSSIBLE:
+ case POSSIBLE:
resultString = "Certificate to be tried.\n";
break;
- case BuildStep.BACK:
+ case BACK:
resultString = "Certificate backed out since path does not "
+ "satisfy build requirements.\n";
break;
- case BuildStep.FOLLOW:
+ case FOLLOW:
resultString = "Certificate satisfies conditions.\n";
break;
- case BuildStep.FAIL:
+ case FAIL:
resultString = "Certificate backed out since path does not "
+ "satisfy conditions.\n";
break;
- case BuildStep.SUCCEED:
+ case SUCCEED:
resultString = "Certificate satisfies conditions.\n";
break;
default:
@@ -220,6 +218,7 @@
*
* @returns String
*/
+ @Override
public String toString() {
String out = "Internal Error\n";
switch (result) {
@@ -273,8 +272,6 @@
* @returns String
*/
public String fullToString() {
- String out = resultToString(getResult());
- out = out + vertex.toString();
- return out;
+ return resultToString(getResult()) + vertex.toString();
}
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/Builder.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/Builder.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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,9 +31,8 @@
import java.security.cert.*;
import java.util.*;
-import javax.security.auth.x500.X500Principal;
-
import sun.security.action.GetBooleanAction;
+import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug;
import sun.security.x509.GeneralNames;
import sun.security.x509.GeneralNameInterface;
@@ -56,9 +55,7 @@
private static final Debug debug = Debug.getInstance("certpath");
private Set<String> matchingPolicies;
- final PKIXBuilderParameters buildParams;
- final X500Principal targetSubjectDN;
- final Date date;
+ final BuilderParams buildParams;
final X509CertSelector targetCertConstraints;
/**
@@ -74,14 +71,10 @@
*
* @param params the parameter set used to build a certification path
*/
- Builder(PKIXBuilderParameters buildParams, X500Principal targetSubjectDN) {
+ Builder(BuilderParams buildParams) {
this.buildParams = buildParams;
- this.targetSubjectDN = targetSubjectDN;
- // Initialize date if not specified
- Date paramsDate = buildParams.getDate();
- this.date = paramsDate != null ? paramsDate : new Date();
this.targetCertConstraints =
- (X509CertSelector) buildParams.getTargetCertConstraints();
+ (X509CertSelector)buildParams.targetCertConstraints();
}
/**
@@ -104,7 +97,8 @@
* @param certPathList the certPathList generated thus far
*/
abstract void verifyCert(X509Certificate cert, State currentState,
- List<X509Certificate> certPathList) throws GeneralSecurityException;
+ List<X509Certificate> certPathList)
+ throws GeneralSecurityException;
/**
* Verifies whether the input certificate completes the path.
@@ -123,7 +117,7 @@
* @param certPathList the certification path list
*/
abstract void addCertToPath(X509Certificate cert,
- LinkedList<X509Certificate> certPathList);
+ LinkedList<X509Certificate> certPathList);
/**
* Removes final certificate from the certPathList
@@ -147,7 +141,8 @@
* is a grandparent, etc.
*/
static int distance(GeneralNameInterface base,
- GeneralNameInterface test, int incomparable) {
+ GeneralNameInterface test, int incomparable)
+ {
switch (base.constrains(test)) {
case GeneralNameInterface.NAME_DIFF_TYPE:
if (debug != null) {
@@ -192,7 +187,8 @@
* some number of down hops.
*/
static int hops(GeneralNameInterface base, GeneralNameInterface test,
- int incomparable) {
+ int incomparable)
+ {
int baseRtest = base.constrains(test);
switch (baseRtest) {
case GeneralNameInterface.NAME_DIFF_TYPE:
@@ -282,9 +278,9 @@
* @throws IOException if certificate does not get closer
*/
static int targetDistance(NameConstraintsExtension constraints,
- X509Certificate cert, GeneralNameInterface target)
- throws IOException {
-
+ X509Certificate cert, GeneralNameInterface target)
+ throws IOException
+ {
/* ensure that certificate satisfies existing name constraints */
if (constraints != null && !constraints.verify(cert)) {
throw new IOException("certificate does not satisfy existing name "
@@ -295,7 +291,7 @@
try {
certImpl = X509CertImpl.toImpl(cert);
} catch (CertificateException e) {
- throw (IOException)new IOException("Invalid certificate").initCause(e);
+ throw new IOException("Invalid certificate", e);
}
/* see if certificate subject matches target */
X500Name subject = X500Name.asX500Name(certImpl.getSubjectX500Principal());
@@ -398,13 +394,13 @@
*/
Set<String> getMatchingPolicies() {
if (matchingPolicies != null) {
- Set<String> initialPolicies = buildParams.getInitialPolicies();
+ Set<String> initialPolicies = buildParams.initialPolicies();
if ((!initialPolicies.isEmpty()) &&
(!initialPolicies.contains(PolicyChecker.ANY_POLICY)) &&
- (buildParams.isPolicyMappingInhibited()))
+ (buildParams.policyMappingInhibited()))
{
- initialPolicies.add(PolicyChecker.ANY_POLICY);
- matchingPolicies = initialPolicies;
+ matchingPolicies = new HashSet<>(initialPolicies);
+ matchingPolicies.add(PolicyChecker.ANY_POLICY);
} else {
// we just return an empty set to make sure that there is
// at least a certificate policies extension in the cert
@@ -429,13 +425,15 @@
* Returns true iff resultCerts changed (a cert was added to the collection)
*/
boolean addMatchingCerts(X509CertSelector selector,
- Collection<CertStore> certStores,
- Collection<X509Certificate> resultCerts, boolean checkAll) {
+ Collection<CertStore> certStores,
+ Collection<X509Certificate> resultCerts,
+ boolean checkAll)
+ {
X509Certificate targetCert = selector.getCertificate();
if (targetCert != null) {
// no need to search CertStores
if (selector.match(targetCert) && !X509CertImpl.isSelfSigned
- (targetCert, buildParams.getSigProvider())) {
+ (targetCert, buildParams.sigProvider())) {
if (debug != null) {
debug.println("Builder.addMatchingCerts: adding target cert");
}
@@ -450,7 +448,7 @@
store.getCertificates(selector);
for (Certificate cert : certs) {
if (!X509CertImpl.isSelfSigned
- ((X509Certificate)cert, buildParams.getSigProvider())) {
+ ((X509Certificate)cert, buildParams.sigProvider())) {
if (resultCerts.add((X509Certificate)cert)) {
add = true;
}
@@ -471,16 +469,4 @@
}
return add;
}
-
- /**
- * Returns true if CertStore is local. Currently, returns true if
- * type is Collection or if it has been initialized with
- * CollectionCertStoreParameters. A new API method should be added
- * to CertStore that returns local or remote.
- */
- static boolean isLocalCertStore(CertStore certStore) {
- return (certStore.getType().equals("Collection") ||
- certStore.getCertStoreParameters() instanceof
- CollectionCertStoreParameters);
- }
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, 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
@@ -83,9 +83,8 @@
= (CertStoreHelper)c.newInstance();
cache.put(type, csh);
return csh;
- } catch (InstantiationException e) {
- throw new AssertionError(e);
- } catch (IllegalAccessException e) {
+ } catch (InstantiationException |
+ IllegalAccessException e) {
throw new AssertionError(e);
}
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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,7 +31,6 @@
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
-import java.util.Iterator;
import java.security.cert.CertSelector;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
@@ -114,6 +113,7 @@
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
+ @Override
public Collection<Certificate> engineGetCertificates
(CertSelector selector) throws CertStoreException {
if (coll == null) {
@@ -122,18 +122,15 @@
// Tolerate a few ConcurrentModificationExceptions
for (int c = 0; c < 10; c++) {
try {
- HashSet<Certificate> result = new HashSet<Certificate>();
- Iterator<?> i = coll.iterator();
+ HashSet<Certificate> result = new HashSet<>();
if (selector != null) {
- while (i.hasNext()) {
- Object o = i.next();
+ for (Object o : coll) {
if ((o instanceof Certificate) &&
selector.match((Certificate) o))
result.add((Certificate)o);
}
} else {
- while (i.hasNext()) {
- Object o = i.next();
+ for (Object o : coll) {
if (o instanceof Certificate)
result.add((Certificate)o);
}
@@ -157,6 +154,7 @@
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
+ @Override
public Collection<CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException
{
@@ -166,22 +164,19 @@
// Tolerate a few ConcurrentModificationExceptions
for (int c = 0; c < 10; c++) {
try {
- HashSet<CRL> result = new HashSet<CRL>();
- Iterator<?> i = coll.iterator();
+ HashSet<CRL> result = new HashSet<>();
if (selector != null) {
- while (i.hasNext()) {
- Object o = i.next();
+ for (Object o : coll) {
if ((o instanceof CRL) && selector.match((CRL) o))
result.add((CRL)o);
}
} else {
- while (i.hasNext()) {
- Object o = i.next();
+ for (Object o : coll) {
if (o instanceof CRL)
result.add((CRL)o);
}
}
- return(result);
+ return result;
} catch (ConcurrentModificationException e) { }
}
throw new ConcurrentModificationException("Too many "
--- a/jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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,19 +25,20 @@
package sun.security.provider.certpath;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-import java.util.HashSet;
import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
-import java.security.cert.X509Certificate;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXReason;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
import sun.security.util.Debug;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.NameConstraintsExtension;
import sun.security.x509.X509CertImpl;
@@ -66,13 +67,12 @@
* Creates a ConstraintsChecker.
*
* @param certPathLength the length of the certification path
- * @throws CertPathValidatorException if the checker cannot be initialized
*/
- ConstraintsChecker(int certPathLength) throws CertPathValidatorException {
+ ConstraintsChecker(int certPathLength) {
this.certPathLength = certPathLength;
- init(false);
}
+ @Override
public void init(boolean forward) throws CertPathValidatorException {
if (!forward) {
i = 0;
@@ -84,15 +84,17 @@
}
}
+ @Override
public boolean isForwardCheckingSupported() {
return false;
}
+ @Override
public Set<String> getSupportedExtensions() {
if (supportedExts == null) {
- supportedExts = new HashSet<String>();
- supportedExts.add(PKIXExtensions.BasicConstraints_Id.toString());
- supportedExts.add(PKIXExtensions.NameConstraints_Id.toString());
+ supportedExts = new HashSet<String>(2);
+ supportedExts.add(BasicConstraints_Id.toString());
+ supportedExts.add(NameConstraints_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts);
}
return supportedExts;
@@ -104,14 +106,15 @@
*
* @param cert the <code>Certificate</code> to be checked
* @param unresCritExts a <code>Collection</code> of OID strings
- * representing the current set of unresolved critical extensions
+ * representing the current set of unresolved critical extensions
* @throws CertPathValidatorException if the specified certificate
- * does not pass the check
+ * does not pass the check
*/
+ @Override
public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException
{
- X509Certificate currCert = (X509Certificate) cert;
+ X509Certificate currCert = (X509Certificate)cert;
i++;
// MUST run NC check second, since it depends on BC check to
@@ -120,8 +123,8 @@
verifyNameConstraints(currCert);
if (unresCritExts != null && !unresCritExts.isEmpty()) {
- unresCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString());
- unresCritExts.remove(PKIXExtensions.NameConstraints_Id.toString());
+ unresCritExts.remove(BasicConstraints_Id.toString());
+ unresCritExts.remove(NameConstraints_Id.toString());
}
}
@@ -166,9 +169,9 @@
/**
* Helper to fold sets of name constraints together
*/
- static NameConstraintsExtension
- mergeNameConstraints(X509Certificate currCert,
- NameConstraintsExtension prevNC) throws CertPathValidatorException
+ static NameConstraintsExtension mergeNameConstraints(
+ X509Certificate currCert, NameConstraintsExtension prevNC)
+ throws CertPathValidatorException
{
X509CertImpl currCertImpl;
try {
@@ -197,7 +200,7 @@
// Make sure we do a clone here, because we're probably
// going to modify this object later and we don't want to
// be sharing it with a Certificate object!
- return (NameConstraintsExtension) newConstraints.clone();
+ return (NameConstraintsExtension)newConstraints.clone();
}
} else {
try {
--- a/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java Tue May 29 14:56:48 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,785 +0,0 @@
-/*
- * Copyright (c) 2000, 2011, 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.math.BigInteger;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.Iterator;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
-import java.security.cert.*;
-import java.security.cert.CertPathValidatorException.BasicReason;
-import java.security.interfaces.DSAPublicKey;
-import sun.security.util.Debug;
-import sun.security.x509.AccessDescription;
-import sun.security.x509.AuthorityInfoAccessExtension;
-import sun.security.x509.CRLDistributionPointsExtension;
-import sun.security.x509.DistributionPoint;
-import sun.security.x509.GeneralName;
-import sun.security.x509.GeneralNames;
-import sun.security.x509.PKIXExtensions;
-import sun.security.x509.X500Name;
-import sun.security.x509.X509CertImpl;
-import sun.security.x509.X509CRLEntryImpl;
-
-/**
- * CrlRevocationChecker is a <code>PKIXCertPathChecker</code> that checks
- * revocation status information on a PKIX certificate using CRLs obtained
- * from one or more <code>CertStores</code>. This is based on section 6.3
- * of RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt).
- *
- * @since 1.4
- * @author Seth Proctor
- * @author Steve Hanna
- */
-class CrlRevocationChecker extends PKIXCertPathChecker {
-
- private static final Debug debug = Debug.getInstance("certpath");
- private final TrustAnchor mAnchor;
- private final List<CertStore> mStores;
- private final String mSigProvider;
- private final Date mCurrentTime;
- private PublicKey mPrevPubKey;
- private boolean mCRLSignFlag;
- private HashSet<X509CRL> mPossibleCRLs;
- private HashSet<X509CRL> mApprovedCRLs;
- private final PKIXParameters mParams;
- private static final boolean [] mCrlSignUsage =
- { false, false, false, false, false, false, true };
- private static final boolean[] ALL_REASONS =
- {true, true, true, true, true, true, true, true, true};
- private boolean mOnlyEECert = false;
-
- // Maximum clock skew in milliseconds (15 minutes) allowed when checking
- // validity of CRLs
- private static final long MAX_CLOCK_SKEW = 900000;
-
- /**
- * Creates a <code>CrlRevocationChecker</code>.
- *
- * @param anchor anchor selected to validate the target certificate
- * @param params <code>PKIXParameters</code> to be used for
- * finding certificates and CRLs, etc.
- */
- CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params)
- throws CertPathValidatorException
- {
- this(anchor, params, null);
- }
-
- /**
- * Creates a <code>CrlRevocationChecker</code>, allowing
- * extra certificates to be supplied beyond those contained
- * in the <code>PKIXParameters</code>.
- *
- * @param anchor anchor selected to validate the target certificate
- * @param params <code>PKIXParameters</code> to be used for
- * finding certificates and CRLs, etc.
- * @param certs a <code>Collection</code> of certificates
- * that may be useful, beyond those available
- * through <code>params</code> (<code>null</code>
- * if none)
- */
- CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
- Collection<X509Certificate> certs) throws CertPathValidatorException
- {
- this(anchor, params, certs, false);
- }
-
- CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
- Collection<X509Certificate> certs, boolean onlyEECert)
- throws CertPathValidatorException {
- mAnchor = anchor;
- mParams = params;
- mStores = new ArrayList<CertStore>(params.getCertStores());
- mSigProvider = params.getSigProvider();
- if (certs != null) {
- try {
- mStores.add(CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certs)));
- } catch (Exception e) {
- // should never occur but not necessarily fatal, so log it,
- // ignore and continue
- if (debug != null) {
- debug.println("CrlRevocationChecker: " +
- "error creating Collection CertStore: " + e);
- }
- }
- }
- Date testDate = params.getDate();
- mCurrentTime = (testDate != null ? testDate : new Date());
- mOnlyEECert = onlyEECert;
- init(false);
- }
-
- /**
- * Initializes the internal state of the checker from parameters
- * specified in the constructor
- */
- public void init(boolean forward) throws CertPathValidatorException
- {
- if (!forward) {
- if (mAnchor != null) {
- if (mAnchor.getCAPublicKey() != null) {
- mPrevPubKey = mAnchor.getCAPublicKey();
- } else {
- mPrevPubKey = mAnchor.getTrustedCert().getPublicKey();
- }
- } else {
- mPrevPubKey = null;
- }
- mCRLSignFlag = true;
- } else {
- throw new CertPathValidatorException("forward checking "
- + "not supported");
- }
- }
-
- public boolean isForwardCheckingSupported() {
- return false;
- }
-
- public Set<String> getSupportedExtensions() {
- return null;
- }
-
- /**
- * Performs the revocation status check on the certificate using
- * its internal state.
- *
- * @param cert the Certificate
- * @param unresolvedCritExts a Collection of the unresolved critical
- * extensions
- * @exception CertPathValidatorException Exception thrown if
- * certificate does not verify
- */
- public void check(Certificate cert, Collection<String> unresolvedCritExts)
- throws CertPathValidatorException
- {
- X509Certificate currCert = (X509Certificate) cert;
- verifyRevocationStatus(currCert, mPrevPubKey, mCRLSignFlag, true);
-
- // Make new public key if parameters are missing
- PublicKey cKey = currCert.getPublicKey();
- if (cKey instanceof DSAPublicKey &&
- ((DSAPublicKey)cKey).getParams() == null) {
- // cKey needs to inherit DSA parameters from prev key
- cKey = BasicChecker.makeInheritedParamsKey(cKey, mPrevPubKey);
- }
- mPrevPubKey = cKey;
- mCRLSignFlag = certCanSignCrl(currCert);
- }
-
- /**
- * Performs the revocation status check on the certificate using
- * the provided state variables, as well as the constant internal
- * data.
- *
- * @param currCert the Certificate
- * @param prevKey the previous PublicKey in the chain
- * @param signFlag a boolean as returned from the last call, or true
- * if this is the first cert in the chain
- * @return a boolean specifying if the cert is allowed to vouch for the
- * validity of a CRL for the next iteration
- * @exception CertPathValidatorException Exception thrown if
- * certificate does not verify.
- */
- public boolean check(X509Certificate currCert, PublicKey prevKey,
- boolean signFlag) throws CertPathValidatorException
- {
- verifyRevocationStatus(currCert, prevKey, signFlag, true);
- return certCanSignCrl(currCert);
- }
-
- /**
- * Checks that a cert can be used to verify a CRL.
- *
- * @param currCert an X509Certificate to check
- * @return a boolean specifying if the cert is allowed to vouch for the
- * validity of a CRL
- */
- static boolean certCanSignCrl(X509Certificate currCert) {
- // if the cert doesn't include the key usage ext, or
- // the key usage ext asserts cRLSigning, return true,
- // otherwise return false.
- boolean[] kbools = currCert.getKeyUsage();
- if (kbools != null) {
- return kbools[6];
- }
- return false;
- }
-
- /**
- * Internal method to start the verification of a cert
- */
- private void verifyRevocationStatus(X509Certificate currCert,
- PublicKey prevKey, boolean signFlag, boolean allowSeparateKey)
- throws CertPathValidatorException
- {
- verifyRevocationStatus(currCert, prevKey, signFlag,
- allowSeparateKey, null, mParams.getTrustAnchors());
- }
-
- /**
- * Internal method to start the verification of a cert
- * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
- * whose revocation status depends on the
- * non-revoked status of this cert. To avoid
- * circular dependencies, we assume they're
- * revoked while checking the revocation
- * status of this cert.
- * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
- */
- private void verifyRevocationStatus(X509Certificate currCert,
- PublicKey prevKey, boolean signFlag, boolean allowSeparateKey,
- Set<X509Certificate> stackedCerts,
- Set<TrustAnchor> trustAnchors) throws CertPathValidatorException {
-
- String msg = "revocation status";
- if (debug != null) {
- debug.println("CrlRevocationChecker.verifyRevocationStatus()" +
- " ---checking " + msg + "...");
- }
-
- if (mOnlyEECert && currCert.getBasicConstraints() != -1) {
- if (debug != null) {
- debug.println("Skipping revocation check, not end entity cert");
- }
- return;
- }
-
- // reject circular dependencies - RFC 3280 is not explicit on how
- // to handle this, so we feel it is safest to reject them until
- // the issue is resolved in the PKIX WG.
- if ((stackedCerts != null) && stackedCerts.contains(currCert)) {
- if (debug != null) {
- debug.println("CrlRevocationChecker.verifyRevocationStatus()" +
- " circular dependency");
- }
- throw new CertPathValidatorException
- ("Could not determine revocation status", null, null, -1,
- BasicReason.UNDETERMINED_REVOCATION_STATUS);
- }
-
- // init the state for this run
- mPossibleCRLs = new HashSet<X509CRL>();
- mApprovedCRLs = new HashSet<X509CRL>();
- boolean[] reasonsMask = new boolean[9];
-
- try {
- X509CRLSelector sel = new X509CRLSelector();
- sel.setCertificateChecking(currCert);
- CertPathHelper.setDateAndTime(sel, mCurrentTime, MAX_CLOCK_SKEW);
-
- for (CertStore mStore : mStores) {
- for (java.security.cert.CRL crl : mStore.getCRLs(sel)) {
- mPossibleCRLs.add((X509CRL)crl);
- }
- }
- DistributionPointFetcher store =
- DistributionPointFetcher.getInstance();
- // all CRLs returned by the DP Fetcher have also been verified
- mApprovedCRLs.addAll(store.getCRLs(sel, signFlag, prevKey,
- mSigProvider, mStores, reasonsMask, trustAnchors,
- mParams.getDate()));
- } catch (Exception e) {
- if (debug != null) {
- debug.println("CrlRevocationChecker.verifyRevocationStatus() "
- + "unexpected exception: " + e.getMessage());
- }
- throw new CertPathValidatorException(e);
- }
-
- if (debug != null) {
- debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
- "crls.size() = " + mPossibleCRLs.size());
- }
- if (!mPossibleCRLs.isEmpty()) {
- // Now that we have a list of possible CRLs, see which ones can
- // be approved
- mApprovedCRLs.addAll(verifyPossibleCRLs(mPossibleCRLs, currCert,
- signFlag, prevKey, reasonsMask, trustAnchors));
- }
- if (debug != null) {
- debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
- "approved crls.size() = " + mApprovedCRLs.size());
- }
-
- // make sure that we have at least one CRL that _could_ cover
- // the certificate in question and all reasons are covered
- if (mApprovedCRLs.isEmpty() ||
- !Arrays.equals(reasonsMask, ALL_REASONS)) {
- if (allowSeparateKey) {
- verifyWithSeparateSigningKey(currCert, prevKey, signFlag,
- stackedCerts);
- return;
- } else {
- throw new CertPathValidatorException
- ("Could not determine revocation status", null, null, -1,
- BasicReason.UNDETERMINED_REVOCATION_STATUS);
- }
- }
-
- // See if the cert is in the set of approved crls.
- if (debug != null) {
- BigInteger sn = currCert.getSerialNumber();
- debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
- "starting the final sweep...");
- debug.println("CrlRevocationChecker.verifyRevocationStatus" +
- " cert SN: " + sn.toString());
- }
-
- CRLReason reasonCode = CRLReason.UNSPECIFIED;
- X509CRLEntryImpl entry = null;
- for (X509CRL crl : mApprovedCRLs) {
- X509CRLEntry e = crl.getRevokedCertificate(currCert);
- if (e != null) {
- try {
- entry = X509CRLEntryImpl.toImpl(e);
- } catch (CRLException ce) {
- throw new CertPathValidatorException(ce);
- }
- if (debug != null) {
- debug.println("CrlRevocationChecker.verifyRevocationStatus"
- + " CRL entry: " + entry.toString());
- }
-
- /*
- * Abort CRL validation and throw exception if there are any
- * unrecognized critical CRL entry extensions (see section
- * 5.3 of RFC 3280).
- */
- Set<String> unresCritExts = entry.getCriticalExtensionOIDs();
- if (unresCritExts != null && !unresCritExts.isEmpty()) {
- /* remove any that we will process */
- unresCritExts.remove
- (PKIXExtensions.ReasonCode_Id.toString());
- unresCritExts.remove
- (PKIXExtensions.CertificateIssuer_Id.toString());
- if (!unresCritExts.isEmpty()) {
- if (debug != null) {
- debug.println("Unrecognized "
- + "critical extension(s) in revoked CRL entry: "
- + unresCritExts);
- }
- throw new CertPathValidatorException
- ("Could not determine revocation status", null, null,
- -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
- }
- }
-
- reasonCode = entry.getRevocationReason();
- if (reasonCode == null) {
- reasonCode = CRLReason.UNSPECIFIED;
- }
- Throwable t = new CertificateRevokedException
- (entry.getRevocationDate(), reasonCode,
- crl.getIssuerX500Principal(), entry.getExtensions());
- throw new CertPathValidatorException(t.getMessage(), t,
- null, -1, BasicReason.REVOKED);
- }
- }
- }
-
- /**
- * We have a cert whose revocation status couldn't be verified by
- * a CRL issued by the cert that issued the CRL. See if we can
- * find a valid CRL issued by a separate key that can verify the
- * revocation status of this certificate.
- * <p>
- * Note that this does not provide support for indirect CRLs,
- * only CRLs signed with a different key (but the same issuer
- * name) as the certificate being checked.
- *
- * @param currCert the <code>X509Certificate</code> to be checked
- * @param prevKey the <code>PublicKey</code> that failed
- * @param signFlag <code>true</code> if that key was trusted to sign CRLs
- * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
- * whose revocation status depends on the
- * non-revoked status of this cert. To avoid
- * circular dependencies, we assume they're
- * revoked while checking the revocation
- * status of this cert.
- * @throws CertPathValidatorException if the cert's revocation status
- * cannot be verified successfully with another key
- */
- private void verifyWithSeparateSigningKey(X509Certificate currCert,
- PublicKey prevKey, boolean signFlag, Set<X509Certificate> stackedCerts)
- throws CertPathValidatorException {
- String msg = "revocation status";
- if (debug != null) {
- debug.println(
- "CrlRevocationChecker.verifyWithSeparateSigningKey()" +
- " ---checking " + msg + "...");
- }
-
- // reject circular dependencies - RFC 3280 is not explicit on how
- // to handle this, so we feel it is safest to reject them until
- // the issue is resolved in the PKIX WG.
- if ((stackedCerts != null) && stackedCerts.contains(currCert)) {
- if (debug != null) {
- debug.println(
- "CrlRevocationChecker.verifyWithSeparateSigningKey()" +
- " circular dependency");
- }
- throw new CertPathValidatorException
- ("Could not determine revocation status", null, null,
- -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
- }
-
- // If prevKey wasn't trusted, maybe we just didn't have the right
- // path to it. Don't rule that key out.
- if (!signFlag) {
- prevKey = null;
- }
-
- // Try to find another key that might be able to sign
- // CRLs vouching for this cert.
- buildToNewKey(currCert, prevKey, stackedCerts);
- }
-
- /**
- * Tries to find a CertPath that establishes a key that can be
- * used to verify the revocation status of a given certificate.
- * Ignores keys that have previously been tried. Throws a
- * CertPathValidatorException if no such key could be found.
- *
- * @param currCert the <code>X509Certificate</code> to be checked
- * @param prevKey the <code>PublicKey</code> of the certificate whose key
- * cannot be used to vouch for the CRL and should be ignored
- * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
- * whose revocation status depends on the
- * establishment of this path.
- * @throws CertPathValidatorException on failure
- */
- private void buildToNewKey(X509Certificate currCert,
- PublicKey prevKey, Set<X509Certificate> stackedCerts)
- throws CertPathValidatorException {
-
- if (debug != null) {
- debug.println("CrlRevocationChecker.buildToNewKey()" +
- " starting work");
- }
- Set<PublicKey> badKeys = new HashSet<PublicKey>();
- if (prevKey != null) {
- badKeys.add(prevKey);
- }
- X509CertSelector certSel = new RejectKeySelector(badKeys);
- certSel.setSubject(currCert.getIssuerX500Principal());
- certSel.setKeyUsage(mCrlSignUsage);
-
- Set<TrustAnchor> newAnchors =
- (mAnchor == null ? mParams.getTrustAnchors() :
- Collections.singleton(mAnchor));
-
- PKIXBuilderParameters builderParams;
- if (mParams instanceof PKIXBuilderParameters) {
- builderParams = (PKIXBuilderParameters) mParams.clone();
- builderParams.setTargetCertConstraints(certSel);
- // Policy qualifiers must be rejected, since we don't have
- // any way to convey them back to the application.
- builderParams.setPolicyQualifiersRejected(true);
- try {
- builderParams.setTrustAnchors(newAnchors);
- } catch (InvalidAlgorithmParameterException iape) {
- throw new RuntimeException(iape); // should never occur
- }
- } else {
- // It's unfortunate that there's no easy way to make a
- // PKIXBuilderParameters object from a PKIXParameters
- // object. This might miss some things if parameters
- // are added in the future or the validatorParams object
- // is a custom class derived from PKIXValidatorParameters.
- try {
- builderParams = new PKIXBuilderParameters(newAnchors, certSel);
- } catch (InvalidAlgorithmParameterException iape) {
- throw new RuntimeException(iape); // should never occur
- }
- builderParams.setInitialPolicies(mParams.getInitialPolicies());
- builderParams.setCertStores(mStores);
- builderParams.setExplicitPolicyRequired
- (mParams.isExplicitPolicyRequired());
- builderParams.setPolicyMappingInhibited
- (mParams.isPolicyMappingInhibited());
- builderParams.setAnyPolicyInhibited(mParams.isAnyPolicyInhibited());
- // Policy qualifiers must be rejected, since we don't have
- // any way to convey them back to the application.
- // That's the default, so no need to write code.
- builderParams.setDate(mParams.getDate());
- builderParams.setCertPathCheckers(mParams.getCertPathCheckers());
- builderParams.setSigProvider(mParams.getSigProvider());
- }
-
- // Skip revocation during this build to detect circular
- // references. But check revocation afterwards, using the
- // key (or any other that works).
- builderParams.setRevocationEnabled(false);
-
- // check for AuthorityInformationAccess extension
- if (Builder.USE_AIA == true) {
- X509CertImpl currCertImpl = null;
- try {
- currCertImpl = X509CertImpl.toImpl(currCert);
- } catch (CertificateException ce) {
- // ignore but log it
- if (debug != null) {
- debug.println("CrlRevocationChecker.buildToNewKey: " +
- "error decoding cert: " + ce);
- }
- }
- AuthorityInfoAccessExtension aiaExt = null;
- if (currCertImpl != null) {
- aiaExt = currCertImpl.getAuthorityInfoAccessExtension();
- }
- if (aiaExt != null) {
- List<AccessDescription> adList = aiaExt.getAccessDescriptions();
- if (adList != null) {
- for (AccessDescription ad : adList) {
- CertStore cs = URICertStore.getInstance(ad);
- if (cs != null) {
- if (debug != null) {
- debug.println("adding AIAext CertStore");
- }
- builderParams.addCertStore(cs);
- }
- }
- }
- }
- }
-
- CertPathBuilder builder = null;
- try {
- builder = CertPathBuilder.getInstance("PKIX");
- } catch (NoSuchAlgorithmException nsae) {
- throw new CertPathValidatorException(nsae);
- }
- while (true) {
- try {
- if (debug != null) {
- debug.println("CrlRevocationChecker.buildToNewKey()" +
- " about to try build ...");
- }
- PKIXCertPathBuilderResult cpbr =
- (PKIXCertPathBuilderResult) builder.build(builderParams);
-
- if (debug != null) {
- debug.println("CrlRevocationChecker.buildToNewKey()" +
- " about to check revocation ...");
- }
- // Now check revocation of all certs in path, assuming that
- // the stackedCerts are revoked.
- if (stackedCerts == null) {
- stackedCerts = new HashSet<X509Certificate>();
- }
- stackedCerts.add(currCert);
- TrustAnchor ta = cpbr.getTrustAnchor();
- PublicKey prevKey2 = ta.getCAPublicKey();
- if (prevKey2 == null) {
- prevKey2 = ta.getTrustedCert().getPublicKey();
- }
- boolean signFlag = true;
- List<? extends Certificate> cpList =
- cpbr.getCertPath().getCertificates();
- try {
- for (int i = cpList.size()-1; i >= 0; i-- ) {
- X509Certificate cert = (X509Certificate) cpList.get(i);
-
- if (debug != null) {
- debug.println("CrlRevocationChecker.buildToNewKey()"
- + " index " + i + " checking " + cert);
- }
- verifyRevocationStatus(cert, prevKey2, signFlag, true,
- stackedCerts, newAnchors);
- signFlag = certCanSignCrl(cert);
- prevKey2 = cert.getPublicKey();
- }
- } catch (CertPathValidatorException cpve) {
- // ignore it and try to get another key
- badKeys.add(cpbr.getPublicKey());
- continue;
- }
-
- if (debug != null) {
- debug.println("CrlRevocationChecker.buildToNewKey()" +
- " got key " + cpbr.getPublicKey());
- }
- // Now check revocation on the current cert using that key.
- // If it doesn't check out, try to find a different key.
- // And if we can't find a key, then return false.
- PublicKey newKey = cpbr.getPublicKey();
- try {
- verifyRevocationStatus(currCert, newKey, true, false);
- // If that passed, the cert is OK!
- return;
- } catch (CertPathValidatorException cpve) {
- // If it is revoked, rethrow exception
- if (cpve.getReason() == BasicReason.REVOKED) {
- throw cpve;
- }
- // Otherwise, ignore the exception and
- // try to get another key.
- }
- badKeys.add(newKey);
- } catch (InvalidAlgorithmParameterException iape) {
- throw new CertPathValidatorException(iape);
- } catch (CertPathBuilderException cpbe) {
- throw new CertPathValidatorException
- ("Could not determine revocation status", null, null,
- -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
- }
- }
- }
-
- /*
- * This inner class extends the X509CertSelector to add an additional
- * check to make sure the subject public key isn't on a particular list.
- * This class is used by buildToNewKey() to make sure the builder doesn't
- * end up with a CertPath to a public key that has already been rejected.
- */
- private static class RejectKeySelector extends X509CertSelector {
- private final Set<PublicKey> badKeySet;
-
- /**
- * Creates a new <code>RejectKeySelector</code>.
- *
- * @param badPublicKeys a <code>Set</code> of
- * <code>PublicKey</code>s that
- * should be rejected (or <code>null</code>
- * if no such check should be done)
- */
- RejectKeySelector(Set<PublicKey> badPublicKeys) {
- this.badKeySet = badPublicKeys;
- }
-
- /**
- * Decides whether a <code>Certificate</code> should be selected.
- *
- * @param cert the <code>Certificate</code> to be checked
- * @return <code>true</code> if the <code>Certificate</code> should be
- * selected, <code>false</code> otherwise
- */
- public boolean match(Certificate cert) {
- if (!super.match(cert))
- return(false);
-
- if (badKeySet.contains(cert.getPublicKey())) {
- if (debug != null)
- debug.println("RejectCertSelector.match: bad key");
- return false;
- }
-
- if (debug != null)
- debug.println("RejectCertSelector.match: returning true");
- return true;
- }
-
- /**
- * Return a printable representation of the <code>CertSelector</code>.
- *
- * @return a <code>String</code> describing the contents of the
- * <code>CertSelector</code>
- */
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("RejectCertSelector: [\n");
- sb.append(super.toString());
- sb.append(badKeySet);
- sb.append("]");
- return sb.toString();
- }
- }
-
- /**
- * Internal method that verifies a set of possible_crls,
- * and sees if each is approved, based on the cert.
- *
- * @param crls a set of possible CRLs to test for acceptability
- * @param cert the certificate whose revocation status is being checked
- * @param signFlag <code>true</code> if prevKey was trusted to sign CRLs
- * @param prevKey the public key of the issuer of cert
- * @param reasonsMask the reason code mask
- * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s>
- * @return a collection of approved crls (or an empty collection)
- */
- private Collection<X509CRL> verifyPossibleCRLs(Set<X509CRL> crls,
- X509Certificate cert, boolean signFlag, PublicKey prevKey,
- boolean[] reasonsMask,
- Set<TrustAnchor> trustAnchors) throws CertPathValidatorException {
-
- try {
- X509CertImpl certImpl = X509CertImpl.toImpl(cert);
- if (debug != null) {
- debug.println("CRLRevocationChecker.verifyPossibleCRLs: " +
- "Checking CRLDPs for "
- + certImpl.getSubjectX500Principal());
- }
- CRLDistributionPointsExtension ext =
- certImpl.getCRLDistributionPointsExtension();
- List<DistributionPoint> points = null;
- if (ext == null) {
- // assume a DP with reasons and CRLIssuer fields omitted
- // and a DP name of the cert issuer.
- // TODO add issuerAltName too
- X500Name certIssuer = (X500Name)certImpl.getIssuerDN();
- DistributionPoint point = new DistributionPoint
- (new GeneralNames().add(new GeneralName(certIssuer)),
- null, null);
- points = Collections.singletonList(point);
- } else {
- points = ext.get(CRLDistributionPointsExtension.POINTS);
- }
- Set<X509CRL> results = new HashSet<X509CRL>();
- DistributionPointFetcher dpf =
- DistributionPointFetcher.getInstance();
- for (Iterator<DistributionPoint> t = points.iterator();
- t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
- DistributionPoint point = t.next();
- for (X509CRL crl : crls) {
- if (dpf.verifyCRL(certImpl, point, crl, reasonsMask,
- signFlag, prevKey, mSigProvider,
- trustAnchors, mStores, mParams.getDate())) {
- results.add(crl);
- }
- }
- }
- return results;
- } catch (Exception e) {
- if (debug != null) {
- debug.println("Exception while verifying CRL: "+e.getMessage());
- e.printStackTrace();
- }
- return Collections.emptySet();
- }
- }
-}
--- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,14 +27,14 @@
import java.io.*;
import java.net.URI;
-import java.util.*;
import java.security.*;
import java.security.cert.*;
import javax.security.auth.x500.X500Principal;
+import java.util.*;
-import sun.security.action.GetBooleanAction;
import sun.security.util.Debug;
import sun.security.util.DerOutputStream;
+import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.*;
/**
@@ -58,44 +58,23 @@
{true, true, true, true, true, true, true, true, true};
/**
- * Flag indicating whether support for the CRL distribution point
- * extension shall be enabled. Currently disabled by default for
- * compatibility and legal reasons.
- */
- private final static boolean USE_CRLDP = AccessController.doPrivileged
- (new GetBooleanAction("com.sun.security.enableCRLDP"));
-
- // singleton instance
- private static final DistributionPointFetcher INSTANCE =
- new DistributionPointFetcher();
-
- /**
* Private instantiation only.
*/
private DistributionPointFetcher() {}
/**
- * Return a DistributionPointFetcher instance.
- */
- static DistributionPointFetcher getInstance() {
- return INSTANCE;
- }
-
- /**
* Return the X509CRLs matching this selector. The selector must be
* an X509CRLSelector with certificateChecking set.
- *
- * If CRLDP support is disabled, this method always returns an
- * empty set.
*/
- Collection<X509CRL> getCRLs(X509CRLSelector selector, boolean signFlag,
- PublicKey prevKey, String provider, List<CertStore> certStores,
- boolean[] reasonsMask, Set<TrustAnchor> trustAnchors,
- Date validity) throws CertStoreException {
-
- if (USE_CRLDP == false) {
- return Collections.emptySet();
- }
+ static Collection<X509CRL> getCRLs(X509CRLSelector selector,
+ boolean signFlag, PublicKey prevKey,
+ String provider,
+ List<CertStore> certStores,
+ boolean[] reasonsMask,
+ Set<TrustAnchor> trustAnchors,
+ Date validity)
+ throws CertStoreException
+ {
X509Certificate cert = selector.getCertificateChecking();
if (cert == null) {
return Collections.emptySet();
@@ -116,7 +95,7 @@
}
List<DistributionPoint> points =
ext.get(CRLDistributionPointsExtension.POINTS);
- Set<X509CRL> results = new HashSet<X509CRL>();
+ Set<X509CRL> results = new HashSet<>();
for (Iterator<DistributionPoint> t = points.iterator();
t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
DistributionPoint point = t.next();
@@ -129,9 +108,7 @@
debug.println("Returning " + results.size() + " CRLs");
}
return results;
- } catch (CertificateException e) {
- return Collections.emptySet();
- } catch (IOException e) {
+ } catch (CertificateException | IOException e) {
return Collections.emptySet();
}
}
@@ -140,7 +117,7 @@
* Download CRLs from the given distribution point, verify and return them.
* See the top of the class for current limitations.
*/
- private Collection<X509CRL> getCRLs(X509CRLSelector selector,
+ private static Collection<X509CRL> getCRLs(X509CRLSelector selector,
X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
boolean signFlag, PublicKey prevKey, String provider,
List<CertStore> certStores, Set<TrustAnchor> trustAnchors,
@@ -200,7 +177,7 @@
certStores, validity)) {
crls.add(crl);
}
- } catch (Exception e) {
+ } catch (IOException | CRLException e) {
// don't add the CRL
if (debug != null) {
debug.println("Exception verifying CRL: " + e.getMessage());
@@ -214,7 +191,7 @@
/**
* Download CRL from given URI.
*/
- private X509CRL getCRL(URIName name) {
+ private static X509CRL getCRL(URIName name) {
URI uri = name.getURI();
if (debug != null) {
debug.println("Trying to fetch CRL from DP " + uri);
@@ -240,7 +217,7 @@
/**
* Fetch CRLs from certStores.
*/
- private Collection<X509CRL> getCRLs(X500Name name,
+ private static Collection<X509CRL> getCRLs(X500Name name,
X500Principal certIssuer, List<CertStore> certStores)
{
if (debug != null) {
@@ -249,7 +226,7 @@
X509CRLSelector xcs = new X509CRLSelector();
xcs.addIssuer(name.asX500Principal());
xcs.addIssuer(certIssuer);
- Collection<X509CRL> crls = new ArrayList<X509CRL>();
+ Collection<X509CRL> crls = new ArrayList<>();
for (CertStore store : certStores) {
try {
for (CRL crl : store.getCRLs(xcs)) {
@@ -285,7 +262,7 @@
* certification path should be determined
* @return true if ok, false if not
*/
- boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
+ static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
X509CRL crl, boolean[] reasonsMask, boolean signFlag,
PublicKey prevKey, String provider,
Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
@@ -340,9 +317,9 @@
} else {
// in case of self-issued indirect CRL issuer.
byte[] certAKID = certImpl.getExtensionValue(
- PKIXExtensions.AuthorityKey_Id.toString());
+ AuthorityKey_Id.toString());
byte[] crlAKID = crlImpl.getExtensionValue(
- PKIXExtensions.AuthorityKey_Id.toString());
+ AuthorityKey_Id.toString());
if (certAKID == null || crlAKID == null) {
// cannot recognize indirect CRL without AKID
@@ -539,7 +516,7 @@
// verify that interim reasons mask includes one or more reasons
// not included in the reasons mask
boolean oneOrMore = false;
- for (int i=0; i < interimReasonsMask.length && !oneOrMore; i++) {
+ for (int i = 0; i < interimReasonsMask.length && !oneOrMore; i++) {
if (!reasonsMask[i] && interimReasonsMask[i]) {
oneOrMore = true;
}
@@ -615,7 +592,7 @@
PKIXCertPathBuilderResult result =
(PKIXCertPathBuilderResult) builder.build(params);
prevKey = result.getPublicKey();
- } catch (Exception e) {
+ } catch (GeneralSecurityException e) {
throw new CRLException(e);
}
}
@@ -633,7 +610,7 @@
// validate the signature on the CRL
try {
crl.verify(prevKey, provider);
- } catch (Exception e) {
+ } catch (GeneralSecurityException e) {
if (debug != null) {
debug.println("CRL signature failed to verify");
}
@@ -644,22 +621,21 @@
Set<String> unresCritExts = crl.getCriticalExtensionOIDs();
// remove any that we have processed
if (unresCritExts != null) {
- unresCritExts.remove
- (PKIXExtensions.IssuingDistributionPoint_Id.toString());
+ unresCritExts.remove(IssuingDistributionPoint_Id.toString());
if (!unresCritExts.isEmpty()) {
if (debug != null) {
debug.println("Unrecognized critical extension(s) in CRL: "
+ unresCritExts);
- Iterator<String> i = unresCritExts.iterator();
- while (i.hasNext())
- debug.println(i.next());
+ for (String ext : unresCritExts) {
+ debug.println(ext);
+ }
}
return false;
}
}
// update reasonsMask
- for (int i=0; i < interimReasonsMask.length; i++) {
+ for (int i = 0; i < interimReasonsMask.length; i++) {
if (!reasonsMask[i] && interimReasonsMask[i]) {
reasonsMask[i] = true;
}
@@ -671,9 +647,10 @@
* Append relative name to the issuer name and return a new
* GeneralNames object.
*/
- private GeneralNames getFullNames(X500Name issuer, RDN rdn)
- throws IOException {
- List<RDN> rdns = new ArrayList<RDN>(issuer.rdns());
+ private static GeneralNames getFullNames(X500Name issuer, RDN rdn)
+ throws IOException
+ {
+ List<RDN> rdns = new ArrayList<>(issuer.rdns());
rdns.add(rdn);
X500Name fullName = new X500Name(rdns.toArray(new RDN[0]));
GeneralNames fullNames = new GeneralNames();
@@ -681,15 +658,16 @@
return fullNames;
}
- /** Verifies whether a CRL is issued by a certain certificate
+ /**
+ * Verifies whether a CRL is issued by a certain certificate
*
* @param cert the certificate
* @param crl the CRL to be verified
* @param provider the name of the signature provider
*/
private static boolean issues(X509CertImpl cert, X509CRLImpl crl,
- String provider) throws IOException {
-
+ String provider) throws IOException
+ {
boolean matched = false;
AdaptableX509CertSelector issuerSelector =
@@ -727,7 +705,7 @@
try {
crl.verify(cert.getPublicKey(), provider);
matched = true;
- } catch (Exception e) {
+ } catch (GeneralSecurityException e) {
matched = false;
}
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Thu May 31 17:07:28 2012 -0400
@@ -26,10 +26,9 @@
package sun.security.provider.certpath;
import java.io.IOException;
-import java.util.*;
-
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
+import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.PKIXReason;
@@ -40,12 +39,14 @@
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.security.cert.X509CertSelector;
+import java.util.*;
import javax.security.auth.x500.X500Principal;
+import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug;
import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.PolicyMappingsExtension;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
@@ -72,21 +73,17 @@
TrustAnchor trustAnchor;
private Comparator<X509Certificate> comparator;
private boolean searchAllCertStores = true;
- private boolean onlyEECert = false;
/**
* Initialize the builder with the input parameters.
*
* @param params the parameter set used to build a certification path
*/
- ForwardBuilder(PKIXBuilderParameters buildParams,
- X500Principal targetSubjectDN, boolean searchAllCertStores,
- boolean onlyEECert)
- {
- super(buildParams, targetSubjectDN);
+ ForwardBuilder(BuilderParams buildParams, boolean searchAllCertStores) {
+ super(buildParams);
// populate sets of trusted certificates and subject DNs
- trustAnchors = buildParams.getTrustAnchors();
+ trustAnchors = buildParams.trustAnchors();
trustedCerts = new HashSet<X509Certificate>(trustAnchors.size());
trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size());
for (TrustAnchor anchor : trustAnchors) {
@@ -100,7 +97,6 @@
}
comparator = new PKIXCertComparator(trustedSubjectDNs);
this.searchAllCertStores = searchAllCertStores;
- this.onlyEECert = onlyEECert;
}
/**
@@ -112,8 +108,9 @@
* Must be an instance of <code>ForwardState</code>
* @param certStores list of CertStores
*/
- Collection<X509Certificate> getMatchingCerts
- (State currentState, List<CertStore> certStores)
+ @Override
+ Collection<X509Certificate> getMatchingCerts(State currentState,
+ List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException
{
if (debug != null) {
@@ -127,7 +124,7 @@
* As each cert is added, it is sorted based on the PKIXCertComparator
* algorithm.
*/
- Set<X509Certificate> certs = new TreeSet<X509Certificate>(comparator);
+ Set<X509Certificate> certs = new TreeSet<>(comparator);
/*
* Only look for EE certs if search has just started.
@@ -145,9 +142,10 @@
* and requirements specified in the parameters and PKIX state.
*/
private void getMatchingEECerts(ForwardState currentState,
- List<CertStore> certStores, Collection<X509Certificate> eeCerts)
- throws IOException {
-
+ List<CertStore> certStores,
+ Collection<X509Certificate> eeCerts)
+ throws IOException
+ {
if (debug != null) {
debug.println("ForwardBuilder.getMatchingEECerts()...");
}
@@ -165,12 +163,12 @@
/*
* Match on certificate validity date
*/
- eeSelector.setCertificateValid(date);
+ eeSelector.setCertificateValid(buildParams.date());
/*
* Policy processing optimizations
*/
- if (buildParams.isExplicitPolicyRequired()) {
+ if (buildParams.explicitPolicyRequired()) {
eeSelector.setPolicy(getMatchingPolicies());
}
/*
@@ -188,9 +186,10 @@
* and requirements specified in the parameters and PKIX state.
*/
private void getMatchingCACerts(ForwardState currentState,
- List<CertStore> certStores, Collection<X509Certificate> caCerts)
- throws IOException {
-
+ List<CertStore> certStores,
+ Collection<X509Certificate> caCerts)
+ throws IOException
+ {
if (debug != null) {
debug.println("ForwardBuilder.getMatchingCACerts()...");
}
@@ -216,8 +215,8 @@
}
if (caTargetSelector == null) {
- caTargetSelector = (X509CertSelector)
- targetCertConstraints.clone();
+ caTargetSelector =
+ (X509CertSelector) targetCertConstraints.clone();
/*
* Since we don't check the validity period of trusted
@@ -229,7 +228,7 @@
/*
* Policy processing optimizations
*/
- if (buildParams.isExplicitPolicyRequired())
+ if (buildParams.explicitPolicyRequired())
caTargetSelector.setPolicy(getMatchingPolicies());
}
@@ -249,7 +248,7 @@
/*
* Policy processing optimizations
*/
- if (buildParams.isExplicitPolicyRequired())
+ if (buildParams.explicitPolicyRequired())
caSelector.setPolicy(getMatchingPolicies());
}
@@ -278,7 +277,7 @@
* check the validity period
*/
caSelector.setValidityPeriod(currentState.cert.getNotBefore(),
- currentState.cert.getNotAfter());
+ currentState.cert.getNotAfter());
sel = caSelector;
}
@@ -307,7 +306,7 @@
* The trusted certificate matching is completed. We need to match
* on certificate validity date.
*/
- sel.setCertificateValid(date);
+ sel.setCertificateValid(buildParams.date());
/*
* Require CA certs with a pathLenConstraint that allows
@@ -323,11 +322,12 @@
* certificate pairs.
*/
if (currentState.isInitial() ||
- (buildParams.getMaxPathLength() == -1) ||
- (buildParams.getMaxPathLength() > currentState.traversedCACerts))
+ (buildParams.maxPathLength() == -1) ||
+ (buildParams.maxPathLength() > currentState.traversedCACerts))
{
if (addMatchingCerts(sel, certStores,
- caCerts, searchAllCertStores) && !searchAllCertStores) {
+ caCerts, searchAllCertStores)
+ && !searchAllCertStores) {
return;
}
}
@@ -356,7 +356,8 @@
// because of the selector, so the cast is safe
@SuppressWarnings("unchecked")
private boolean getCerts(AuthorityInfoAccessExtension aiaExt,
- Collection<X509Certificate> certs) {
+ Collection<X509Certificate> certs)
+ {
if (Builder.USE_AIA == false) {
return false;
}
@@ -449,6 +450,7 @@
* @throws ClassCastException if either argument is not of type
* X509Certificate
*/
+ @Override
public int compare(X509Certificate oCert1, X509Certificate oCert2) {
// if certs are the same, return 0
@@ -651,8 +653,10 @@
* @param currentState the current state against which the cert is verified
* @param certPathList the certPathList generated thus far
*/
+ @Override
void verifyCert(X509Certificate cert, State currentState,
- List<X509Certificate> certPathList) throws GeneralSecurityException
+ List<X509Certificate> certPathList)
+ throws GeneralSecurityException
{
if (debug != null) {
debug.println("ForwardBuilder.verifyCert(SN: "
@@ -686,7 +690,7 @@
debug.println("policyMappingFound = " + policyMappingFound);
}
if (cert.equals(cpListCert)) {
- if ((buildParams.isPolicyMappingInhibited()) ||
+ if ((buildParams.policyMappingInhibited()) ||
(!policyMappingFound)) {
if (debug != null) {
debug.println("loop detected!!");
@@ -721,7 +725,7 @@
* all extensions that all user checkers are capable of
* processing.
*/
- for (PKIXCertPathChecker checker : buildParams.getCertPathCheckers()) {
+ for (PKIXCertPathChecker checker : buildParams.certPathCheckers()) {
if (!checker.isForwardCheckingSupported()) {
Set<String> supportedExts = checker.getSupportedExtensions();
if (supportedExts != null) {
@@ -735,23 +739,15 @@
* to check. If there are any left, throw an exception!
*/
if (!unresCritExts.isEmpty()) {
- unresCritExts.remove(
- PKIXExtensions.BasicConstraints_Id.toString());
- unresCritExts.remove(
- PKIXExtensions.NameConstraints_Id.toString());
- unresCritExts.remove(
- PKIXExtensions.CertificatePolicies_Id.toString());
- unresCritExts.remove(
- PKIXExtensions.PolicyMappings_Id.toString());
- unresCritExts.remove(
- PKIXExtensions.PolicyConstraints_Id.toString());
- unresCritExts.remove(
- PKIXExtensions.InhibitAnyPolicy_Id.toString());
- unresCritExts.remove(
- PKIXExtensions.SubjectAlternativeName_Id.toString());
- unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
- unresCritExts.remove(
- PKIXExtensions.ExtendedKeyUsage_Id.toString());
+ unresCritExts.remove(BasicConstraints_Id.toString());
+ unresCritExts.remove(NameConstraints_Id.toString());
+ unresCritExts.remove(CertificatePolicies_Id.toString());
+ unresCritExts.remove(PolicyMappings_Id.toString());
+ unresCritExts.remove(PolicyConstraints_Id.toString());
+ unresCritExts.remove(InhibitAnyPolicy_Id.toString());
+ unresCritExts.remove(SubjectAlternativeName_Id.toString());
+ unresCritExts.remove(KeyUsage_Id.toString());
+ unresCritExts.remove(ExtendedKeyUsage_Id.toString());
if (!unresCritExts.isEmpty())
throw new CertPathValidatorException
@@ -789,31 +785,12 @@
*/
/*
- * Check revocation for the previous cert
- */
- if (buildParams.isRevocationEnabled()) {
-
- // first off, see if this cert can authorize revocation...
- if (CrlRevocationChecker.certCanSignCrl(cert)) {
- // And then check to be sure no key requiring key parameters
- // has been encountered
- if (!currState.keyParamsNeeded())
- // If all that checks out, we can check the
- // revocation status of the cert. Otherwise,
- // we'll just wait until the end.
- currState.crlChecker.check(currState.cert,
- cert.getPublicKey(),
- true);
- }
- }
-
- /*
* Check signature only if no key requiring key parameters has been
* encountered.
*/
if (!currState.keyParamsNeeded()) {
(currState.cert).verify(cert.getPublicKey(),
- buildParams.getSigProvider());
+ buildParams.sigProvider());
}
}
@@ -829,6 +806,7 @@
* @param cert the certificate to test
* @return a boolean value indicating whether the cert completes the path.
*/
+ @Override
boolean isPathCompleted(X509Certificate cert) {
for (TrustAnchor anchor : trustAnchors) {
if (anchor.getTrustedCert() != null) {
@@ -840,7 +818,7 @@
}
} else {
X500Principal principal = anchor.getCA();
- java.security.PublicKey publicKey = anchor.getCAPublicKey();
+ PublicKey publicKey = anchor.getCAPublicKey();
if (principal != null && publicKey != null &&
principal.equals(cert.getSubjectX500Principal())) {
@@ -859,21 +837,6 @@
}
}
- /* Check revocation if it is enabled */
- if (buildParams.isRevocationEnabled()) {
- try {
- CrlRevocationChecker crlChecker = new CrlRevocationChecker
- (anchor, buildParams, null, onlyEECert);
- crlChecker.check(cert, anchor.getCAPublicKey(), true);
- } catch (CertPathValidatorException cpve) {
- if (debug != null) {
- debug.println("ForwardBuilder.isPathCompleted() cpve");
- cpve.printStackTrace();
- }
- continue;
- }
- }
-
/*
* Check signature
*/
@@ -882,18 +845,17 @@
// parameters, yet there is no key to inherit the parameters
// from. This is probably such a rare case that it is not worth
// trying to detect the situation earlier.
- cert.verify(anchor.getCAPublicKey(),
- buildParams.getSigProvider());
+ cert.verify(anchor.getCAPublicKey(), buildParams.sigProvider());
} catch (InvalidKeyException ike) {
if (debug != null) {
debug.println("ForwardBuilder.isPathCompleted() invalid "
- + "DSA key found");
+ + "DSA key found");
}
continue;
- } catch (Exception e){
+ } catch (GeneralSecurityException e){
if (debug != null) {
debug.println("ForwardBuilder.isPathCompleted() " +
- "unexpected exception");
+ "unexpected exception");
e.printStackTrace();
}
continue;
@@ -911,8 +873,10 @@
* @param cert the certificate to be added
* @param certPathList the certification path list
*/
+ @Override
void addCertToPath(X509Certificate cert,
- LinkedList<X509Certificate> certPathList) {
+ LinkedList<X509Certificate> certPathList)
+ {
certPathList.addFirst(cert);
}
@@ -920,6 +884,7 @@
*
* @param certPathList the certification path list
*/
+ @Override
void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
certPathList.removeFirst();
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java Thu May 31 17:07:28 2012 -0400
@@ -34,7 +34,6 @@
import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.security.auth.x500.X500Principal;
@@ -76,8 +75,6 @@
/* Flag indicating if state is initial (path is just starting) */
private boolean init = true;
- /* the checker used for revocation status */
- public CrlRevocationChecker crlChecker;
/* the untrusted certificates checker */
UntrustedChecker untrustedChecker;
@@ -96,6 +93,7 @@
*
* @return boolean flag indicating if the state is initial (just starting)
*/
+ @Override
public boolean isInitial() {
return init;
}
@@ -107,6 +105,7 @@
* @return boolean true if key needing to inherit parameters has been
* encountered; false otherwise.
*/
+ @Override
public boolean keyParamsNeeded() {
return keyParamsNeededFlag;
}
@@ -114,23 +113,18 @@
/**
* Display state for debugging purposes
*/
+ @Override
public String toString() {
- StringBuffer sb = new StringBuffer();
- try {
- sb.append("State [");
- sb.append("\n issuerDN of last cert: " + issuerDN);
- sb.append("\n traversedCACerts: " + traversedCACerts);
- sb.append("\n init: " + String.valueOf(init));
- sb.append("\n keyParamsNeeded: "
- + String.valueOf(keyParamsNeededFlag));
- sb.append("\n subjectNamesTraversed: \n" + subjectNamesTraversed);
- sb.append("]\n");
- } catch (Exception e) {
- if (debug != null) {
- debug.println("ForwardState.toString() unexpected exception");
- e.printStackTrace();
- }
- }
+ StringBuilder sb = new StringBuilder();
+ sb.append("State [");
+ sb.append("\n issuerDN of last cert: ").append(issuerDN);
+ sb.append("\n traversedCACerts: ").append(traversedCACerts);
+ sb.append("\n init: ").append(String.valueOf(init));
+ sb.append("\n keyParamsNeeded: ").append
+ (String.valueOf(keyParamsNeededFlag));
+ sb.append("\n subjectNamesTraversed: \n").append
+ (subjectNamesTraversed);
+ sb.append("]\n");
return sb.toString();
}
@@ -150,12 +144,10 @@
* that supports forward checking and initialize the forwardCheckers
*/
forwardCheckers = new ArrayList<PKIXCertPathChecker>();
- if (certPathCheckers != null) {
- for (PKIXCertPathChecker checker : certPathCheckers) {
- if (checker.isForwardCheckingSupported()) {
- checker.init(true);
- forwardCheckers.add(checker);
- }
+ for (PKIXCertPathChecker checker : certPathCheckers) {
+ if (checker.isForwardCheckingSupported()) {
+ checker.init(true);
+ forwardCheckers.add(checker);
}
}
@@ -167,6 +159,7 @@
*
* @param cert the certificate which is used to update the state
*/
+ @Override
public void updateState(X509Certificate cert)
throws CertificateException, IOException, CertPathValidatorException {
@@ -211,13 +204,11 @@
if (subjAltNameExt != null) {
GeneralNames gNames = subjAltNameExt.get(
SubjectAlternativeNameExtension.SUBJECT_NAME);
- for (Iterator<GeneralName> t = gNames.iterator();
- t.hasNext(); ) {
- GeneralNameInterface gName = t.next().getName();
- subjectNamesTraversed.add(gName);
+ for (GeneralName gName : gNames.names()) {
+ subjectNamesTraversed.add(gName.getName());
}
}
- } catch (Exception e) {
+ } catch (IOException e) {
if (debug != null) {
debug.println("ForwardState.updateState() unexpected "
+ "exception");
@@ -239,6 +230,7 @@
* because some of them will
* not have their contents modified by subsequent calls to updateState.
*/
+ @Override
@SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
public Object clone() {
try {
--- a/jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, 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
@@ -180,7 +180,7 @@
if (cert.equals(oldEntry)) {
return;
}
- List<X509Certificate> list = new ArrayList<X509Certificate>(2);
+ List<X509Certificate> list = new ArrayList<>(2);
list.add(cert);
list.add((X509Certificate)oldEntry);
certSubjects.put(subject, list);
@@ -206,7 +206,7 @@
if (crl.equals(oldEntry)) {
return;
}
- List<X509CRL> list = new ArrayList<X509CRL>(2);
+ List<X509CRL> list = new ArrayList<>(2);
list.add(crl);
list.add((X509CRL)oldEntry);
crlIssuers.put(issuer, list);
@@ -234,19 +234,20 @@
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
+ @Override
public Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
throws CertStoreException {
// no selector means match all
if (selector == null) {
- Set<Certificate> matches = new HashSet<Certificate>();
+ Set<Certificate> matches = new HashSet<>();
matchX509Certs(new X509CertSelector(), matches);
matches.addAll(otherCertificates);
return matches;
}
if (selector instanceof X509CertSelector == false) {
- Set<Certificate> matches = new HashSet<Certificate>();
+ Set<Certificate> matches = new HashSet<>();
matchX509Certs(selector, matches);
for (Certificate cert : otherCertificates) {
if (selector.match(cert)) {
@@ -285,7 +286,7 @@
// See certSubjects javadoc.
@SuppressWarnings("unchecked")
List<X509Certificate> list = (List<X509Certificate>)entry;
- Set<X509Certificate> matches = new HashSet<X509Certificate>(16);
+ Set<X509Certificate> matches = new HashSet<>(16);
for (X509Certificate cert : list) {
if (x509Selector.match(cert)) {
matches.add(cert);
@@ -295,7 +296,7 @@
}
}
// cannot use index, iterate all
- Set<Certificate> matches = new HashSet<Certificate>(16);
+ Set<Certificate> matches = new HashSet<>(16);
matchX509Certs(x509Selector, matches);
return matches;
}
@@ -338,18 +339,19 @@
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
+ @Override
public Collection<CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException {
if (selector == null) {
- Set<CRL> matches = new HashSet<CRL>();
+ Set<CRL> matches = new HashSet<>();
matchX509CRLs(new X509CRLSelector(), matches);
matches.addAll(otherCRLs);
return matches;
}
if (selector instanceof X509CRLSelector == false) {
- Set<CRL> matches = new HashSet<CRL>();
+ Set<CRL> matches = new HashSet<>();
matchX509CRLs(selector, matches);
for (CRL crl : otherCRLs) {
if (selector.match(crl)) {
@@ -366,7 +368,7 @@
// see if the issuer is specified
Collection<X500Principal> issuers = x509Selector.getIssuers();
if (issuers != null) {
- HashSet<CRL> matches = new HashSet<CRL>(16);
+ HashSet<CRL> matches = new HashSet<>(16);
for (X500Principal issuer : issuers) {
Object entry = crlIssuers.get(issuer);
if (entry == null) {
@@ -390,7 +392,7 @@
return matches;
}
// cannot use index, iterate all
- Set<CRL> matches = new HashSet<CRL>(16);
+ Set<CRL> matches = new HashSet<>(16);
matchX509CRLs(x509Selector, matches);
return matches;
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -30,7 +30,7 @@
import java.security.cert.PKIXReason;
import sun.security.util.Debug;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
/**
* KeyChecker is a <code>PKIXCertPathChecker</code> that checks that the
@@ -45,33 +45,29 @@
class KeyChecker extends PKIXCertPathChecker {
private static final Debug debug = Debug.getInstance("certpath");
- // the index of keyCertSign in the boolean KeyUsage array
- private static final int keyCertSign = 5;
private final int certPathLen;
- private CertSelector targetConstraints;
+ private final CertSelector targetConstraints;
private int remainingCerts;
private Set<String> supportedExts;
/**
- * Default Constructor
+ * Creates a KeyChecker.
*
* @param certPathLen allowable cert path length
* @param targetCertSel a CertSelector object specifying the constraints
* on the target certificate
*/
- KeyChecker(int certPathLen, CertSelector targetCertSel)
- throws CertPathValidatorException
- {
+ KeyChecker(int certPathLen, CertSelector targetCertSel) {
this.certPathLen = certPathLen;
this.targetConstraints = targetCertSel;
- init(false);
}
/**
* Initializes the internal state of the checker from parameters
* specified in the constructor
*/
+ @Override
public void init(boolean forward) throws CertPathValidatorException {
if (!forward) {
remainingCerts = certPathLen;
@@ -81,16 +77,18 @@
}
}
- public final boolean isForwardCheckingSupported() {
+ @Override
+ public boolean isForwardCheckingSupported() {
return false;
}
+ @Override
public Set<String> getSupportedExtensions() {
if (supportedExts == null) {
- supportedExts = new HashSet<String>();
- supportedExts.add(PKIXExtensions.KeyUsage_Id.toString());
- supportedExts.add(PKIXExtensions.ExtendedKeyUsage_Id.toString());
- supportedExts.add(PKIXExtensions.SubjectAlternativeName_Id.toString());
+ supportedExts = new HashSet<String>(3);
+ supportedExts.add(KeyUsage_Id.toString());
+ supportedExts.add(ExtendedKeyUsage_Id.toString());
+ supportedExts.add(SubjectAlternativeName_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts);
}
return supportedExts;
@@ -102,20 +100,20 @@
*
* @param cert the Certificate
* @param unresolvedCritExts the unresolved critical extensions
- * @exception CertPathValidatorException Exception thrown if certificate
- * does not verify
+ * @throws CertPathValidatorException if certificate does not verify
*/
+ @Override
public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException
{
- X509Certificate currCert = (X509Certificate) cert;
+ X509Certificate currCert = (X509Certificate)cert;
remainingCerts--;
// if final certificate, check that target constraints are satisfied
if (remainingCerts == 0) {
- if ((targetConstraints != null) &&
- (targetConstraints.match(currCert) == false)) {
+ if (targetConstraints != null &&
+ targetConstraints.match(currCert) == false) {
throw new CertPathValidatorException("target certificate " +
"constraints check failed");
}
@@ -126,25 +124,26 @@
// remove the extensions that we have checked
if (unresCritExts != null && !unresCritExts.isEmpty()) {
- unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
- unresCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString());
- unresCritExts.remove(
- PKIXExtensions.SubjectAlternativeName_Id.toString());
+ unresCritExts.remove(KeyUsage_Id.toString());
+ unresCritExts.remove(ExtendedKeyUsage_Id.toString());
+ unresCritExts.remove(SubjectAlternativeName_Id.toString());
}
}
+ // the index of keyCertSign in the boolean KeyUsage array
+ private static final int KEY_CERT_SIGN = 5;
/**
- * Static method to verify that the key usage and extended key usage
- * extension in a CA cert. The key usage extension, if present, must
- * assert the keyCertSign bit. The extended key usage extension, if
- * present, must include anyExtendedKeyUsage.
+ * Verifies the key usage extension in a CA cert.
+ * The key usage extension, if present, must assert the keyCertSign bit.
+ * The extended key usage extension is not checked (see CR 4776794 for
+ * more information).
*/
static void verifyCAKeyUsage(X509Certificate cert)
throws CertPathValidatorException {
String msg = "CA key usage";
if (debug != null) {
debug.println("KeyChecker.verifyCAKeyUsage() ---checking " + msg
- + "...");
+ + "...");
}
boolean[] keyUsageBits = cert.getKeyUsage();
@@ -156,7 +155,7 @@
}
// throw an exception if the keyCertSign bit is not set
- if (!keyUsageBits[keyCertSign]) {
+ if (!keyUsageBits[KEY_CERT_SIGN]) {
throw new CertPathValidatorException
(msg + " check failed: keyCertSign bit is not set", null,
null, -1, PKIXReason.INVALID_KEY_USAGE);
@@ -164,7 +163,7 @@
if (debug != null) {
debug.println("KeyChecker.verifyCAKeyUsage() " + msg
- + " verified.");
+ + " verified.");
}
}
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,7 @@
import static sun.security.provider.certpath.OCSPResponse.*;
import sun.security.util.Debug;
+import sun.security.util.ObjectIdentifier;
import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension;
import sun.security.x509.GeneralName;
@@ -62,6 +63,9 @@
*/
public final class OCSP {
+ static final ObjectIdentifier NONCE_EXTENSION_OID =
+ ObjectIdentifier.newInternal(new int[]{ 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
+
private static final Debug debug = Debug.getInstance("certpath");
private static final int CONNECT_TIMEOUT = 15000; // 15 seconds
@@ -83,7 +87,7 @@
* encoding the OCSP Request or validating the OCSP Response
*/
public static RevocationStatus check(X509Certificate cert,
- X509Certificate issuerCert)
+ X509Certificate issuerCert)
throws IOException, CertPathValidatorException {
CertId certId = null;
URI responderURI = null;
@@ -95,16 +99,13 @@
("No OCSP Responder URI in certificate");
}
certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
- } catch (CertificateException ce) {
+ } catch (CertificateException | IOException e) {
throw new CertPathValidatorException
- ("Exception while encoding OCSPRequest", ce);
- } catch (IOException ioe) {
- throw new CertPathValidatorException
- ("Exception while encoding OCSPRequest", ioe);
+ ("Exception while encoding OCSPRequest", e);
}
OCSPResponse ocspResponse = check(Collections.singletonList(certId),
- responderURI, issuerCert, null);
- return (RevocationStatus) ocspResponse.getSingleResponse(certId);
+ responderURI, issuerCert, null, Collections.<Extension>emptyList());
+ return (RevocationStatus)ocspResponse.getSingleResponse(certId);
}
/**
@@ -123,22 +124,34 @@
* encoding the OCSP Request or validating the OCSP Response
*/
public static RevocationStatus check(X509Certificate cert,
- X509Certificate issuerCert, URI responderURI, X509Certificate
- responderCert, Date date)
- throws IOException, CertPathValidatorException {
+ X509Certificate issuerCert,
+ URI responderURI,
+ X509Certificate responderCert,
+ Date date)
+ throws IOException, CertPathValidatorException
+ {
+ return check(cert, issuerCert, responderURI, responderCert, date,
+ Collections.<Extension>emptyList());
+ }
+
+ // Called by com.sun.deploy.security.TrustDecider
+ public static RevocationStatus check(X509Certificate cert,
+ X509Certificate issuerCert,
+ URI responderURI,
+ X509Certificate responderCert,
+ Date date, List<Extension> extensions)
+ throws IOException, CertPathValidatorException
+ {
CertId certId = null;
try {
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
- } catch (CertificateException ce) {
+ } catch (CertificateException | IOException e) {
throw new CertPathValidatorException
- ("Exception while encoding OCSPRequest", ce);
- } catch (IOException ioe) {
- throw new CertPathValidatorException
- ("Exception while encoding OCSPRequest", ioe);
+ ("Exception while encoding OCSPRequest", e);
}
OCSPResponse ocspResponse = check(Collections.singletonList(certId),
- responderURI, responderCert, date);
+ responderURI, responderCert, date, extensions);
return (RevocationStatus) ocspResponse.getSingleResponse(certId);
}
@@ -157,12 +170,14 @@
* encoding the OCSP Request or validating the OCSP Response
*/
static OCSPResponse check(List<CertId> certIds, URI responderURI,
- X509Certificate responderCert, Date date)
- throws IOException, CertPathValidatorException {
-
+ X509Certificate responderCert, Date date,
+ List<Extension> extensions)
+ throws IOException, CertPathValidatorException
+ {
byte[] bytes = null;
+ OCSPRequest request = null;
try {
- OCSPRequest request = new OCSPRequest(certIds);
+ request = new OCSPRequest(certIds, extensions);
bytes = request.encodeBytes();
} catch (IOException ioe) {
throw new CertPathValidatorException
@@ -214,6 +229,8 @@
}
}
response = Arrays.copyOf(response, total);
+ } catch (IOException ioe) {
+ throw new NetworkFailureException(ioe);
} finally {
if (in != null) {
try {
@@ -233,33 +250,15 @@
OCSPResponse ocspResponse = null;
try {
- ocspResponse = new OCSPResponse(response, date, responderCert);
+ ocspResponse = new OCSPResponse(response);
} 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());
- }
- }
+ // verify the response
+ ocspResponse.verify(certIds, responderCert, date, request.getNonce());
+
return ocspResponse;
}
@@ -271,6 +270,7 @@
* @param cert the certificate
* @return the URI of the OCSP Responder, or null if not specified
*/
+ // Called by com.sun.deploy.security.TrustDecider
public static URI getResponderURI(X509Certificate cert) {
try {
return getResponderURI(X509CertImpl.toImpl(cert));
@@ -330,4 +330,12 @@
*/
Map<String, Extension> getSingleExtensions();
}
+
+ static class NetworkFailureException extends CertPathValidatorException {
+ private static final long serialVersionUID = 0l;
+
+ private NetworkFailureException(IOException ioe) {
+ super(ioe);
+ }
+ }
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java Tue May 29 14:56:48 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,446 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, 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.math.BigInteger;
-import java.util.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.Security;
-import java.security.cert.*;
-import java.security.cert.CertPathValidatorException.BasicReason;
-import java.net.URI;
-import java.net.URISyntaxException;
-import javax.security.auth.x500.X500Principal;
-
-import static sun.security.provider.certpath.OCSP.*;
-import sun.security.util.Debug;
-import sun.security.x509.*;
-
-/**
- * OCSPChecker is a <code>PKIXCertPathChecker</code> that uses the
- * Online Certificate Status Protocol (OCSP) as specified in RFC 2560
- * <a href="http://www.ietf.org/rfc/rfc2560.txt">
- * http://www.ietf.org/rfc/rfc2560.txt</a>.
- *
- * @author Ram Marti
- */
-class OCSPChecker extends PKIXCertPathChecker {
-
- static final String OCSP_ENABLE_PROP = "ocsp.enable";
- static final String OCSP_URL_PROP = "ocsp.responderURL";
- static final String OCSP_CERT_SUBJECT_PROP =
- "ocsp.responderCertSubjectName";
- static final String OCSP_CERT_ISSUER_PROP = "ocsp.responderCertIssuerName";
- static final String OCSP_CERT_NUMBER_PROP =
- "ocsp.responderCertSerialNumber";
-
- private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
- private static final Debug DEBUG = Debug.getInstance("certpath");
- private static final boolean dump = false;
-
- private int remainingCerts;
-
- private X509Certificate[] certs;
-
- private CertPath cp;
-
- private PKIXParameters pkixParams;
-
- private boolean onlyEECert = false;
-
- /**
- * Default Constructor
- *
- * @param certPath the X509 certification path
- * @param pkixParams the input PKIX parameter set
- * @throws CertPathValidatorException if OCSPChecker can not be created
- */
- OCSPChecker(CertPath certPath, PKIXParameters pkixParams)
- throws CertPathValidatorException {
- this(certPath, pkixParams, false);
- }
-
- OCSPChecker(CertPath certPath, PKIXParameters pkixParams, boolean onlyEECert)
- throws CertPathValidatorException {
-
- this.cp = certPath;
- this.pkixParams = pkixParams;
- this.onlyEECert = onlyEECert;
- List<? extends Certificate> tmp = cp.getCertificates();
- certs = tmp.toArray(new X509Certificate[tmp.size()]);
- init(false);
- }
-
- /**
- * Initializes the internal state of the checker from parameters
- * specified in the constructor
- */
- @Override
- public void init(boolean forward) throws CertPathValidatorException {
- if (!forward) {
- remainingCerts = certs.length + 1;
- } else {
- throw new CertPathValidatorException(
- "Forward checking not supported");
- }
- }
-
- @Override public boolean isForwardCheckingSupported() {
- return false;
- }
-
- @Override public Set<String> getSupportedExtensions() {
- return Collections.<String>emptySet();
- }
-
- /**
- * Sends an OCSPRequest for the certificate to the OCSP Server and
- * processes the response back from the OCSP Server.
- *
- * @param cert the Certificate
- * @param unresolvedCritExts the unresolved critical extensions
- * @exception CertPathValidatorException Exception is thrown if the
- * certificate has been revoked.
- */
- @Override
- public void check(Certificate cert, Collection<String> unresolvedCritExts)
- throws CertPathValidatorException {
-
- // Decrement the certificate counter
- remainingCerts--;
-
- X509CertImpl currCertImpl = null;
- try {
- currCertImpl = X509CertImpl.toImpl((X509Certificate)cert);
- } catch (CertificateException ce) {
- throw new CertPathValidatorException(ce);
- }
-
- if (onlyEECert && currCertImpl.getBasicConstraints() != -1) {
- if (DEBUG != null) {
- DEBUG.println("Skipping revocation check, not end entity cert");
- }
- return;
- }
-
- /*
- * OCSP security property values, in the following order:
- * 1. ocsp.responderURL
- * 2. ocsp.responderCertSubjectName
- * 3. ocsp.responderCertIssuerName
- * 4. ocsp.responderCertSerialNumber
- */
- // should cache these properties to avoid calling every time?
- String[] properties = getOCSPProperties();
-
- // Check whether OCSP is feasible before seeking cert information
- URI uri = getOCSPServerURI(currCertImpl, properties[0]);
-
- // When responder's subject name is set then the issuer/serial
- // properties are ignored
- X500Principal responderSubjectName = null;
- X500Principal responderIssuerName = null;
- BigInteger responderSerialNumber = null;
- if (properties[1] != null) {
- responderSubjectName = new X500Principal(properties[1]);
- } else if (properties[2] != null && properties[3] != null) {
- responderIssuerName = new X500Principal(properties[2]);
- // remove colon or space separators
- String value = stripOutSeparators(properties[3]);
- responderSerialNumber = new BigInteger(value, 16);
- } else if (properties[2] != null || properties[3] != null) {
- throw new CertPathValidatorException(
- "Must specify both ocsp.responderCertIssuerName and " +
- "ocsp.responderCertSerialNumber properties");
- }
-
- // If the OCSP responder cert properties are set then the
- // identified cert must be located in the trust anchors or
- // in the cert stores.
- boolean seekResponderCert = false;
- if (responderSubjectName != null || responderIssuerName != null) {
- seekResponderCert = true;
- }
-
- // Set the issuer certificate to the next cert in the chain
- // (unless we're processing the final cert).
- X509Certificate issuerCert = null;
- boolean seekIssuerCert = true;
- X509Certificate responderCert = null;
- if (remainingCerts < certs.length) {
- issuerCert = certs[remainingCerts];
- seekIssuerCert = false; // done
-
- // By default, the OCSP responder's cert is the same as the
- // issuer of the cert being validated.
- if (!seekResponderCert) {
- responderCert = issuerCert;
- if (DEBUG != null) {
- DEBUG.println("Responder's certificate is the same " +
- "as the issuer of the certificate being validated");
- }
- }
- }
-
- // Check anchor certs for:
- // - the issuer cert (of the cert being validated)
- // - the OCSP responder's cert
- if (seekIssuerCert || seekResponderCert) {
-
- if (DEBUG != null && seekResponderCert) {
- DEBUG.println("Searching trust anchors for responder's " +
- "certificate");
- }
-
- // Extract the anchor certs
- Iterator<TrustAnchor> anchors
- = pkixParams.getTrustAnchors().iterator();
- if (!anchors.hasNext()) {
- throw new CertPathValidatorException(
- "Must specify at least one trust anchor");
- }
-
- X500Principal certIssuerName =
- currCertImpl.getIssuerX500Principal();
- while (anchors.hasNext() && (seekIssuerCert || seekResponderCert)) {
-
- TrustAnchor anchor = anchors.next();
- X509Certificate anchorCert = anchor.getTrustedCert();
- X500Principal anchorSubjectName =
- anchorCert.getSubjectX500Principal();
-
- if (dump) {
- System.out.println("Issuer DN is " + certIssuerName);
- System.out.println("Subject DN is " + anchorSubjectName);
- }
-
- // Check if anchor cert is the issuer cert
- if (seekIssuerCert &&
- certIssuerName.equals(anchorSubjectName)) {
-
- issuerCert = anchorCert;
- seekIssuerCert = false; // done
-
- // By default, the OCSP responder's cert is the same as
- // the issuer of the cert being validated.
- if (!seekResponderCert && responderCert == null) {
- responderCert = anchorCert;
- if (DEBUG != null) {
- DEBUG.println("Responder's certificate is the" +
- " same as the issuer of the certificate " +
- "being validated");
- }
- }
- }
-
- // Check if anchor cert is the responder cert
- if (seekResponderCert) {
- // Satisfy the responder subject name property only, or
- // satisfy the responder issuer name and serial number
- // properties only
- if ((responderSubjectName != null &&
- responderSubjectName.equals(anchorSubjectName)) ||
- (responderIssuerName != null &&
- responderSerialNumber != null &&
- responderIssuerName.equals(
- anchorCert.getIssuerX500Principal()) &&
- responderSerialNumber.equals(
- anchorCert.getSerialNumber()))) {
-
- responderCert = anchorCert;
- seekResponderCert = false; // done
- }
- }
- }
- if (issuerCert == null) {
- throw new CertPathValidatorException(
- "No trusted certificate for " + currCertImpl.getIssuerDN());
- }
-
- // Check cert stores if responder cert has not yet been found
- if (seekResponderCert) {
- if (DEBUG != null) {
- DEBUG.println("Searching cert stores for responder's " +
- "certificate");
- }
- X509CertSelector filter = null;
- if (responderSubjectName != null) {
- filter = new X509CertSelector();
- filter.setSubject(responderSubjectName);
- } else if (responderIssuerName != null &&
- responderSerialNumber != null) {
- filter = new X509CertSelector();
- filter.setIssuer(responderIssuerName);
- filter.setSerialNumber(responderSerialNumber);
- }
- if (filter != null) {
- List<CertStore> certStores = pkixParams.getCertStores();
- for (CertStore certStore : certStores) {
- Iterator<? extends Certificate> i = null;
- try {
- i = certStore.getCertificates(filter).iterator();
- } catch (CertStoreException cse) {
- // ignore and try next certStore
- if (DEBUG != null) {
- DEBUG.println("CertStore exception:" + cse);
- }
- continue;
- }
- if (i.hasNext()) {
- responderCert = (X509Certificate) i.next();
- seekResponderCert = false; // done
- break;
- }
- }
- }
- }
- }
-
- // Could not find the certificate identified in the OCSP properties
- if (seekResponderCert) {
- throw new CertPathValidatorException(
- "Cannot find the responder's certificate " +
- "(set using the OCSP security properties).");
- }
-
- // The algorithm constraints of the OCSP trusted responder certificate
- // does not need to be checked in this code. The constraints will be
- // checked when the responder's certificate is validated.
-
- CertId certId = null;
- OCSPResponse response = null;
- try {
- certId = new CertId
- (issuerCert, currCertImpl.getSerialNumberObject());
- response = OCSP.check(Collections.singletonList(certId), uri,
- responderCert, pkixParams.getDate());
- } catch (Exception e) {
- if (e instanceof CertPathValidatorException) {
- throw (CertPathValidatorException) e;
- } else {
- // Wrap exceptions in CertPathValidatorException so that
- // we can fallback to CRLs, if enabled.
- throw new CertPathValidatorException(e);
- }
- }
-
- RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId);
- RevocationStatus.CertStatus certStatus = rs.getCertStatus();
- if (certStatus == RevocationStatus.CertStatus.REVOKED) {
- Throwable t = new CertificateRevokedException(
- rs.getRevocationTime(), rs.getRevocationReason(),
- responderCert.getSubjectX500Principal(),
- rs.getSingleExtensions());
- throw new CertPathValidatorException(t.getMessage(), t,
- null, -1, BasicReason.REVOKED);
- } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
- throw new CertPathValidatorException(
- "Certificate's revocation status is unknown", null, cp,
- remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
- }
- }
-
- /*
- * The OCSP security property values are in the following order:
- * 1. ocsp.responderURL
- * 2. ocsp.responderCertSubjectName
- * 3. ocsp.responderCertIssuerName
- * 4. ocsp.responderCertSerialNumber
- */
- private static URI getOCSPServerURI(X509CertImpl currCertImpl,
- String responderURL) throws CertPathValidatorException {
-
- if (responderURL != null) {
- try {
- return new URI(responderURL);
- } catch (URISyntaxException e) {
- throw new CertPathValidatorException(e);
- }
- }
-
- // Examine the certificate's AuthorityInfoAccess extension
- AuthorityInfoAccessExtension aia =
- currCertImpl.getAuthorityInfoAccessExtension();
- if (aia == null) {
- throw new CertPathValidatorException(
- "Must specify the location of an OCSP Responder");
- }
-
- List<AccessDescription> descriptions = aia.getAccessDescriptions();
- for (AccessDescription description : descriptions) {
- if (description.getAccessMethod().equals((Object)
- AccessDescription.Ad_OCSP_Id)) {
-
- GeneralName generalName = description.getAccessLocation();
- if (generalName.getType() == GeneralNameInterface.NAME_URI) {
- URIName uri = (URIName) generalName.getName();
- return uri.getURI();
- }
- }
- }
-
- throw new CertPathValidatorException(
- "Cannot find the location of the OCSP Responder");
- }
-
- /*
- * Retrieves the values of the OCSP security properties.
- */
- private static String[] getOCSPProperties() {
- final String[] properties = new String[4];
-
- AccessController.doPrivileged(
- new PrivilegedAction<Void>() {
- public Void run() {
- properties[0] = Security.getProperty(OCSP_URL_PROP);
- properties[1] =
- Security.getProperty(OCSP_CERT_SUBJECT_PROP);
- properties[2] =
- Security.getProperty(OCSP_CERT_ISSUER_PROP);
- properties[3] =
- Security.getProperty(OCSP_CERT_NUMBER_PROP);
- return null;
- }
- });
-
- return properties;
- }
-
- /*
- * Removes any non-hexadecimal characters from a string.
- */
- private static String stripOutSeparators(String value) {
- char[] chars = value.toCharArray();
- StringBuilder hexNumber = new StringBuilder();
- for (int i = 0; i < chars.length; i++) {
- if (HEX_DIGITS.indexOf(chars[i]) != -1) {
- hexNumber.append(chars[i]);
- }
- }
- return hexNumber.toString();
- }
-}
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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,8 +26,10 @@
package sun.security.provider.certpath;
import java.io.IOException;
+import java.security.cert.Extension;
import java.util.Collections;
import java.util.List;
+
import sun.misc.HexDumpEncoder;
import sun.security.util.*;
@@ -74,22 +76,29 @@
class OCSPRequest {
- private static final Debug debug = Debug.getInstance("certpath");
private static final boolean dump = false;
// List of request CertIds
private final List<CertId> certIds;
+ private final List<Extension> extensions;
+ private byte[] nonce;
/*
* Constructs an OCSPRequest. This constructor is used
* to construct an unsigned OCSP Request for a single user cert.
*/
OCSPRequest(CertId certId) {
- this.certIds = Collections.singletonList(certId);
+ this(Collections.singletonList(certId));
}
OCSPRequest(List<CertId> certIds) {
this.certIds = certIds;
+ this.extensions = Collections.<Extension>emptyList();
+ }
+
+ OCSPRequest(List<CertId> certIds, List<Extension> extensions) {
+ this.certIds = certIds;
+ this.extensions = extensions;
}
byte[] encodeBytes() throws IOException {
@@ -104,7 +113,20 @@
}
tmp.write(DerValue.tag_Sequence, requestsOut);
- // No extensions supported
+ if (!extensions.isEmpty()) {
+ DerOutputStream extOut = new DerOutputStream();
+ for (Extension ext : extensions) {
+ ext.encode(extOut);
+ if (ext.getId().equals(OCSP.NONCE_EXTENSION_OID.toString())) {
+ nonce = ext.getValue();
+ }
+ }
+ DerOutputStream extsOut = new DerOutputStream();
+ extsOut.write(DerValue.tag_Sequence, extOut);
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
+ true, (byte)2), extsOut);
+ }
+
DerOutputStream tbsRequest = new DerOutputStream();
tbsRequest.write(DerValue.tag_Sequence, tmp);
@@ -126,4 +148,8 @@
List<CertId> getCertIds() {
return certIds;
}
+
+ byte[] getNonce() {
+ return nonce;
+ }
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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.CRLReason;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+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 javax.security.auth.x500.X500Principal;
+
import sun.misc.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;
@@ -125,13 +129,10 @@
};
private static ResponseStatus[] rsvalues = ResponseStatus.values();
- private static final Debug DEBUG = Debug.getInstance("certpath");
+ private static final Debug debug = Debug.getInstance("certpath");
private static final boolean dump = false;
private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1});
- private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID =
- ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
-
private static final int CERT_STATUS_GOOD = 0;
private static final int CERT_STATUS_REVOKED = 1;
private static final int CERT_STATUS_UNKNOWN = 2;
@@ -143,9 +144,6 @@
// Object identifier for the OCSPSigning key purpose
private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
- private final ResponseStatus responseStatus;
- private final Map<CertId, SingleResponse> singleResponseMap;
-
// Maximum clock skew in milliseconds (15 minutes) allowed when checking
// validity of OCSP responses
private static final long MAX_CLOCK_SKEW = 900000;
@@ -153,14 +151,20 @@
// an array of all of the CRLReasons (used in SingleResponse)
private static CRLReason[] values = CRLReason.values();
+ private final ResponseStatus responseStatus;
+ private final Map<CertId, SingleResponse> singleResponseMap;
+ private final List<X509CertImpl> certs;
+ private final AlgorithmId sigAlgId;
+ private final byte[] signature;
+ private final byte[] tbsResponseData;
+ private final X500Principal responderName;
+ private final byte[] responderKey;
+ private final byte[] responseNonce;
+
/*
* Create an OCSP response from its ASN.1 DER encoding.
*/
- OCSPResponse(byte[] bytes, Date dateCheckedAgainst,
- X509Certificate responderCert)
- throws IOException, CertPathValidatorException {
-
- // OCSPResponse
+ OCSPResponse(byte[] bytes) throws IOException {
if (dump) {
HexDumpEncoder hexEnc = new HexDumpEncoder();
System.out.println("OCSPResponse bytes are...");
@@ -181,12 +185,19 @@
// unspecified responseStatus
throw new IOException("Unknown OCSPResponse status: " + status);
}
- if (DEBUG != null) {
- DEBUG.println("OCSP response status: " + responseStatus);
+ if (debug != null) {
+ debug.println("OCSP response status: " + responseStatus);
}
if (responseStatus != ResponseStatus.SUCCESSFUL) {
// no need to continue, responseBytes are not set.
singleResponseMap = Collections.emptyMap();
+ certs = Collections.<X509CertImpl>emptyList();
+ sigAlgId = null;
+ signature = null;
+ tbsResponseData = null;
+ responderName = null;
+ responderKey = null;
+ responseNonce = null;
return;
}
@@ -206,15 +217,15 @@
derIn = tmp.data;
ObjectIdentifier responseType = derIn.getOID();
if (responseType.equals((Object)OCSP_BASIC_RESPONSE_OID)) {
- if (DEBUG != null) {
- DEBUG.println("OCSP response type: basic");
+ if (debug != null) {
+ debug.println("OCSP response type: basic");
}
} else {
- if (DEBUG != null) {
- DEBUG.println("OCSP response type: " + responseType);
+ if (debug != null) {
+ debug.println("OCSP response type: " + responseType);
}
throw new IOException("Unsupported OCSP response type: " +
- responseType);
+ responseType);
}
// BasicOCSPResponse
@@ -229,7 +240,7 @@
DerValue responseData = seqTmp[0];
// Need the DER encoded ResponseData to verify the signature later
- byte[] responseDataDer = seqTmp[0].toByteArray();
+ tbsResponseData = seqTmp[0].toByteArray();
// tbsResponseData
if (responseData.tag != DerValue.tag_Sequence) {
@@ -257,12 +268,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);
+ responderName =
+ new X500Principal(new ByteArrayInputStream(seq.toByteArray()));
+ if (debug != null) {
+ debug.println("OCSP Responder name: " + responderName);
}
+ responderKey = null;
} else if (tag == KEY_TAG) {
- // Ignore, for now
+ responderKey = seq.getOctetString();
+ responderName = null;
} else {
throw new IOException("Bad encoding in responderID element of " +
"OCSP response: expected ASN.1 context specific tag 0 or 1");
@@ -270,57 +284,55 @@
// producedAt
seq = seqDerIn.getDerValue();
- if (DEBUG != null) {
+ if (debug != null) {
Date producedAtDate = seq.getGeneralizedTime();
- DEBUG.println("OCSP response produced at: " + producedAtDate);
+ debug.println("OCSP response produced at: " + producedAtDate);
}
// responses
DerValue[] singleResponseDer = seqDerIn.getSequence(1);
- singleResponseMap
- = new HashMap<CertId, SingleResponse>(singleResponseDer.length);
- if (DEBUG != null) {
- DEBUG.println("OCSP number of SingleResponses: "
- + singleResponseDer.length);
+ singleResponseMap = new HashMap<>(singleResponseDer.length);
+ if (debug != null) {
+ debug.println("OCSP number of SingleResponses: "
+ + singleResponseDer.length);
}
for (int i = 0; i < singleResponseDer.length; i++) {
- SingleResponse singleResponse
- = new SingleResponse(singleResponseDer[i]);
+ SingleResponse singleResponse =
+ new SingleResponse(singleResponseDer[i]);
singleResponseMap.put(singleResponse.getCertId(), singleResponse);
}
// responseExtensions
+ byte[] nonce = null;
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);
+ Extension ext = new Extension(responseExtDer[i]);
+ if (debug != null) {
+ debug.println("OCSP extension: " + ext);
}
- if (responseExtension.getExtensionId().equals((Object)
- OCSP_NONCE_EXTENSION_OID)) {
- /*
- ocspNonce =
- responseExtension[i].getExtensionValue();
- */
- } else if (responseExtension.isCritical()) {
+ // Only the NONCE extension is recognized
+ if (ext.getExtensionId().equals((Object)
+ OCSP.NONCE_EXTENSION_OID))
+ {
+ nonce = ext.getExtensionValue();
+ } else if (ext.isCritical()) {
throw new IOException(
"Unsupported OCSP critical extension: " +
- responseExtension.getExtensionId());
+ ext.getExtensionId());
}
}
}
}
+ responseNonce = nonce;
// signatureAlgorithmId
- AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]);
+ sigAlgId = AlgorithmId.parse(seqTmp[1]);
// signature
- byte[] signature = seqTmp[2].getBitString();
- X509CertImpl[] x509Certs = null;
+ signature = seqTmp[2].getBitString();
// if seq[3] is available , then it is a sequence of certificates
if (seqTmp.length > 3) {
@@ -330,30 +342,59 @@
throw new IOException("Bad encoding in certs element of " +
"OCSP response: expected ASN.1 context specific tag 0.");
}
- DerValue[] certs = seqCert.getData().getSequence(3);
- x509Certs = new X509CertImpl[certs.length];
+ DerValue[] derCerts = seqCert.getData().getSequence(3);
+ certs = new ArrayList<X509CertImpl>(derCerts.length);
try {
- for (int i = 0; i < certs.length; i++) {
- x509Certs[i] = new X509CertImpl(certs[i].toByteArray());
+ for (int i = 0; i < derCerts.length; i++) {
+ certs.add(new X509CertImpl(derCerts[i].toByteArray()));
}
} catch (CertificateException ce) {
throw new IOException("Bad encoding in X509 Certificate", ce);
}
+ } else {
+ certs = Collections.<X509CertImpl>emptyList();
}
+ }
+
+ void verify(List<CertId> certIds, X509Certificate responderCert,
+ Date date, byte[] nonce)
+ throws CertPathValidatorException
+ {
+ if (responseStatus != ResponseStatus.SUCCESSFUL) {
+ throw new CertPathValidatorException
+ ("OCSP response error: " + responseStatus);
+ }
+
+ // Check that the response includes a response for all of the
+ // certs that were supplied in the request
+ for (CertId certId : certIds) {
+ SingleResponse sr = 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());
+ }
+ }
+
// Check whether the cert returned by the responder is trusted
- if (x509Certs != null && x509Certs[0] != null) {
- X509CertImpl cert = x509Certs[0];
-
- // First check if the cert matches the responder cert which
- // was set locally.
+ if (!certs.isEmpty()) {
+ X509CertImpl cert = certs.get(0);
+ // First check if the cert matches the expected responder cert
if (cert.equals(responderCert)) {
// cert is trusted, now verify the signed response
// Next check if the cert was issued by the responder cert
// which was set locally.
} else if (cert.getIssuerX500Principal().equals(
- responderCert.getSubjectX500Principal())) {
+ responderCert.getSubjectX500Principal())) {
// Check for the OCSPSigning key purpose
try {
@@ -380,12 +421,12 @@
// check the validity
try {
- if (dateCheckedAgainst == null) {
+ if (date == null) {
cert.checkValidity();
} else {
- cert.checkValidity(dateCheckedAgainst);
+ cert.checkValidity(date);
}
- } catch (GeneralSecurityException e) {
+ } catch (CertificateException e) {
throw new CertPathValidatorException(
"Responder's certificate not within the " +
"validity period", e);
@@ -401,8 +442,8 @@
Extension noCheck =
cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
if (noCheck != null) {
- if (DEBUG != null) {
- DEBUG.println("Responder's certificate includes " +
+ if (debug != null) {
+ debug.println("Responder's certificate includes " +
"the extension id-pkix-ocsp-nocheck.");
}
} else {
@@ -433,15 +474,44 @@
// "jdk.certpath.disabledAlgorithms".
AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
- if (!verifyResponse(responseDataDer, responderCert,
- sigAlgId, signature)) {
+ if (!verifySignature(responderCert)) {
throw new CertPathValidatorException(
- "Error verifying OCSP Responder's signature");
+ "Error verifying OCSP Response's signature");
}
} else {
// Need responder's cert in order to verify the signature
throw new CertPathValidatorException(
- "Unable to verify OCSP Responder's signature");
+ "Unable to verify OCSP Response's signature");
+ }
+
+ // Check freshness of OCSPResponse
+ if (nonce != null) {
+ if (responseNonce != null && !Arrays.equals(nonce, responseNonce)) {
+ throw new CertPathValidatorException("Nonces don't match");
+ }
+ }
+
+ long now = (date == null) ? System.currentTimeMillis() : date.getTime();
+ Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
+ Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
+ for (SingleResponse sr : singleResponseMap.values()) {
+ if (debug != null) {
+ String until = "";
+ if (sr.nextUpdate != null) {
+ until = " until " + sr.nextUpdate;
+ }
+ debug.println("Response's validity interval is from " +
+ sr.thisUpdate + until);
+ }
+
+ // Check that the test date is within the validity interval
+ if ((sr.thisUpdate != null && nowPlusSkew.before(sr.thisUpdate)) ||
+ (sr.nextUpdate != null && nowMinusSkew.after(sr.nextUpdate)))
+ {
+ throw new CertPathValidatorException(
+ "Response is unreliable: its validity " +
+ "interval is out-of-date");
+ }
}
}
@@ -456,34 +526,31 @@
* Verify the signature of the OCSP response.
* The responder's cert is implicitly trusted.
*/
- private boolean verifyResponse(byte[] responseData, X509Certificate cert,
- AlgorithmId sigAlgId, byte[] signBytes)
+ private boolean verifySignature(X509Certificate cert)
throws CertPathValidatorException {
try {
Signature respSignature = Signature.getInstance(sigAlgId.getName());
respSignature.initVerify(cert);
- respSignature.update(responseData);
+ respSignature.update(tbsResponseData);
- if (respSignature.verify(signBytes)) {
- if (DEBUG != null) {
- DEBUG.println("Verified signature of OCSP Responder");
+ if (respSignature.verify(signature)) {
+ if (debug != null) {
+ debug.println("Verified signature of OCSP Response");
}
return true;
} else {
- if (DEBUG != null) {
- DEBUG.println(
- "Error verifying signature of OCSP Responder");
+ if (debug != null) {
+ debug.println(
+ "Error verifying signature of OCSP Response");
}
return false;
}
- } catch (InvalidKeyException ike) {
- throw new CertPathValidatorException(ike);
- } catch (NoSuchAlgorithmException nsae) {
- throw new CertPathValidatorException(nsae);
- } catch (SignatureException se) {
- throw new CertPathValidatorException(se);
+ } catch (InvalidKeyException | NoSuchAlgorithmException |
+ SignatureException e)
+ {
+ throw new CertPathValidatorException(e);
}
}
@@ -537,9 +604,9 @@
revocationReason = CRLReason.UNSPECIFIED;
}
// RevokedInfo
- if (DEBUG != null) {
- DEBUG.println("Revocation time: " + revocationTime);
- DEBUG.println("Revocation reason: " + revocationReason);
+ if (debug != null) {
+ debug.println("Revocation time: " + revocationTime);
+ debug.println("Revocation reason: " + revocationReason);
}
} else {
revocationTime = null;
@@ -585,8 +652,8 @@
(singleExtDer.length);
for (int i = 0; i < singleExtDer.length; i++) {
Extension ext = new Extension(singleExtDer[i]);
- if (DEBUG != null) {
- DEBUG.println("OCSP single extension: " + ext);
+ if (debug != null) {
+ debug.println("OCSP single extension: " + ext);
}
// We don't support any extensions yet. Therefore, if it
// is critical we must throw an exception because we
@@ -604,29 +671,6 @@
} else {
singleExtensions = Collections.emptyMap();
}
-
- long now = System.currentTimeMillis();
- Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
- Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
- if (DEBUG != null) {
- String until = "";
- if (nextUpdate != null) {
- until = " until " + nextUpdate;
- }
- DEBUG.println("Response's validity interval is from " +
- thisUpdate + until);
- }
- // Check that the test date is within the validity interval
- if ((thisUpdate != null && nowPlusSkew.before(thisUpdate)) ||
- (nextUpdate != null && nowMinusSkew.after(nextUpdate))) {
-
- if (DEBUG != null) {
- DEBUG.println("Response is unreliable: its validity " +
- "interval is out-of-date");
- }
- throw new IOException("Response is unreliable: its validity " +
- "interval is out-of-date");
- }
}
/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIX.java Thu May 31 17:07:28 2012 -0400
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2012, 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.KeyStore;
+import java.security.cert.*;
+import java.util.*;
+import javax.security.auth.x500.X500Principal;
+
+import sun.security.util.Debug;
+
+/**
+ * Common utility methods and classes used by the PKIX CertPathValidator and
+ * CertPathBuilder implementation.
+ */
+class PKIX {
+
+ private static final Debug debug = Debug.getInstance("certpath");
+
+ private PKIX() { }
+
+ static ValidatorParams checkParams(CertPath cp, CertPathParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ if (!(params instanceof PKIXParameters)) {
+ throw new InvalidAlgorithmParameterException("inappropriate "
+ + "params, must be an instance of PKIXParameters");
+ }
+ return new ValidatorParams(cp, (PKIXParameters)params);
+ }
+
+ static BuilderParams checkBuilderParams(CertPathParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ if (!(params instanceof PKIXBuilderParameters)) {
+ throw new InvalidAlgorithmParameterException("inappropriate "
+ + "params, must be an instance of PKIXBuilderParameters");
+ }
+ return new BuilderParams((PKIXBuilderParameters)params);
+ }
+
+ /**
+ * PKIXParameters that are shared by the PKIX CertPathValidator
+ * implementation. Provides additional functionality and avoids
+ * unnecessary cloning.
+ */
+ static class ValidatorParams {
+ private final PKIXParameters params;
+ private CertPath certPath;
+ private List<PKIXCertPathChecker> checkers;
+ private List<CertStore> stores;
+ private boolean gotDate;
+ private Date date;
+ private Set<String> policies;
+ private boolean gotConstraints;
+ private CertSelector constraints;
+ private Set<TrustAnchor> anchors;
+ private List<X509Certificate> certs;
+
+ ValidatorParams(CertPath cp, PKIXParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ this(params);
+ if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {
+ throw new InvalidAlgorithmParameterException("inappropriate "
+ + "CertPath type specified, must be X.509 or X509");
+ }
+ this.certPath = cp;
+ }
+
+ ValidatorParams(PKIXParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ this.anchors = params.getTrustAnchors();
+ // Make sure that none of the trust anchors include name constraints
+ // (not supported).
+ for (TrustAnchor anchor : this.anchors) {
+ if (anchor.getNameConstraints() != null) {
+ throw new InvalidAlgorithmParameterException
+ ("name constraints in trust anchor not supported");
+ }
+ }
+ this.params = params;
+ }
+
+ CertPath certPath() {
+ return certPath;
+ }
+ // called by CertPathBuilder after path has been built
+ void setCertPath(CertPath cp) {
+ this.certPath = cp;
+ }
+ List<X509Certificate> certificates() {
+ if (certs == null) {
+ if (certPath == null) {
+ certs = Collections.emptyList();
+ } else {
+ // Reverse the ordering for validation so that the target
+ // cert is the last certificate
+ @SuppressWarnings("unchecked")
+ List<X509Certificate> xc = new ArrayList<>
+ ((List<X509Certificate>)certPath.getCertificates());
+ Collections.reverse(xc);
+ certs = xc;
+ }
+ }
+ return certs;
+ }
+ List<PKIXCertPathChecker> certPathCheckers() {
+ if (checkers == null)
+ checkers = params.getCertPathCheckers();
+ return checkers;
+ }
+ List<CertStore> certStores() {
+ if (stores == null)
+ stores = params.getCertStores();
+ return stores;
+ }
+ Date date() {
+ if (!gotDate) {
+ date = params.getDate();
+ if (date == null)
+ date = new Date();
+ gotDate = true;
+ }
+ return date;
+ }
+ Set<String> initialPolicies() {
+ if (policies == null)
+ policies = params.getInitialPolicies();
+ return policies;
+ }
+ CertSelector targetCertConstraints() {
+ if (!gotConstraints) {
+ constraints = params.getTargetCertConstraints();
+ gotConstraints = true;
+ }
+ return constraints;
+ }
+ Set<TrustAnchor> trustAnchors() {
+ return anchors;
+ }
+ boolean revocationEnabled() {
+ return params.isRevocationEnabled();
+ }
+ boolean policyMappingInhibited() {
+ return params.isPolicyMappingInhibited();
+ }
+ boolean explicitPolicyRequired() {
+ return params.isExplicitPolicyRequired();
+ }
+ boolean policyQualifiersRejected() {
+ return params.getPolicyQualifiersRejected();
+ }
+ String sigProvider() { return params.getSigProvider(); }
+ boolean anyPolicyInhibited() { return params.isAnyPolicyInhibited(); }
+
+ // in rare cases we need access to the original params, for example
+ // in order to clone CertPathCheckers before building a new chain
+ PKIXParameters getPKIXParameters() {
+ return params;
+ }
+ }
+
+ static class BuilderParams extends ValidatorParams {
+ private PKIXBuilderParameters params;
+ private boolean buildForward = true;
+ private List<CertStore> stores;
+ private X500Principal targetSubject;
+
+ BuilderParams(PKIXBuilderParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ super(params);
+ checkParams(params);
+ }
+ private void checkParams(PKIXBuilderParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ CertSelector sel = targetCertConstraints();
+ if (!(sel instanceof X509CertSelector)) {
+ throw new InvalidAlgorithmParameterException("the "
+ + "targetCertConstraints parameter must be an "
+ + "X509CertSelector");
+ }
+ if (params instanceof SunCertPathBuilderParameters) {
+ buildForward =
+ ((SunCertPathBuilderParameters)params).getBuildForward();
+ }
+ this.params = params;
+ this.targetSubject = getTargetSubject(
+ certStores(), (X509CertSelector)targetCertConstraints());
+ }
+ @Override List<CertStore> certStores() {
+ if (stores == null) {
+ // reorder CertStores so that local CertStores are tried first
+ stores = new ArrayList<>(params.getCertStores());
+ Collections.sort(stores, new CertStoreComparator());
+ }
+ return stores;
+ }
+ int maxPathLength() { return params.getMaxPathLength(); }
+ boolean buildForward() { return buildForward; }
+ PKIXBuilderParameters params() { return params; }
+ X500Principal targetSubject() { return targetSubject; }
+
+ /**
+ * Returns the target subject DN from the first X509Certificate that
+ * is fetched that matches the specified X509CertSelector.
+ */
+ private static X500Principal getTargetSubject(List<CertStore> stores,
+ X509CertSelector sel)
+ throws InvalidAlgorithmParameterException
+ {
+ X500Principal subject = sel.getSubject();
+ if (subject != null) {
+ return subject;
+ }
+ X509Certificate cert = sel.getCertificate();
+ if (cert != null) {
+ subject = cert.getSubjectX500Principal();
+ }
+ if (subject != null) {
+ return subject;
+ }
+ for (CertStore store : stores) {
+ try {
+ Collection<? extends Certificate> certs =
+ (Collection<? extends Certificate>)
+ store.getCertificates(sel);
+ if (!certs.isEmpty()) {
+ X509Certificate xc =
+ (X509Certificate)certs.iterator().next();
+ return xc.getSubjectX500Principal();
+ }
+ } catch (CertStoreException e) {
+ // ignore but log it
+ if (debug != null) {
+ debug.println("BuilderParams.getTargetSubjectDN: " +
+ "non-fatal exception retrieving certs: " + e);
+ e.printStackTrace();
+ }
+ }
+ }
+ throw new InvalidAlgorithmParameterException
+ ("Could not determine unique target subject");
+ }
+ }
+
+ /**
+ * Comparator that orders CertStores so that local CertStores come before
+ * remote CertStores.
+ */
+ private static class CertStoreComparator implements Comparator<CertStore> {
+ @Override
+ public int compare(CertStore store1, CertStore store2) {
+ if (store1.getType().equals("Collection") ||
+ store1.getCertStoreParameters() instanceof
+ CollectionCertStoreParameters) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ }
+}
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Thu May 31 17:07:28 2012 -0400
@@ -25,55 +25,38 @@
package sun.security.provider.certpath;
-import java.security.AccessController;
+import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
-import java.security.cert.CertPath;
-import java.security.cert.CertPathParameters;
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertPathValidatorSpi;
-import java.security.cert.CertPathValidatorResult;
-import java.security.cert.PKIXCertPathChecker;
-import java.security.cert.PKIXCertPathValidatorResult;
-import java.security.cert.PKIXParameters;
-import java.security.cert.PKIXReason;
-import java.security.cert.PolicyNode;
-import java.security.cert.TrustAnchor;
-import java.security.cert.X509Certificate;
-import java.util.Collections;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Set;
-import sun.security.action.GetBooleanSecurityPropertyAction;
+import java.security.cert.*;
+import java.util.*;
+
+import sun.security.provider.certpath.PKIX.ValidatorParams;
+import sun.security.x509.X509CertImpl;
import sun.security.util.Debug;
-import sun.security.x509.X509CertImpl;
-
-
/**
* This class implements the PKIX validation algorithm for certification
* paths consisting exclusively of <code>X509Certificates</code>. It uses
* the specified input parameter set (which must be a
- * <code>PKIXParameters</code> object) and signature provider (if any).
+ * <code>PKIXParameters</code> object).
*
* @since 1.4
* @author Yassir Elley
*/
-public class PKIXCertPathValidator extends CertPathValidatorSpi {
+public final class PKIXCertPathValidator extends CertPathValidatorSpi {
private static final Debug debug = Debug.getInstance("certpath");
- private Date testDate;
- private List<PKIXCertPathChecker> userCheckers;
- private String sigProvider;
- private BasicChecker basicChecker;
- private boolean ocspEnabled = false;
- private boolean onlyEECert = false;
/**
* Default constructor.
*/
public PKIXCertPathValidator() {}
+ @Override
+ public CertPathChecker engineGetRevocationChecker() {
+ return new RevocationChecker();
+ }
+
/**
* Validates a certification path consisting exclusively of
* <code>X509Certificate</code>s using the PKIX validation algorithm,
@@ -81,98 +64,70 @@
* The input parameter set must be a <code>PKIXParameters</code> object.
*
* @param cp the X509 certification path
- * @param param the input PKIX parameter set
+ * @param params the input PKIX parameter set
* @return the result
- * @exception CertPathValidatorException Exception thrown if cert path
- * does not validate.
- * @exception InvalidAlgorithmParameterException if the specified
- * parameters are inappropriate for this certification path validator
+ * @throws CertPathValidatorException if cert path does not validate.
+ * @throws InvalidAlgorithmParameterException if the specified
+ * parameters are inappropriate for this CertPathValidator
*/
+ @Override
public CertPathValidatorResult engineValidate(CertPath cp,
- CertPathParameters param)
+ CertPathParameters params)
throws CertPathValidatorException, InvalidAlgorithmParameterException
{
+ ValidatorParams valParams = PKIX.checkParams(cp, params);
+ return validate(valParams);
+ }
+
+ private static PKIXCertPathValidatorResult validate(ValidatorParams params)
+ throws CertPathValidatorException
+ {
if (debug != null)
debug.println("PKIXCertPathValidator.engineValidate()...");
- if (!(param instanceof PKIXParameters)) {
- throw new InvalidAlgorithmParameterException("inappropriate "
- + "parameters, must be an instance of PKIXParameters");
- }
-
- if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {
- throw new InvalidAlgorithmParameterException("inappropriate "
- + "certification path type specified, must be X.509 or X509");
- }
-
- PKIXParameters pkixParam = (PKIXParameters) param;
-
- // Make sure that none of the trust anchors include name constraints
- // (not supported).
- Set<TrustAnchor> anchors = pkixParam.getTrustAnchors();
- for (TrustAnchor anchor : anchors) {
- if (anchor.getNameConstraints() != null) {
- throw new InvalidAlgorithmParameterException
- ("name constraints in trust anchor not supported");
- }
- }
-
- // the certpath which has been passed in (cp)
- // has the target cert as the first certificate - we
- // need to keep this cp so we can return it
- // in case of an exception and for policy qualifier
- // processing - however, for certpath validation,
- // we need to create a reversed path, where we reverse the
- // ordering so that the target cert is the last certificate
-
- // Must copy elements of certList into a new modifiable List before
- // calling Collections.reverse().
- // If cp is not an X.509 or X509 certpath, an
- // InvalidAlgorithmParameterException will have been thrown by now.
- @SuppressWarnings("unchecked")
- ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>
- ((List<X509Certificate>)cp.getCertificates());
- if (debug != null) {
- if (certList.isEmpty()) {
- debug.println("PKIXCertPathValidator.engineValidate() "
- + "certList is empty");
- }
- debug.println("PKIXCertPathValidator.engineValidate() "
- + "reversing certpath...");
- }
- Collections.reverse(certList);
-
- // now certList has the target cert as the last cert and we
- // can proceed with normal validation
-
- populateVariables(pkixParam);
-
// Retrieve the first certificate in the certpath
// (to be used later in pre-screening)
- X509Certificate firstCert = null;
+ AdaptableX509CertSelector selector = null;
+ List<X509Certificate> certList = params.certificates();
if (!certList.isEmpty()) {
- firstCert = certList.get(0);
+ selector = new AdaptableX509CertSelector();
+ X509Certificate firstCert = certList.get(0);
+ // check trusted certificate's subject
+ selector.setSubject(firstCert.getIssuerX500Principal());
+ // check the validity period
+ selector.setValidityPeriod(firstCert.getNotBefore(),
+ firstCert.getNotAfter());
+ /*
+ * Facilitate certification path construction with authority
+ * key identifier and subject key identifier.
+ */
+ try {
+ X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert);
+ selector.parseAuthorityKeyIdentifierExtension(
+ firstCertImpl.getAuthorityKeyIdentifierExtension());
+ } catch (CertificateException | IOException e) {
+ // ignore
+ }
}
CertPathValidatorException lastException = null;
// We iterate through the set of trust anchors until we find
// one that works at which time we stop iterating
- for (TrustAnchor anchor : anchors) {
+ for (TrustAnchor anchor : params.trustAnchors()) {
X509Certificate trustedCert = anchor.getTrustedCert();
if (trustedCert != null) {
- if (debug != null) {
- debug.println("PKIXCertPathValidator.engineValidate() "
- + "anchor.getTrustedCert() != null");
- }
-
// if this trust anchor is not worth trying,
// we move on to the next one
- if (!isWorthTrying(trustedCert, firstCert)) {
+ if (selector != null && !selector.match(trustedCert)) {
+ if (debug != null) {
+ debug.println("NO - don't try this trustedCert");
+ }
continue;
}
if (debug != null) {
+ debug.println("YES - try this trustedCert");
debug.println("anchor.getTrustedCert()."
+ "getSubjectX500Principal() = "
+ trustedCert.getSubjectX500Principal());
@@ -185,14 +140,7 @@
}
try {
- PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
- PolicyChecker.ANY_POLICY, null, false,
- Collections.singleton(PolicyChecker.ANY_POLICY), false);
- PolicyNode policyTree =
- doValidate(anchor, cp, certList, pkixParam, rootNode);
- // if this anchor works, return success
- return new PKIXCertPathValidatorResult(anchor, policyTree,
- basicChecker.getPublicKey());
+ return validate(anchor, params);
} catch (CertPathValidatorException cpe) {
// remember this exception
lastException = cpe;
@@ -210,146 +158,60 @@
null, null, -1, PKIXReason.NO_TRUST_ANCHOR);
}
- /**
- * Internal method to do some simple checks to see if a given cert is
- * worth trying to validate in the chain.
- */
- private boolean isWorthTrying(X509Certificate trustedCert,
- X509Certificate firstCert) {
-
- boolean worthy = false;
-
- if (debug != null) {
- debug.println("PKIXCertPathValidator.isWorthTrying() checking "
- + "if this trusted cert is worth trying ...");
- }
-
- if (firstCert == null) {
- return true;
- }
-
- AdaptableX509CertSelector issuerSelector =
- new AdaptableX509CertSelector();
-
- // check trusted certificate's subject
- issuerSelector.setSubject(firstCert.getIssuerX500Principal());
+ private static PKIXCertPathValidatorResult validate(TrustAnchor anchor,
+ ValidatorParams params)
+ throws CertPathValidatorException
+ {
+ int certPathLen = params.certificates().size();
- // check the validity period
- issuerSelector.setValidityPeriod(firstCert.getNotBefore(),
- firstCert.getNotAfter());
+ // create PKIXCertPathCheckers
+ List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
+ // add standard checkers that we will be using
+ certPathCheckers.add(new UntrustedChecker());
+ certPathCheckers.add(new AlgorithmChecker(anchor));
+ certPathCheckers.add(new KeyChecker(certPathLen,
+ params.targetCertConstraints()));
+ certPathCheckers.add(new ConstraintsChecker(certPathLen));
+ PolicyNodeImpl rootNode =
+ new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null, false,
+ Collections.singleton(PolicyChecker.ANY_POLICY),
+ false);
+ PolicyChecker pc = new PolicyChecker(params.initialPolicies(),
+ certPathLen,
+ params.explicitPolicyRequired(),
+ params.policyMappingInhibited(),
+ params.anyPolicyInhibited(),
+ params.policyQualifiersRejected(),
+ rootNode);
+ certPathCheckers.add(pc);
+ // default value for date is current time
+ BasicChecker bc = new BasicChecker(anchor, params.date(),
+ params.sigProvider(), false);
+ certPathCheckers.add(bc);
- /*
- * Facilitate certification path construction with authority
- * key identifier and subject key identifier.
- */
- try {
- X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert);
- issuerSelector.parseAuthorityKeyIdentifierExtension(
- firstCertImpl.getAuthorityKeyIdentifierExtension());
-
- worthy = issuerSelector.match(trustedCert);
- } catch (Exception e) {
- // It is not worth trying.
- }
-
- if (debug != null) {
- if (worthy) {
- debug.println("YES - try this trustedCert");
- } else {
- debug.println("NO - don't try this trustedCert");
+ boolean revCheckerAdded = false;
+ List<PKIXCertPathChecker> checkers = params.certPathCheckers();
+ for (PKIXCertPathChecker checker : checkers) {
+ if (checker instanceof PKIXRevocationChecker) {
+ revCheckerAdded = true;
+ // if it's our own, initialize it
+ if (checker instanceof RevocationChecker)
+ ((RevocationChecker)checker).init(anchor, params);
}
}
-
- return worthy;
- }
-
- /**
- * Internal method to setup the internal state
- */
- private void populateVariables(PKIXParameters pkixParam)
- {
- // default value for testDate is current time
- testDate = pkixParam.getDate();
- if (testDate == null) {
- testDate = new Date(System.currentTimeMillis());
+ // only add a RevocationChecker if revocation is enabled and
+ // a PKIXRevocationChecker has not already been added
+ if (params.revocationEnabled() && !revCheckerAdded) {
+ certPathCheckers.add(new RevocationChecker(anchor, params));
}
-
- userCheckers = pkixParam.getCertPathCheckers();
- sigProvider = pkixParam.getSigProvider();
-
- if (pkixParam.isRevocationEnabled()) {
- // Examine OCSP security property
- ocspEnabled = AccessController.doPrivileged(
- new GetBooleanSecurityPropertyAction
- (OCSPChecker.OCSP_ENABLE_PROP));
- onlyEECert = AccessController.doPrivileged(
- new GetBooleanSecurityPropertyAction
- ("com.sun.security.onlyCheckRevocationOfEECert"));
- }
- }
-
- /**
- * Internal method to actually validate a constructed path.
- *
- * @return the valid policy tree
- */
- private PolicyNode doValidate(
- TrustAnchor anchor, CertPath cpOriginal,
- ArrayList<X509Certificate> certList, PKIXParameters pkixParam,
- PolicyNodeImpl rootNode) throws CertPathValidatorException
- {
- int certPathLen = certList.size();
+ // add user-specified checkers
+ certPathCheckers.addAll(checkers);
- basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
- AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor);
- KeyChecker keyChecker = new KeyChecker(certPathLen,
- pkixParam.getTargetCertConstraints());
- ConstraintsChecker constraintsChecker =
- new ConstraintsChecker(certPathLen);
-
- PolicyChecker policyChecker =
- new PolicyChecker(pkixParam.getInitialPolicies(), certPathLen,
- pkixParam.isExplicitPolicyRequired(),
- pkixParam.isPolicyMappingInhibited(),
- pkixParam.isAnyPolicyInhibited(),
- pkixParam.getPolicyQualifiersRejected(),
- rootNode);
- UntrustedChecker untrustedChecker = new UntrustedChecker();
-
- ArrayList<PKIXCertPathChecker> certPathCheckers =
- new ArrayList<PKIXCertPathChecker>();
- // add standard checkers that we will be using
- certPathCheckers.add(untrustedChecker);
- certPathCheckers.add(algorithmChecker);
- certPathCheckers.add(keyChecker);
- certPathCheckers.add(constraintsChecker);
- certPathCheckers.add(policyChecker);
- certPathCheckers.add(basicChecker);
+ PKIXMasterCertPathValidator.validate(params.certPath(),
+ params.certificates(),
+ certPathCheckers);
- // only add a revocationChecker if revocation is enabled
- if (pkixParam.isRevocationEnabled()) {
-
- // Use OCSP if it has been enabled
- if (ocspEnabled) {
- OCSPChecker ocspChecker =
- new OCSPChecker(cpOriginal, pkixParam, onlyEECert);
- certPathCheckers.add(ocspChecker);
- }
-
- // Always use CRLs
- CrlRevocationChecker revocationChecker = new
- CrlRevocationChecker(anchor, pkixParam, certList, onlyEECert);
- certPathCheckers.add(revocationChecker);
- }
-
- // add user-specified checkers
- certPathCheckers.addAll(userCheckers);
-
- PKIXMasterCertPathValidator masterValidator =
- new PKIXMasterCertPathValidator(certPathCheckers);
-
- masterValidator.validate(cpOriginal, certList);
-
- return policyChecker.getPolicyTree();
+ return new PKIXCertPathValidatorResult(anchor, pc.getPolicyTree(),
+ bc.getPublicKey());
}
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -30,10 +30,8 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import java.security.cert.CertificateRevokedException;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXReason;
import java.security.cert.X509Certificate;
@@ -49,32 +47,22 @@
class PKIXMasterCertPathValidator {
private static final Debug debug = Debug.getInstance("certpath");
- private List<PKIXCertPathChecker> certPathCheckers;
-
- /**
- * Initializes the list of PKIXCertPathCheckers whose checks
- * will be performed on each certificate in the certpath.
- *
- * @param certPathCheckers a List of checkers to use
- */
- PKIXMasterCertPathValidator(List<PKIXCertPathChecker> certPathCheckers) {
- this.certPathCheckers = certPathCheckers;
- }
/**
* Validates a certification path consisting exclusively of
- * <code>X509Certificate</code>s using the
- * <code>PKIXCertPathChecker</code>s specified
- * in the constructor. It is assumed that the
+ * <code>X509Certificate</code>s using the specified
+ * <code>PKIXCertPathChecker</code>s. It is assumed that the
* <code>PKIXCertPathChecker</code>s
* have been initialized with any input parameters they may need.
*
* @param cpOriginal the original X509 CertPath passed in by the user
* @param reversedCertList the reversed X509 CertPath (as a List)
- * @exception CertPathValidatorException Exception thrown if cert
- * path does not validate.
+ * @param certPathCheckers the PKIXCertPathCheckers
+ * @throws CertPathValidatorException if cert path does not validate
*/
- void validate(CertPath cpOriginal, List<X509Certificate> reversedCertList)
+ static void validate(CertPath cpOriginal,
+ List<X509Certificate> reversedCertList,
+ List<PKIXCertPathChecker> certPathCheckers)
throws CertPathValidatorException
{
// we actually process reversedCertList, but we keep cpOriginal because
@@ -104,20 +92,18 @@
debug.println("Checking cert" + (i+1) + " ...");
X509Certificate currCert = reversedCertList.get(i);
- Set<String> unresolvedCritExts =
- currCert.getCriticalExtensionOIDs();
- if (unresolvedCritExts == null) {
- unresolvedCritExts = Collections.<String>emptySet();
+ Set<String> unresCritExts = currCert.getCriticalExtensionOIDs();
+ if (unresCritExts == null) {
+ unresCritExts = Collections.<String>emptySet();
}
- if (debug != null && !unresolvedCritExts.isEmpty()) {
+ if (debug != null && !unresCritExts.isEmpty()) {
debug.println("Set of critical extensions:");
- for (String oid : unresolvedCritExts) {
+ for (String oid : unresCritExts) {
debug.println(oid);
}
}
- CertPathValidatorException ocspCause = null;
for (int j = 0; j < certPathCheckers.size(); j++) {
PKIXCertPathChecker currChecker = certPathCheckers.get(j);
@@ -130,65 +116,21 @@
currChecker.init(false);
try {
- currChecker.check(currCert, unresolvedCritExts);
+ currChecker.check(currCert, unresCritExts);
- // OCSP has validated the cert so skip the CRL check
- if (isRevocationCheck(currChecker, j, certPathCheckers)) {
- if (debug != null) {
- debug.println("-checker" + (j + 1) +
- " validation succeeded");
- }
- j++;
- continue; // skip
+ if (debug != null) {
+ debug.println("-checker" + (j + 1) +
+ " validation succeeded");
}
} catch (CertPathValidatorException cpve) {
- // Throw the saved OCSP exception unless the CRL
- // checker has determined that the cert is revoked
- if (ocspCause != null &&
- currChecker instanceof CrlRevocationChecker) {
- if (cpve.getReason() == BasicReason.REVOKED) {
- throw cpve;
- } else {
- throw ocspCause;
- }
- }
- /*
- * Handle failover from OCSP to CRLs
- */
- CertPathValidatorException currentCause =
- new CertPathValidatorException(cpve.getMessage(),
- cpve.getCause(), cpOriginal, cpSize - (i + 1),
- cpve.getReason());
-
- // Check if OCSP has confirmed that the cert was revoked
- if (cpve.getReason() == BasicReason.REVOKED) {
- throw currentCause;
- }
- // Check if it is appropriate to failover
- if (! isRevocationCheck(currChecker, j, certPathCheckers)) {
- // no failover
- throw currentCause;
- }
- // Save the current exception
- // (in case the CRL check also fails)
- ocspCause = currentCause;
-
- // Otherwise, failover to CRLs
- if (debug != null) {
- debug.println(cpve.getMessage());
- debug.println(
- "preparing to failover (from OCSP to CRLs)");
- }
+ throw new CertPathValidatorException(cpve.getMessage(),
+ cpve.getCause(), cpOriginal, cpSize - (i + 1),
+ cpve.getReason());
}
-
- if (debug != null)
- debug.println("-checker" + (j+1) + " validation succeeded");
}
- if (debug != null)
- debug.println("checking for unresolvedCritExts");
- if (!unresolvedCritExts.isEmpty()) {
+ if (!unresCritExts.isEmpty()) {
throw new CertPathValidatorException("unrecognized " +
"critical extension(s)", null, cpOriginal, cpSize-(i+1),
PKIXReason.UNRECOGNIZED_CRIT_EXT);
@@ -200,26 +142,9 @@
if (debug != null) {
debug.println("Cert path validation succeeded. (PKIX validation "
- + "algorithm)");
+ + "algorithm)");
debug.println("-------------------------------------------------"
- + "-------------");
+ + "-------------");
}
}
-
- /*
- * Examines the list of PKIX cert path checkers to determine whether
- * both the current checker and the next checker are revocation checkers.
- * OCSPChecker and CrlRevocationChecker are both revocation checkers.
- */
- private static boolean isRevocationCheck(PKIXCertPathChecker checker,
- int index, List<PKIXCertPathChecker> checkers) {
-
- if (checker instanceof OCSPChecker && index + 1 < checkers.size()) {
- PKIXCertPathChecker nextChecker = checkers.get(index + 1);
- if (nextChecker instanceof CrlRevocationChecker) {
- return true;
- }
- }
- return false;
- }
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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,9 +25,8 @@
package sun.security.provider.certpath;
-import java.util.*;
import java.io.IOException;
-
+import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
@@ -36,13 +35,14 @@
import java.security.cert.PolicyNode;
import java.security.cert.PolicyQualifierInfo;
import java.security.cert.X509Certificate;
+import java.util.*;
import sun.security.util.Debug;
import sun.security.x509.CertificatePoliciesExtension;
import sun.security.x509.PolicyConstraintsExtension;
import sun.security.x509.PolicyMappingsExtension;
import sun.security.x509.CertificatePolicyMap;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.PolicyInformation;
import sun.security.x509.X509CertImpl;
import sun.security.x509.InhibitAnyPolicyExtension;
@@ -88,7 +88,7 @@
PolicyChecker(Set<String> initialPolicies, int certPathLen,
boolean expPolicyRequired, boolean polMappingInhibited,
boolean anyPolicyInhibited, boolean rejectPolicyQualifiers,
- PolicyNodeImpl rootNode) throws CertPathValidatorException
+ PolicyNodeImpl rootNode)
{
if (initialPolicies.isEmpty()) {
// if no initialPolicies are specified by user, set
@@ -104,18 +104,18 @@
this.anyPolicyInhibited = anyPolicyInhibited;
this.rejectPolicyQualifiers = rejectPolicyQualifiers;
this.rootNode = rootNode;
- init(false);
}
/**
* Initializes the internal state of the checker from parameters
* specified in the constructor
*
- * @param forward a boolean indicating whether this checker should
- * be initialized capable of building in the forward direction
- * @exception CertPathValidatorException Exception thrown if user
- * wants to enable forward checking and forward checking is not supported.
+ * @param forward a boolean indicating whether this checker should be
+ * initialized capable of building in the forward direction
+ * @throws CertPathValidatorException if user wants to enable forward
+ * checking and forward checking is not supported.
*/
+ @Override
public void init(boolean forward) throws CertPathValidatorException {
if (forward) {
throw new CertPathValidatorException
@@ -136,6 +136,7 @@
*
* @return true if forward checking is supported, false otherwise
*/
+ @Override
public boolean isForwardCheckingSupported() {
return false;
}
@@ -150,13 +151,14 @@
* @return the Set of extensions supported by this PKIXCertPathChecker,
* or null if no extensions are supported
*/
+ @Override
public Set<String> getSupportedExtensions() {
if (supportedExts == null) {
- supportedExts = new HashSet<String>();
- supportedExts.add(PKIXExtensions.CertificatePolicies_Id.toString());
- supportedExts.add(PKIXExtensions.PolicyMappings_Id.toString());
- supportedExts.add(PKIXExtensions.PolicyConstraints_Id.toString());
- supportedExts.add(PKIXExtensions.InhibitAnyPolicy_Id.toString());
+ supportedExts = new HashSet<String>(4);
+ supportedExts.add(CertificatePolicies_Id.toString());
+ supportedExts.add(PolicyMappings_Id.toString());
+ supportedExts.add(PolicyConstraints_Id.toString());
+ supportedExts.add(InhibitAnyPolicy_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts);
}
return supportedExts;
@@ -168,9 +170,9 @@
*
* @param cert the Certificate to be processed
* @param unresCritExts the unresolved critical extensions
- * @exception CertPathValidatorException Exception thrown if
- * the certificate does not verify.
+ * @throws CertPathValidatorException if the certificate does not verify
*/
+ @Override
public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException
{
@@ -178,10 +180,10 @@
checkPolicy((X509Certificate) cert);
if (unresCritExts != null && !unresCritExts.isEmpty()) {
- unresCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString());
- unresCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString());
- unresCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString());
- unresCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString());
+ unresCritExts.remove(CertificatePolicies_Id.toString());
+ unresCritExts.remove(PolicyMappings_Id.toString());
+ unresCritExts.remove(PolicyConstraints_Id.toString());
+ unresCritExts.remove(InhibitAnyPolicy_Id.toString());
}
}
@@ -290,7 +292,7 @@
if (require == 0)
explicitPolicy = require;
}
- } catch (Exception e) {
+ } catch (IOException e) {
if (debug != null) {
debug.println("PolicyChecker.mergeExplicitPolicy "
+ "unexpected exception");
@@ -339,7 +341,7 @@
policyMapping = inhibit;
}
}
- } catch (Exception e) {
+ } catch (IOException e) {
if (debug != null) {
debug.println("PolicyChecker.mergePolicyMapping "
+ "unexpected exception");
@@ -372,7 +374,7 @@
try {
InhibitAnyPolicyExtension inhAnyPolExt = (InhibitAnyPolicyExtension)
- currCert.getExtension(PKIXExtensions.InhibitAnyPolicy_Id);
+ currCert.getExtension(InhibitAnyPolicy_Id);
if (inhAnyPolExt == null)
return inhibitAnyPolicy;
@@ -387,7 +389,7 @@
inhibitAnyPolicy = skipCerts;
}
}
- } catch (Exception e) {
+ } catch (IOException e) {
if (debug != null) {
debug.println("PolicyChecker.mergeInhibitAnyPolicy "
+ "unexpected exception");
@@ -429,7 +431,7 @@
boolean policiesCritical = false;
List<PolicyInformation> policyInfo;
PolicyNodeImpl rootNode = null;
- Set<PolicyQualifierInfo> anyQuals = new HashSet<PolicyQualifierInfo>();
+ Set<PolicyQualifierInfo> anyQuals = new HashSet<>();
if (origRootNode == null)
rootNode = null;
@@ -600,7 +602,7 @@
PolicyNodeImpl parentNode = (PolicyNodeImpl)anyNode.getParent();
parentNode.deleteChild(anyNode);
// see if there are any initialPolicies not represented by leaf nodes
- Set<String> initial = new HashSet<String>(initPolicies);
+ Set<String> initial = new HashSet<>(initPolicies);
for (PolicyNodeImpl node : rootNode.getPolicyNodes(certIndex)) {
initial.remove(node.getValidPolicy());
}
@@ -697,7 +699,7 @@
}
}
- Set<String> expPols = new HashSet<String>();
+ Set<String> expPols = new HashSet<>();
expPols.add(curParExpPol);
curNode = new PolicyNodeImpl
@@ -762,8 +764,7 @@
}
boolean childDeleted = false;
- for (int j = 0; j < maps.size(); j++) {
- CertificatePolicyMap polMap = maps.get(j);
+ for (CertificatePolicyMap polMap : maps) {
String issuerDomain
= polMap.getIssuerIdentifier().getIdentifier().toString();
String subjectDomain
@@ -816,7 +817,7 @@
PolicyNodeImpl curAnyNodeParent =
(PolicyNodeImpl) curAnyNode.getParent();
- Set<String> expPols = new HashSet<String>();
+ Set<String> expPols = new HashSet<>();
expPols.add(subjectDomain);
PolicyNodeImpl curNode = new PolicyNodeImpl
--- a/jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -134,30 +134,37 @@
node.mCriticalityIndicator, node.mExpectedPolicySet, false);
}
+ @Override
public PolicyNode getParent() {
return mParent;
}
+ @Override
public Iterator<PolicyNodeImpl> getChildren() {
return Collections.unmodifiableSet(mChildren).iterator();
}
+ @Override
public int getDepth() {
return mDepth;
}
+ @Override
public String getValidPolicy() {
return mValidPolicy;
}
+ @Override
public Set<PolicyQualifierInfo> getPolicyQualifiers() {
return Collections.unmodifiableSet(mQualifierSet);
}
+ @Override
public Set<String> getExpectedPolicies() {
return Collections.unmodifiableSet(mExpectedPolicySet);
}
+ @Override
public boolean isCritical() {
return mCriticalityIndicator;
}
@@ -169,12 +176,12 @@
*
* @return a String describing the contents of the Policy Node
*/
+ @Override
public String toString() {
- StringBuffer buffer = new StringBuffer(this.asString());
+ StringBuilder buffer = new StringBuilder(this.asString());
- Iterator<PolicyNodeImpl> it = getChildren();
- while (it.hasNext()) {
- buffer.append(it.next());
+ for (PolicyNodeImpl node : mChildren) {
+ buffer.append(node);
}
return buffer.toString();
}
@@ -293,7 +300,7 @@
* @return a <code>Set</code> of all nodes at the specified depth
*/
Set<PolicyNodeImpl> getPolicyNodes(int depth) {
- Set<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
+ Set<PolicyNodeImpl> set = new HashSet<>();
getPolicyNodes(depth, set);
return set;
}
@@ -337,7 +344,7 @@
private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth,
String expectedOID, boolean matchAny) {
- HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
+ HashSet<PolicyNodeImpl> set = new HashSet<>();
if (mDepth < depth) {
for (PolicyNodeImpl node : mChildren) {
@@ -367,7 +374,7 @@
* @return a Set of matched <code>PolicyNode</code>s
*/
Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) {
- HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
+ HashSet<PolicyNodeImpl> set = new HashSet<>();
if (mDepth < depth) {
for (PolicyNodeImpl node : mChildren) {
@@ -396,7 +403,7 @@
if (mParent == null) {
return "anyPolicy ROOT\n";
} else {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
for (int i = 0, n = getDepth(); i < n; i++) {
sb.append(" ");
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Thu May 31 17:07:28 2012 -0400
@@ -51,9 +51,10 @@
import javax.security.auth.x500.X500Principal;
+import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug;
import sun.security.x509.Extension;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.PolicyMappingsExtension;
@@ -72,28 +73,24 @@
private Debug debug = Debug.getInstance("certpath");
- Set<String> initPolicies;
+ private final Set<String> initPolicies;
/**
* Initialize the builder with the input parameters.
*
* @param params the parameter set used to build a certification path
*/
- ReverseBuilder(PKIXBuilderParameters buildParams,
- X500Principal targetSubjectDN) {
+ ReverseBuilder(BuilderParams buildParams) {
+ super(buildParams);
- super(buildParams, targetSubjectDN);
-
- Set<String> initialPolicies = buildParams.getInitialPolicies();
+ Set<String> initialPolicies = buildParams.initialPolicies();
initPolicies = new HashSet<String>();
if (initialPolicies.isEmpty()) {
// if no initialPolicies are specified by user, set
// initPolicies to be anyPolicy by default
initPolicies.add(PolicyChecker.ANY_POLICY);
} else {
- for (String policy : initialPolicies) {
- initPolicies.add(policy);
- }
+ initPolicies.addAll(initialPolicies);
}
}
@@ -106,6 +103,7 @@
* Must be an instance of <code>ReverseState</code>
* @param certStores list of CertStores
*/
+ @Override
Collection<X509Certificate> getMatchingCerts
(State currState, List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException
@@ -138,56 +136,56 @@
(ReverseState currentState, List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException {
- /*
- * Compose a CertSelector to filter out
- * certs which do not satisfy requirements.
- *
- * First, retrieve clone of current target cert constraints,
- * and then add more selection criteria based on current validation state.
- */
- X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
+ /*
+ * Compose a CertSelector to filter out
+ * certs which do not satisfy requirements.
+ *
+ * First, retrieve clone of current target cert constraints, and
+ * then add more selection criteria based on current validation state.
+ */
+ X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
- /*
- * Match on issuer (subject of previous cert)
- */
- sel.setIssuer(currentState.subjectDN);
+ /*
+ * Match on issuer (subject of previous cert)
+ */
+ sel.setIssuer(currentState.subjectDN);
- /*
- * Match on certificate validity date.
- */
- sel.setCertificateValid(date);
+ /*
+ * Match on certificate validity date.
+ */
+ sel.setCertificateValid(buildParams.date());
- /*
- * Policy processing optimizations
- */
- if (currentState.explicitPolicy == 0)
- sel.setPolicy(getMatchingPolicies());
+ /*
+ * Policy processing optimizations
+ */
+ if (currentState.explicitPolicy == 0)
+ sel.setPolicy(getMatchingPolicies());
- /*
- * If previous cert has a subject key identifier extension,
- * use it to match on authority key identifier extension.
- */
- /*if (currentState.subjKeyId != null) {
- AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
+ /*
+ * If previous cert has a subject key identifier extension,
+ * use it to match on authority key identifier extension.
+ */
+ /*if (currentState.subjKeyId != null) {
+ AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
(KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
null, null);
sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
- }*/
+ }*/
- /*
- * Require EE certs
- */
- sel.setBasicConstraints(-2);
+ /*
+ * Require EE certs
+ */
+ sel.setBasicConstraints(-2);
- /* Retrieve matching certs from CertStores */
- HashSet<X509Certificate> eeCerts = new HashSet<X509Certificate>();
- addMatchingCerts(sel, certStores, eeCerts, true);
+ /* Retrieve matching certs from CertStores */
+ HashSet<X509Certificate> eeCerts = new HashSet<>();
+ addMatchingCerts(sel, certStores, eeCerts, true);
- if (debug != null) {
- debug.println("ReverseBuilder.getMatchingEECerts got " + eeCerts.size()
- + " certs.");
- }
- return eeCerts;
+ if (debug != null) {
+ debug.println("ReverseBuilder.getMatchingEECerts got "
+ + eeCerts.size() + " certs.");
+ }
+ return eeCerts;
}
/*
@@ -198,63 +196,71 @@
(ReverseState currentState, List<CertStore> certStores)
throws CertificateException, CertStoreException, IOException {
- /*
- * Compose a CertSelector to filter out
- * certs which do not satisfy requirements.
- */
- X509CertSelector sel = new X509CertSelector();
+ /*
+ * Compose a CertSelector to filter out
+ * certs which do not satisfy requirements.
+ */
+ X509CertSelector sel = new X509CertSelector();
- /*
- * Match on issuer (subject of previous cert)
- */
- sel.setIssuer(currentState.subjectDN);
+ /*
+ * Match on issuer (subject of previous cert)
+ */
+ sel.setIssuer(currentState.subjectDN);
- /*
- * Match on certificate validity date.
- */
- sel.setCertificateValid(date);
+ /*
+ * Match on certificate validity date.
+ */
+ sel.setCertificateValid(buildParams.date());
- /*
- * Match on target subject name (checks that current cert's
- * name constraints permit it to certify target).
- * (4 is the integer type for DIRECTORY name).
- */
- sel.addPathToName(4, targetCertConstraints.getSubjectAsBytes());
+ /*
+ * Match on target subject name (checks that current cert's
+ * name constraints permit it to certify target).
+ * (4 is the integer type for DIRECTORY name).
+ */
+ byte[] subject = targetCertConstraints.getSubjectAsBytes();
+ if (subject != null) {
+ sel.addPathToName(4, subject);
+ } else {
+ X509Certificate cert = targetCertConstraints.getCertificate();
+ if (cert != null) {
+ sel.addPathToName(4,
+ cert.getSubjectX500Principal().getEncoded());
+ }
+ }
- /*
- * Policy processing optimizations
- */
- if (currentState.explicitPolicy == 0)
- sel.setPolicy(getMatchingPolicies());
+ /*
+ * Policy processing optimizations
+ */
+ if (currentState.explicitPolicy == 0)
+ sel.setPolicy(getMatchingPolicies());
- /*
- * If previous cert has a subject key identifier extension,
- * use it to match on authority key identifier extension.
- */
- /*if (currentState.subjKeyId != null) {
- AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
+ /*
+ * If previous cert has a subject key identifier extension,
+ * use it to match on authority key identifier extension.
+ */
+ /*if (currentState.subjKeyId != null) {
+ AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
(KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
null, null);
- sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
- }*/
+ sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
+ }*/
- /*
- * Require CA certs
- */
- sel.setBasicConstraints(0);
+ /*
+ * Require CA certs
+ */
+ sel.setBasicConstraints(0);
- /* Retrieve matching certs from CertStores */
- ArrayList<X509Certificate> reverseCerts =
- new ArrayList<X509Certificate>();
- addMatchingCerts(sel, certStores, reverseCerts, true);
+ /* Retrieve matching certs from CertStores */
+ ArrayList<X509Certificate> reverseCerts = new ArrayList<>();
+ addMatchingCerts(sel, certStores, reverseCerts, true);
- /* Sort remaining certs using name constraints */
- Collections.sort(reverseCerts, new PKIXCertComparator());
+ /* Sort remaining certs using name constraints */
+ Collections.sort(reverseCerts, new PKIXCertComparator());
- if (debug != null)
- debug.println("ReverseBuilder.getMatchingCACerts got " +
- reverseCerts.size() + " certs.");
- return reverseCerts;
+ if (debug != null)
+ debug.println("ReverseBuilder.getMatchingCACerts got " +
+ reverseCerts.size() + " certs.");
+ return reverseCerts;
}
/*
@@ -269,23 +275,25 @@
private Debug debug = Debug.getInstance("certpath");
+ @Override
public int compare(X509Certificate cert1, X509Certificate cert2) {
/*
* if either cert certifies the target, always
* put at head of list.
*/
- if (cert1.getSubjectX500Principal().equals(targetSubjectDN)) {
+ X500Principal targetSubject = buildParams.targetSubject();
+ if (cert1.getSubjectX500Principal().equals(targetSubject)) {
return -1;
}
- if (cert2.getSubjectX500Principal().equals(targetSubjectDN)) {
+ if (cert2.getSubjectX500Principal().equals(targetSubject)) {
return 1;
}
int targetDist1;
int targetDist2;
try {
- X500Name targetSubjectName = X500Name.asX500Name(targetSubjectDN);
+ X500Name targetSubjectName = X500Name.asX500Name(targetSubject);
targetDist1 = Builder.targetDistance(
null, cert1, targetSubjectName);
targetDist2 = Builder.targetDistance(
@@ -330,6 +338,7 @@
* @param currentState the current state against which the cert is verified
* @param certPathList the certPathList generated thus far
*/
+ @Override
void verifyCert(X509Certificate cert, State currState,
List<X509Certificate> certPathList)
throws GeneralSecurityException
@@ -362,8 +371,7 @@
* of the same certificate, we reverse the certpathlist first
*/
if ((certPathList != null) && (!certPathList.isEmpty())) {
- List<X509Certificate> reverseCertList =
- new ArrayList<X509Certificate>();
+ List<X509Certificate> reverseCertList = new ArrayList<>();
for (X509Certificate c : certPathList) {
reverseCertList.add(0, c);
}
@@ -378,8 +386,8 @@
}
if (debug != null)
debug.println("policyMappingFound = " + policyMappingFound);
- if (cert.equals(cpListCert)){
- if ((buildParams.isPolicyMappingInhibited()) ||
+ if (cert.equals(cpListCert)) {
+ if ((buildParams.policyMappingInhibited()) ||
(!policyMappingFound)){
if (debug != null)
debug.println("loop detected!!");
@@ -390,7 +398,7 @@
}
/* check if target cert */
- boolean finalCert = cert.getSubjectX500Principal().equals(targetSubjectDN);
+ boolean finalCert = cert.getSubjectX500Principal().equals(buildParams.targetSubject());
/* check if CA cert */
boolean caCert = (cert.getBasicConstraints() != -1 ? true : false);
@@ -431,23 +439,20 @@
/*
* Check revocation.
*/
- if (buildParams.isRevocationEnabled()) {
-
- currentState.crlChecker.check(cert,
- currentState.pubKey,
- currentState.crlSign);
+ if (buildParams.revocationEnabled() && currentState.revChecker != null) {
+ currentState.revChecker.check(cert, Collections.<String>emptySet());
}
/* Check name constraints if this is not a self-issued cert */
if (finalCert || !X509CertImpl.isSelfIssued(cert)){
- if (currentState.nc != null){
+ if (currentState.nc != null) {
try {
if (!currentState.nc.verify(cert)){
throw new CertPathValidatorException
("name constraints check failed", null, null, -1,
PKIXReason.INVALID_NAME);
}
- } catch (IOException ioe){
+ } catch (IOException ioe) {
throw new CertPathValidatorException(ioe);
}
}
@@ -461,7 +466,7 @@
(currentState.certIndex, initPolicies,
currentState.explicitPolicy, currentState.policyMapping,
currentState.inhibitAnyPolicy,
- buildParams.getPolicyQualifiersRejected(), currentState.rootNode,
+ buildParams.policyQualifiersRejected(), currentState.rootNode,
certImpl, finalCert);
/*
@@ -486,15 +491,15 @@
* already checked. If there are any left, throw an exception!
*/
if (!unresolvedCritExts.isEmpty()) {
- unresolvedCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString());
- unresolvedCritExts.remove(PKIXExtensions.NameConstraints_Id.toString());
- unresolvedCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString());
- unresolvedCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString());
- unresolvedCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString());
- unresolvedCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString());
- unresolvedCritExts.remove(PKIXExtensions.SubjectAlternativeName_Id.toString());
- unresolvedCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
- unresolvedCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString());
+ unresolvedCritExts.remove(BasicConstraints_Id.toString());
+ unresolvedCritExts.remove(NameConstraints_Id.toString());
+ unresolvedCritExts.remove(CertificatePolicies_Id.toString());
+ unresolvedCritExts.remove(PolicyMappings_Id.toString());
+ unresolvedCritExts.remove(PolicyConstraints_Id.toString());
+ unresolvedCritExts.remove(InhibitAnyPolicy_Id.toString());
+ unresolvedCritExts.remove(SubjectAlternativeName_Id.toString());
+ unresolvedCritExts.remove(KeyUsage_Id.toString());
+ unresolvedCritExts.remove(ExtendedKeyUsage_Id.toString());
if (!unresolvedCritExts.isEmpty())
throw new CertPathValidatorException
@@ -505,8 +510,8 @@
/*
* Check signature.
*/
- if (buildParams.getSigProvider() != null) {
- cert.verify(currentState.pubKey, buildParams.getSigProvider());
+ if (buildParams.sigProvider() != null) {
+ cert.verify(currentState.pubKey, buildParams.sigProvider());
} else {
cert.verify(currentState.pubKey);
}
@@ -519,8 +524,9 @@
* @param cert the certificate to test
* @return a boolean value indicating whether the cert completes the path.
*/
+ @Override
boolean isPathCompleted(X509Certificate cert) {
- return cert.getSubjectX500Principal().equals(targetSubjectDN);
+ return cert.getSubjectX500Principal().equals(buildParams.targetSubject());
}
/** Adds the certificate to the certPathList
@@ -528,6 +534,7 @@
* @param cert the certificate to be added
* @param certPathList the certification path list
*/
+ @Override
void addCertToPath(X509Certificate cert,
LinkedList<X509Certificate> certPathList) {
certPathList.addLast(cert);
@@ -537,6 +544,7 @@
*
* @param certPathList the certification path list
*/
+ @Override
void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
certPathList.removeLast();
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java Thu May 31 17:07:28 2012 -0400
@@ -40,6 +40,7 @@
import java.util.Set;
import javax.security.auth.x500.X500Principal;
+import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug;
import sun.security.x509.NameConstraintsExtension;
import sun.security.x509.SubjectKeyIdentifierExtension;
@@ -94,7 +95,7 @@
private boolean init = true;
/* the checker used for revocation status */
- public CrlRevocationChecker crlChecker;
+ RevocationChecker revChecker;
/* the algorithm checker */
AlgorithmChecker algorithmChecker;
@@ -108,7 +109,7 @@
/* Flag indicating if current cert can vouch for the CRL for
* the next cert
*/
- public boolean crlSign = true;
+ boolean crlSign = true;
/**
* Returns a boolean flag indicating if the state is initial
@@ -116,6 +117,7 @@
*
* @return boolean flag indicating if the state is initial (just starting)
*/
+ @Override
public boolean isInitial() {
return init;
}
@@ -123,44 +125,32 @@
/**
* Display state for debugging purposes
*/
+ @Override
public String toString() {
- StringBuffer sb = new StringBuffer();
- try {
- sb.append("State [");
- sb.append("\n subjectDN of last cert: " + subjectDN);
- sb.append("\n subjectKeyIdentifier: " + String.valueOf(subjKeyId));
- sb.append("\n nameConstraints: " + String.valueOf(nc));
- sb.append("\n certIndex: " + certIndex);
- sb.append("\n explicitPolicy: " + explicitPolicy);
- sb.append("\n policyMapping: " + policyMapping);
- sb.append("\n inhibitAnyPolicy: " + inhibitAnyPolicy);
- sb.append("\n rootNode: " + rootNode);
- sb.append("\n remainingCACerts: " + remainingCACerts);
- sb.append("\n crlSign: " + crlSign);
- sb.append("\n init: " + init);
- sb.append("\n]\n");
- } catch (Exception e) {
- if (debug != null) {
- debug.println("ReverseState.toString() unexpected exception");
- e.printStackTrace();
- }
- }
+ StringBuilder sb = new StringBuilder();
+ sb.append("State [");
+ sb.append("\n subjectDN of last cert: ").append(subjectDN);
+ sb.append("\n subjectKeyIdentifier: ").append
+ (String.valueOf(subjKeyId));
+ sb.append("\n nameConstraints: ").append(String.valueOf(nc));
+ sb.append("\n certIndex: ").append(certIndex);
+ sb.append("\n explicitPolicy: ").append(explicitPolicy);
+ sb.append("\n policyMapping: ").append(policyMapping);
+ sb.append("\n inhibitAnyPolicy: ").append(inhibitAnyPolicy);
+ sb.append("\n rootNode: ").append(rootNode);
+ sb.append("\n remainingCACerts: ").append(remainingCACerts);
+ sb.append("\n crlSign: ").append(crlSign);
+ sb.append("\n init: ").append(init);
+ sb.append("\n]\n");
return sb.toString();
}
/**
* Initialize the state.
*
- * @param maxPathLen The maximum number of CA certs in a path, where -1
- * means unlimited and 0 means only a single EE cert is allowed.
- * @param explicitPolicyRequired True, if explicit policy is required.
- * @param policyMappingInhibited True, if policy mapping is inhibited.
- * @param anyPolicyInhibited True, if any policy is inhibited.
- * @param certPathCheckers the list of user-defined PKIXCertPathCheckers
+ * @param buildParams builder parameters
*/
- public void initState(int maxPathLen, boolean explicitPolicyRequired,
- boolean policyMappingInhibited, boolean anyPolicyInhibited,
- List<PKIXCertPathChecker> certPathCheckers)
+ public void initState(BuilderParams buildParams)
throws CertPathValidatorException
{
/*
@@ -168,60 +158,52 @@
* Note that -1 maxPathLen implies unlimited.
* 0 implies only an EE cert is acceptable.
*/
- remainingCACerts = (maxPathLen == -1 ? Integer.MAX_VALUE : maxPathLen);
+ int maxPathLen = buildParams.maxPathLength();
+ remainingCACerts = (maxPathLen == -1) ? Integer.MAX_VALUE
+ : maxPathLen;
/* Initialize explicit policy state variable */
- if (explicitPolicyRequired) {
+ if (buildParams.explicitPolicyRequired()) {
explicitPolicy = 0;
} else {
// unconstrained if maxPathLen is -1,
// otherwise, we want to initialize this to the value of the
// longest possible path + 1 (i.e. maxpathlen + finalcert + 1)
- explicitPolicy = (maxPathLen == -1)
- ? maxPathLen
- : maxPathLen + 2;
+ explicitPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
}
/* Initialize policy mapping state variable */
- if (policyMappingInhibited) {
+ if (buildParams.policyMappingInhibited()) {
policyMapping = 0;
} else {
- policyMapping = (maxPathLen == -1)
- ? maxPathLen
- : maxPathLen + 2;
+ policyMapping = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
}
/* Initialize inhibit any policy state variable */
- if (anyPolicyInhibited) {
+ if (buildParams.anyPolicyInhibited()) {
inhibitAnyPolicy = 0;
} else {
- inhibitAnyPolicy = (maxPathLen == -1)
- ? maxPathLen
- : maxPathLen + 2;
+ inhibitAnyPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
}
/* Initialize certIndex */
certIndex = 1;
/* Initialize policy tree */
- Set<String> initExpPolSet = new HashSet<String>(1);
+ Set<String> initExpPolSet = new HashSet<>(1);
initExpPolSet.add(PolicyChecker.ANY_POLICY);
- rootNode = new PolicyNodeImpl
- (null, PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
+ rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null,
+ false, initExpPolSet, false);
/*
* Initialize each user-defined checker
+ * Shallow copy the checkers
*/
- if (certPathCheckers != null) {
- /* Shallow copy the checkers */
- userCheckers = new ArrayList<PKIXCertPathChecker>(certPathCheckers);
- /* initialize each checker (just in case) */
- for (PKIXCertPathChecker checker : certPathCheckers) {
- checker.init(false);
- }
- } else {
- userCheckers = new ArrayList<PKIXCertPathChecker>();
+ userCheckers = new ArrayList<>(buildParams.certPathCheckers());
+ /* initialize each checker (just in case) */
+ for (PKIXCertPathChecker checker : userCheckers) {
+ checker.init(false);
}
/* Start by trusting the cert to sign CRLs */
@@ -234,8 +216,9 @@
* Update the state with the specified trust anchor.
*
* @param anchor the most-trusted CA
+ * @param buildParams builder parameters
*/
- public void updateState(TrustAnchor anchor)
+ public void updateState(TrustAnchor anchor, BuilderParams buildParams)
throws CertificateException, IOException, CertPathValidatorException
{
trustAnchor = anchor;
@@ -247,14 +230,26 @@
updateState(anchor.getCAPublicKey(), caName);
}
- // The user specified AlgorithmChecker may not be
+ // The user specified AlgorithmChecker and RevocationChecker may not be
// able to set the trust anchor until now.
+ boolean revCheckerAdded = false;
for (PKIXCertPathChecker checker : userCheckers) {
if (checker instanceof AlgorithmChecker) {
((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
+ } else if (checker instanceof RevocationChecker) {
+ ((RevocationChecker)checker).init(anchor, buildParams);
+ ((RevocationChecker)checker).init(false);
+ revCheckerAdded = true;
}
}
+ // only create a RevocationChecker if revocation is enabled and
+ // a PKIXRevocationChecker has not already been added
+ if (buildParams.revocationEnabled() && !revCheckerAdded) {
+ revChecker = new RevocationChecker(anchor, buildParams);
+ revChecker.init(false);
+ }
+
init = false;
}
@@ -313,7 +308,7 @@
subjKeyId = icert.getSubjectKeyIdentifierExtension();
/* update crlSign */
- crlSign = CrlRevocationChecker.certCanSignCrl(cert);
+ crlSign = RevocationChecker.certCanSignCrl(cert);
/* update current name constraints */
if (nc != null) {
@@ -352,6 +347,7 @@
*
* @return boolean flag indicating if key lacking parameters encountered.
*/
+ @Override
public boolean keyParamsNeeded() {
/* when building in reverse, we immediately get parameters needed
* or else throw an exception
@@ -368,6 +364,7 @@
* because some of them (e.g., subjKeyId) will
* not have their contents modified by subsequent calls to updateState.
*/
+ @Override
@SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
public Object clone() {
try {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java Thu May 31 17:07:28 2012 -0400
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (c) 2012, 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.io.IOException;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedAction;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.cert.CertPathValidatorException.BasicReason;
+import java.security.cert.Extension;
+import java.security.cert.*;
+import java.security.interfaces.DSAPublicKey;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.security.auth.x500.X500Principal;
+
+import static sun.security.provider.certpath.OCSP.*;
+import sun.security.provider.certpath.PKIX.ValidatorParams;
+import sun.security.action.GetPropertyAction;
+import sun.security.x509.*;
+import static sun.security.x509.PKIXExtensions.*;
+import sun.security.util.Debug;
+
+class RevocationChecker extends PKIXRevocationChecker {
+
+ private static final Debug debug = Debug.getInstance("certpath");
+
+ private TrustAnchor anchor;
+ private ValidatorParams params;
+ private boolean onlyEE;
+ private boolean softFail;
+ private boolean crlDP;
+ private URI responderURI;
+ private X509Certificate responderCert;
+ private List<CertStore> certStores;
+ private Map<X509Certificate, byte[]> ocspStapled;
+ private List<Extension> ocspExtensions;
+ private boolean legacy;
+
+ // state variables
+ private X509Certificate issuerCert;
+ private PublicKey prevPubKey;
+ private boolean crlSignFlag;
+
+ private enum Mode { PREFER_OCSP, PREFER_CRLS, ONLY_CRLS };
+ private Mode mode = Mode.PREFER_OCSP;
+
+ private static class RevocationProperties {
+ boolean onlyEE;
+ boolean ocspEnabled;
+ boolean crlDPEnabled;
+ String ocspUrl;
+ String ocspSubject;
+ String ocspIssuer;
+ String ocspSerial;
+ }
+
+ RevocationChecker() {
+ legacy = false;
+ }
+
+ RevocationChecker(TrustAnchor anchor, ValidatorParams params)
+ throws CertPathValidatorException
+ {
+ legacy = true;
+ init(anchor, params);
+ }
+
+ void init(TrustAnchor anchor, ValidatorParams params)
+ throws CertPathValidatorException
+ {
+ RevocationProperties rp = getRevocationProperties();
+ URI uri = getOCSPResponder();
+ responderURI = (uri == null) ? toURI(rp.ocspUrl) : uri;
+ X509Certificate cert = getOCSPResponderCert();
+ responderCert = (cert == null)
+ ? getResponderCert(rp, params.trustAnchors(),
+ params.certStores())
+ : cert;
+ Set<Option> options = getOptions();
+ for (Option option : options) {
+ switch (option) {
+ case ONLY_END_ENTITY:
+ case PREFER_CRLS:
+ case SOFT_FAIL:
+ break;
+ default:
+ throw new CertPathValidatorException(
+ "Unrecognized revocation parameter option: " + option);
+ }
+ }
+
+ // set mode, only end entity flag
+ if (legacy) {
+ mode = (rp.ocspEnabled) ? Mode.PREFER_OCSP : Mode.ONLY_CRLS;
+ onlyEE = rp.onlyEE;
+ } else {
+ if (options.contains(Option.PREFER_CRLS)) {
+ mode = Mode.PREFER_CRLS;
+ }
+ onlyEE = options.contains(Option.ONLY_END_ENTITY);
+ }
+ softFail = options.contains(Option.SOFT_FAIL);
+ if (legacy) {
+ crlDP = rp.crlDPEnabled;
+ } else {
+ crlDP = true;
+ }
+ ocspStapled = getOCSPStapledResponses();
+ ocspExtensions = getOCSPExtensions();
+
+ this.anchor = anchor;
+ this.params = params;
+ this.certStores = new ArrayList<>(params.certStores());
+ try {
+ this.certStores.add(CertStore.getInstance("Collection",
+ new CollectionCertStoreParameters(params.certificates())));
+ } catch (InvalidAlgorithmParameterException |
+ NoSuchAlgorithmException e) {
+ // should never occur but not necessarily fatal, so log it,
+ // ignore and continue
+ if (debug != null) {
+ debug.println("RevocationChecker: " +
+ "error creating Collection CertStore: " + e);
+ }
+ }
+ }
+
+ private static URI toURI(String uriString)
+ throws CertPathValidatorException
+ {
+ try {
+ if (uriString != null) {
+ return new URI(uriString);
+ }
+ return null;
+ } catch (URISyntaxException e) {
+ throw new CertPathValidatorException(
+ "cannot parse ocsp.responderURL property", e);
+ }
+ }
+
+ private static RevocationProperties getRevocationProperties() {
+ return AccessController.doPrivileged(
+ new PrivilegedAction<RevocationProperties>() {
+ public RevocationProperties run() {
+ RevocationProperties rp = new RevocationProperties();
+ String onlyEE = Security.getProperty(
+ "com.sun.security.onlyCheckRevocationOfEECert");
+ rp.onlyEE = onlyEE != null
+ && onlyEE.equalsIgnoreCase("true");
+ String ocspEnabled = Security.getProperty("ocsp.enable");
+ rp.ocspEnabled = ocspEnabled != null
+ && ocspEnabled.equalsIgnoreCase("true");
+ rp.ocspUrl = Security.getProperty("ocsp.responderURL");
+ rp.ocspSubject
+ = Security.getProperty("ocsp.responderCertSubjectName");
+ rp.ocspIssuer
+ = Security.getProperty("ocsp.responderCertIssuerName");
+ rp.ocspSerial
+ = Security.getProperty("ocsp.responderCertSerialNumber");
+ rp.crlDPEnabled
+ = Boolean.getBoolean("com.sun.security.enableCRLDP");
+ return rp;
+ }
+ }
+ );
+ }
+
+ private static X509Certificate getResponderCert(RevocationProperties rp,
+ Set<TrustAnchor> anchors,
+ List<CertStore> stores)
+ throws CertPathValidatorException
+ {
+ if (rp.ocspSubject != null) {
+ return getResponderCert(rp.ocspSubject, anchors, stores);
+ } else if (rp.ocspIssuer != null && rp.ocspSerial != null) {
+ return getResponderCert(rp.ocspIssuer, rp.ocspSerial,
+ anchors, stores);
+ } else if (rp.ocspIssuer != null || rp.ocspSerial != null) {
+ throw new CertPathValidatorException(
+ "Must specify both ocsp.responderCertIssuerName and " +
+ "ocsp.responderCertSerialNumber properties");
+ }
+ return null;
+ }
+
+ private static X509Certificate getResponderCert(String subject,
+ Set<TrustAnchor> anchors,
+ List<CertStore> stores)
+ throws CertPathValidatorException
+ {
+ X509CertSelector sel = new X509CertSelector();
+ try {
+ sel.setSubject(new X500Principal(subject));
+ } catch (IllegalArgumentException e) {
+ throw new CertPathValidatorException(
+ "cannot parse ocsp.responderCertSubjectName property", e);
+ }
+ return getResponderCert(sel, anchors, stores);
+ }
+
+ private static X509Certificate getResponderCert(String issuer,
+ String serial,
+ Set<TrustAnchor> anchors,
+ List<CertStore> stores)
+ throws CertPathValidatorException
+ {
+ X509CertSelector sel = new X509CertSelector();
+ try {
+ sel.setIssuer(new X500Principal(issuer));
+ } catch (IllegalArgumentException e) {
+ throw new CertPathValidatorException(
+ "cannot parse ocsp.responderCertIssuerName property", e);
+ }
+ try {
+ sel.setSerialNumber(new BigInteger(stripOutSeparators(serial), 16));
+ } catch (NumberFormatException e) {
+ throw new CertPathValidatorException(
+ "cannot parse ocsp.responderCertSerialNumber property", e);
+ }
+ return getResponderCert(sel, anchors, stores);
+ }
+
+ private static X509Certificate getResponderCert(X509CertSelector sel,
+ Set<TrustAnchor> anchors,
+ List<CertStore> stores)
+ throws CertPathValidatorException
+ {
+ // first check TrustAnchors
+ for (TrustAnchor anchor : anchors) {
+ X509Certificate cert = anchor.getTrustedCert();
+ if (cert == null) {
+ continue;
+ }
+ if (sel.match(cert)) {
+ return cert;
+ }
+ }
+ // now check CertStores
+ for (CertStore store : stores) {
+ try {
+ Collection<? extends Certificate> certs =
+ store.getCertificates(sel);
+ if (!certs.isEmpty()) {
+ return (X509Certificate)certs.iterator().next();
+ }
+ } catch (CertStoreException e) {
+ // ignore and try next CertStore
+ if (debug != null) {
+ debug.println("CertStore exception:" + e);
+ }
+ continue;
+ }
+ }
+ throw new CertPathValidatorException(
+ "Cannot find the responder's certificate " +
+ "(set using the OCSP security properties).");
+ }
+
+ @Override
+ public void init(boolean forward) throws CertPathValidatorException {
+ if (forward) {
+ throw new
+ CertPathValidatorException("forward checking not supported");
+ } else {
+ if (anchor != null) {
+ issuerCert = anchor.getTrustedCert();
+ prevPubKey = (issuerCert != null) ? issuerCert.getPublicKey()
+ : anchor.getCAPublicKey();
+ }
+ crlSignFlag = true;
+ }
+ }
+
+ @Override
+ public boolean isForwardCheckingSupported() {
+ return false;
+ }
+
+ @Override
+ public Set<String> getSupportedExtensions() {
+ return null;
+ }
+
+ @Override
+ public void check(Certificate cert, Collection<String> unresolvedCritExts)
+ throws CertPathValidatorException
+ {
+ X509Certificate xcert = (X509Certificate)cert;
+ if (onlyEE && xcert.getBasicConstraints() != -1) {
+ if (debug != null) {
+ debug.println("Skipping revocation check, not end entity cert");
+ }
+ } else {
+ check(xcert, unresolvedCritExts, prevPubKey, crlSignFlag);
+ }
+ updateState(xcert);
+ }
+
+ void check(X509Certificate xcert, Collection<String> unresolvedCritExts,
+ PublicKey pubKey, boolean crlSignFlag)
+ throws CertPathValidatorException
+ {
+ try {
+ switch (mode) {
+ case PREFER_OCSP:
+ checkOCSP(xcert, unresolvedCritExts);
+ break;
+ case PREFER_CRLS:
+ case ONLY_CRLS:
+ checkCRLs(xcert, unresolvedCritExts, null,
+ pubKey, crlSignFlag);
+ break;
+ }
+ } catch (CertPathValidatorException e) {
+ if (e.getReason() == BasicReason.REVOKED) {
+ throw e;
+ }
+ CertPathValidatorException cause = e;
+ if (softFail && e instanceof NetworkFailureException) {
+ if (mode == Mode.ONLY_CRLS) return;
+ }
+ // Rethrow the exception if ONLY_CRLS
+ if (mode == Mode.ONLY_CRLS) {
+ throw e;
+ }
+ // Otherwise, failover
+ if (debug != null) {
+ debug.println("RevocationChecker.check() " + e.getMessage());
+ debug.println("RevocationChecker.check() preparing to failover");
+ }
+ try {
+ switch (mode) {
+ case PREFER_OCSP:
+ checkCRLs(xcert, unresolvedCritExts, null,
+ pubKey, crlSignFlag);
+ break;
+ case PREFER_CRLS:
+ checkOCSP(xcert, unresolvedCritExts);
+ break;
+ }
+ } catch (CertPathValidatorException x) {
+ if (debug != null) {
+ debug.println("RevocationChecker.check() failover failed");
+ debug.println("RevocationChecker.check() " + x.getMessage());
+ }
+ if (x.getReason() == BasicReason.REVOKED) {
+ throw x;
+ }
+ if (cause != null) {
+ if (softFail && cause instanceof NetworkFailureException) {
+ return;
+ } else {
+ cause.addSuppressed(x);
+ throw cause;
+ }
+ }
+ if (softFail && x instanceof NetworkFailureException) {
+ return;
+ }
+ throw x;
+ }
+ }
+ }
+
+ private void updateState(X509Certificate cert)
+ throws CertPathValidatorException
+ {
+ issuerCert = cert;
+
+ // Make new public key if parameters are missing
+ PublicKey pubKey = cert.getPublicKey();
+ if (pubKey instanceof DSAPublicKey &&
+ ((DSAPublicKey)pubKey).getParams() == null) {
+ // pubKey needs to inherit DSA parameters from prev key
+ pubKey = BasicChecker.makeInheritedParamsKey(pubKey, prevPubKey);
+ }
+ prevPubKey = pubKey;
+ crlSignFlag = certCanSignCrl(cert);
+ }
+
+ // Maximum clock skew in milliseconds (15 minutes) allowed when checking
+ // validity of CRLs
+ private static final long MAX_CLOCK_SKEW = 900000;
+ private void checkCRLs(X509Certificate cert,
+ Collection<String> unresolvedCritExts,
+ Set<X509Certificate> stackedCerts,
+ PublicKey pubKey, boolean signFlag)
+ throws CertPathValidatorException
+ {
+ checkCRLs(cert, pubKey, signFlag, true,
+ stackedCerts, params.trustAnchors());
+ }
+
+ private void checkCRLs(X509Certificate cert, PublicKey prevKey,
+ boolean signFlag, boolean allowSeparateKey,
+ Set<X509Certificate> stackedCerts,
+ Set<TrustAnchor> anchors)
+ throws CertPathValidatorException
+ {
+ if (debug != null) {
+ debug.println("RevocationChecker.checkCRLs()" +
+ " ---checking revocation status ...");
+ }
+
+ // reject circular dependencies - RFC 3280 is not explicit on how
+ // to handle this, so we feel it is safest to reject them until
+ // the issue is resolved in the PKIX WG.
+ if (stackedCerts != null && stackedCerts.contains(cert)) {
+ if (debug != null) {
+ debug.println("RevocationChecker.checkCRLs()" +
+ " circular dependency");
+ }
+ throw new CertPathValidatorException
+ ("Could not determine revocation status", null, null, -1,
+ BasicReason.UNDETERMINED_REVOCATION_STATUS);
+ }
+
+ Set<X509CRL> possibleCRLs = new HashSet<>();
+ Set<X509CRL> approvedCRLs = new HashSet<>();
+ X509CRLSelector sel = new X509CRLSelector();
+ sel.setCertificateChecking(cert);
+ CertPathHelper.setDateAndTime(sel, params.date(), MAX_CLOCK_SKEW);
+
+ // First, check cached CRLs
+ for (CertStore store : certStores) {
+ try {
+ for (CRL crl : store.getCRLs(sel)) {
+ possibleCRLs.add((X509CRL)crl);
+ }
+ } catch (CertStoreException e) {
+ // XXX ignore?
+ }
+ }
+
+ if (debug != null) {
+ debug.println("RevocationChecker.checkCRLs() " +
+ "possible crls.size() = " + possibleCRLs.size());
+ }
+ boolean[] reasonsMask = new boolean[9];
+ if (!possibleCRLs.isEmpty()) {
+ // Now that we have a list of possible CRLs, see which ones can
+ // be approved
+ approvedCRLs.addAll(verifyPossibleCRLs(possibleCRLs, cert, prevKey,
+ signFlag, reasonsMask,
+ anchors));
+ }
+
+ if (debug != null) {
+ debug.println("RevocationChecker.checkCRLs() " +
+ "approved crls.size() = " + approvedCRLs.size());
+ }
+
+ // make sure that we have at least one CRL that _could_ cover
+ // the certificate in question and all reasons are covered
+ if (!approvedCRLs.isEmpty() &&
+ Arrays.equals(reasonsMask, ALL_REASONS))
+ {
+ checkApprovedCRLs(cert, approvedCRLs);
+ } else {
+ // Check Distribution Points
+ // all CRLs returned by the DP Fetcher have also been verified
+ try {
+ if (crlDP) {
+ approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
+ sel, signFlag, prevKey,
+ params.sigProvider(), certStores,
+ reasonsMask, anchors, params.date()));
+ }
+ } catch (CertStoreException e) {
+ if (debug != null) {
+ debug.println("RevocationChecker.checkCRLs() " +
+ "unexpected exception: " + e.getMessage());
+ }
+ throw new CertPathValidatorException(e);
+ }
+ if (!approvedCRLs.isEmpty() &&
+ Arrays.equals(reasonsMask, ALL_REASONS))
+ {
+ checkApprovedCRLs(cert, approvedCRLs);
+ } else {
+ if (allowSeparateKey) {
+ verifyWithSeparateSigningKey(cert, prevKey, signFlag,
+ stackedCerts);
+ return;
+ } else {
+ throw new CertPathValidatorException
+ ("Could not determine revocation status", null, null, -1,
+ BasicReason.UNDETERMINED_REVOCATION_STATUS);
+ }
+ }
+ }
+ }
+
+ private void checkApprovedCRLs(X509Certificate cert,
+ Set<X509CRL> approvedCRLs)
+ throws CertPathValidatorException
+ {
+ // See if the cert is in the set of approved crls.
+ if (debug != null) {
+ BigInteger sn = cert.getSerialNumber();
+ debug.println("RevocationChecker.checkApprovedCRLs() " +
+ "starting the final sweep...");
+ debug.println("RevocationChecker.checkApprovedCRLs()" +
+ " cert SN: " + sn.toString());
+ }
+
+ CRLReason reasonCode = CRLReason.UNSPECIFIED;
+ X509CRLEntryImpl entry = null;
+ for (X509CRL crl : approvedCRLs) {
+ X509CRLEntry e = crl.getRevokedCertificate(cert);
+ if (e != null) {
+ try {
+ entry = X509CRLEntryImpl.toImpl(e);
+ } catch (CRLException ce) {
+ throw new CertPathValidatorException(ce);
+ }
+ if (debug != null) {
+ debug.println("RevocationChecker.checkApprovedCRLs()"
+ + " CRL entry: " + entry.toString());
+ }
+
+ /*
+ * Abort CRL validation and throw exception if there are any
+ * unrecognized critical CRL entry extensions (see section
+ * 5.3 of RFC 3280).
+ */
+ Set<String> unresCritExts = entry.getCriticalExtensionOIDs();
+ if (unresCritExts != null && !unresCritExts.isEmpty()) {
+ /* remove any that we will process */
+ unresCritExts.remove(ReasonCode_Id.toString());
+ unresCritExts.remove(CertificateIssuer_Id.toString());
+ if (!unresCritExts.isEmpty()) {
+ if (debug != null) {
+ debug.println("Unrecognized "
+ + "critical extension(s) in revoked CRL entry: "
+ + unresCritExts);
+ }
+ throw new CertPathValidatorException
+ ("Could not determine revocation status", null, null,
+ -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
+ }
+ }
+
+ reasonCode = entry.getRevocationReason();
+ if (reasonCode == null) {
+ reasonCode = CRLReason.UNSPECIFIED;
+ }
+ Throwable t = new CertificateRevokedException
+ (entry.getRevocationDate(), reasonCode,
+ crl.getIssuerX500Principal(), entry.getExtensions());
+ throw new CertPathValidatorException(t.getMessage(), t,
+ null, -1, BasicReason.REVOKED);
+ }
+ }
+ }
+
+ private void checkOCSP(X509Certificate cert,
+ Collection<String> unresolvedCritExts)
+ throws CertPathValidatorException
+ {
+ X509CertImpl currCert = null;
+ try {
+ currCert = X509CertImpl.toImpl(cert);
+ } catch (CertificateException ce) {
+ throw new CertPathValidatorException(ce);
+ }
+
+ URI responderURI = (this.responderURI != null)
+ ? this.responderURI : getOCSPServerURI(currCert);
+
+ X509Certificate respCert = (responderCert == null) ? issuerCert
+ : responderCert;
+
+ // The algorithm constraints of the OCSP trusted responder certificate
+ // does not need to be checked in this code. The constraints will be
+ // checked when the responder's certificate is validated.
+
+ OCSPResponse response = null;
+ CertId certId = null;
+ try {
+ certId = new CertId(issuerCert, currCert.getSerialNumberObject());
+
+ // check if there is a stapled OCSP response available
+ byte[] responseBytes = ocspStapled.get(cert);
+ if (responseBytes != null) {
+ if (debug != null) {
+ debug.println("Found stapled OCSP response");
+ }
+ response = new OCSPResponse(responseBytes);
+
+ // verify the response
+ byte[] nonce = null;
+ for (Extension ext : ocspExtensions) {
+ if (ext.getId().equals("1.3.6.1.5.5.7.48.1.2")) {
+ nonce = ext.getValue();
+ }
+ }
+ response.verify(Collections.singletonList(certId), respCert,
+ params.date(), nonce);
+
+ } else {
+ response = OCSP.check(Collections.singletonList(certId),
+ responderURI, respCert, params.date(),
+ ocspExtensions);
+ }
+ } catch (IOException e) {
+ throw new CertPathValidatorException(e);
+ }
+
+ RevocationStatus rs =
+ (RevocationStatus)response.getSingleResponse(certId);
+ RevocationStatus.CertStatus certStatus = rs.getCertStatus();
+ if (certStatus == RevocationStatus.CertStatus.REVOKED) {
+ Throwable t = new CertificateRevokedException(
+ rs.getRevocationTime(), rs.getRevocationReason(),
+ respCert.getSubjectX500Principal(), rs.getSingleExtensions());
+ throw new CertPathValidatorException(t.getMessage(), t, null,
+ -1, BasicReason.REVOKED);
+ } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
+ throw new CertPathValidatorException(
+ "Certificate's revocation status is unknown", null,
+ params.certPath(), -1,
+ BasicReason.UNDETERMINED_REVOCATION_STATUS);
+ }
+ }
+
+ /*
+ * Removes any non-hexadecimal characters from a string.
+ */
+ private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
+ private static String stripOutSeparators(String value) {
+ char[] chars = value.toCharArray();
+ StringBuilder hexNumber = new StringBuilder();
+ for (int i = 0; i < chars.length; i++) {
+ if (HEX_DIGITS.indexOf(chars[i]) != -1) {
+ hexNumber.append(chars[i]);
+ }
+ }
+ return hexNumber.toString();
+ }
+
+ private static URI getOCSPServerURI(X509CertImpl cert)
+ throws CertPathValidatorException
+ {
+ // Examine the certificate's AuthorityInfoAccess extension
+ AuthorityInfoAccessExtension aia =
+ cert.getAuthorityInfoAccessExtension();
+ if (aia == null) {
+ throw new CertPathValidatorException(
+ "Must specify the location of an OCSP Responder");
+ }
+
+ List<AccessDescription> descriptions = aia.getAccessDescriptions();
+ for (AccessDescription description : descriptions) {
+ if (description.getAccessMethod().equals((Object)
+ AccessDescription.Ad_OCSP_Id)) {
+
+ GeneralName generalName = description.getAccessLocation();
+ if (generalName.getType() == GeneralNameInterface.NAME_URI) {
+ URIName uri = (URIName)generalName.getName();
+ return uri.getURI();
+ }
+ }
+ }
+
+ throw new CertPathValidatorException(
+ "Cannot find the location of the OCSP Responder");
+ }
+
+ /**
+ * Checks that a cert can be used to verify a CRL.
+ *
+ * @param cert an X509Certificate to check
+ * @return a boolean specifying if the cert is allowed to vouch for the
+ * validity of a CRL
+ */
+ static boolean certCanSignCrl(X509Certificate cert) {
+ // if the cert doesn't include the key usage ext, or
+ // the key usage ext asserts cRLSigning, return true,
+ // otherwise return false.
+ boolean[] keyUsage = cert.getKeyUsage();
+ if (keyUsage != null) {
+ return keyUsage[6];
+ }
+ return false;
+ }
+
+ /**
+ * Internal method that verifies a set of possible_crls,
+ * and sees if each is approved, based on the cert.
+ *
+ * @param crls a set of possible CRLs to test for acceptability
+ * @param cert the certificate whose revocation status is being checked
+ * @param signFlag <code>true</code> if prevKey was trusted to sign CRLs
+ * @param prevKey the public key of the issuer of cert
+ * @param reasonsMask the reason code mask
+ * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s>
+ * @return a collection of approved crls (or an empty collection)
+ */
+ private static final boolean[] ALL_REASONS =
+ {true, true, true, true, true, true, true, true, true};
+ private Collection<X509CRL> verifyPossibleCRLs(Set<X509CRL> crls,
+ X509Certificate cert,
+ PublicKey prevKey,
+ boolean signFlag,
+ boolean[] reasonsMask,
+ Set<TrustAnchor> anchors)
+ throws CertPathValidatorException
+ {
+ try {
+ X509CertImpl certImpl = X509CertImpl.toImpl(cert);
+ if (debug != null) {
+ debug.println("RevocationChecker.verifyPossibleCRLs: " +
+ "Checking CRLDPs for "
+ + certImpl.getSubjectX500Principal());
+ }
+ CRLDistributionPointsExtension ext =
+ certImpl.getCRLDistributionPointsExtension();
+ List<DistributionPoint> points = null;
+ if (ext == null) {
+ // assume a DP with reasons and CRLIssuer fields omitted
+ // and a DP name of the cert issuer.
+ // TODO add issuerAltName too
+ X500Name certIssuer = (X500Name)certImpl.getIssuerDN();
+ DistributionPoint point = new DistributionPoint(
+ new GeneralNames().add(new GeneralName(certIssuer)),
+ null, null);
+ points = Collections.singletonList(point);
+ } else {
+ points = ext.get(CRLDistributionPointsExtension.POINTS);
+ }
+ Set<X509CRL> results = new HashSet<>();
+ for (DistributionPoint point : points) {
+ for (X509CRL crl : crls) {
+ if (DistributionPointFetcher.verifyCRL(
+ certImpl, point, crl, reasonsMask, signFlag,
+ prevKey, params.sigProvider(), anchors,
+ certStores, params.date()))
+ {
+ results.add(crl);
+ }
+ }
+ if (Arrays.equals(reasonsMask, ALL_REASONS))
+ break;
+ }
+ return results;
+ } catch (CertificateException | CRLException | IOException e) {
+ if (debug != null) {
+ debug.println("Exception while verifying CRL: "+e.getMessage());
+ e.printStackTrace();
+ }
+ return Collections.emptySet();
+ }
+ }
+
+ /**
+ * We have a cert whose revocation status couldn't be verified by
+ * a CRL issued by the cert that issued the CRL. See if we can
+ * find a valid CRL issued by a separate key that can verify the
+ * revocation status of this certificate.
+ * <p>
+ * Note that this does not provide support for indirect CRLs,
+ * only CRLs signed with a different key (but the same issuer
+ * name) as the certificate being checked.
+ *
+ * @param currCert the <code>X509Certificate</code> to be checked
+ * @param prevKey the <code>PublicKey</code> that failed
+ * @param signFlag <code>true</code> if that key was trusted to sign CRLs
+ * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
+ * whose revocation status depends on the
+ * non-revoked status of this cert. To avoid
+ * circular dependencies, we assume they're
+ * revoked while checking the revocation
+ * status of this cert.
+ * @throws CertPathValidatorException if the cert's revocation status
+ * cannot be verified successfully with another key
+ */
+ private void verifyWithSeparateSigningKey(X509Certificate cert,
+ PublicKey prevKey,
+ boolean signFlag,
+ Set<X509Certificate> stackedCerts)
+ throws CertPathValidatorException
+ {
+ String msg = "revocation status";
+ if (debug != null) {
+ debug.println(
+ "RevocationChecker.verifyWithSeparateSigningKey()" +
+ " ---checking " + msg + "...");
+ }
+
+ // reject circular dependencies - RFC 3280 is not explicit on how
+ // to handle this, so we feel it is safest to reject them until
+ // the issue is resolved in the PKIX WG.
+ if ((stackedCerts != null) && stackedCerts.contains(cert)) {
+ if (debug != null) {
+ debug.println(
+ "RevocationChecker.verifyWithSeparateSigningKey()" +
+ " circular dependency");
+ }
+ throw new CertPathValidatorException
+ ("Could not determine revocation status", null, null,
+ -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
+ }
+
+ // Try to find another key that might be able to sign
+ // CRLs vouching for this cert.
+ // If prevKey wasn't trusted, maybe we just didn't have the right
+ // path to it. Don't rule that key out.
+ if (!signFlag) {
+ buildToNewKey(cert, null, stackedCerts);
+ } else {
+ buildToNewKey(cert, prevKey, stackedCerts);
+ }
+ }
+
+ /**
+ * Tries to find a CertPath that establishes a key that can be
+ * used to verify the revocation status of a given certificate.
+ * Ignores keys that have previously been tried. Throws a
+ * CertPathValidatorException if no such key could be found.
+ *
+ * @param currCert the <code>X509Certificate</code> to be checked
+ * @param prevKey the <code>PublicKey</code> of the certificate whose key
+ * cannot be used to vouch for the CRL and should be ignored
+ * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
+ * whose revocation status depends on the
+ * establishment of this path.
+ * @throws CertPathValidatorException on failure
+ */
+ private static final boolean [] CRL_SIGN_USAGE =
+ { false, false, false, false, false, false, true };
+ private void buildToNewKey(X509Certificate currCert,
+ PublicKey prevKey,
+ Set<X509Certificate> stackedCerts)
+ throws CertPathValidatorException
+ {
+
+ if (debug != null) {
+ debug.println("RevocationChecker.buildToNewKey()" +
+ " starting work");
+ }
+ Set<PublicKey> badKeys = new HashSet<>();
+ if (prevKey != null) {
+ badKeys.add(prevKey);
+ }
+ X509CertSelector certSel = new RejectKeySelector(badKeys);
+ certSel.setSubject(currCert.getIssuerX500Principal());
+ certSel.setKeyUsage(CRL_SIGN_USAGE);
+
+ Set<TrustAnchor> newAnchors = anchor == null ?
+ params.trustAnchors() :
+ Collections.singleton(anchor);
+
+ PKIXBuilderParameters builderParams;
+ try {
+ builderParams = new PKIXBuilderParameters(newAnchors, certSel);
+ } catch (InvalidAlgorithmParameterException iape) {
+ throw new RuntimeException(iape); // should never occur
+ }
+ builderParams.setInitialPolicies(params.initialPolicies());
+ builderParams.setCertStores(certStores);
+ builderParams.setExplicitPolicyRequired
+ (params.explicitPolicyRequired());
+ builderParams.setPolicyMappingInhibited
+ (params.policyMappingInhibited());
+ builderParams.setAnyPolicyInhibited(params.anyPolicyInhibited());
+ // Policy qualifiers must be rejected, since we don't have
+ // any way to convey them back to the application.
+ // That's the default, so no need to write code.
+ builderParams.setDate(params.date());
+ // CertPathCheckers need to be cloned to start from fresh state
+ builderParams.setCertPathCheckers(
+ params.getPKIXParameters().getCertPathCheckers());
+ builderParams.setSigProvider(params.sigProvider());
+
+ // Skip revocation during this build to detect circular
+ // references. But check revocation afterwards, using the
+ // key (or any other that works).
+ builderParams.setRevocationEnabled(false);
+
+ // check for AuthorityInformationAccess extension
+ if (Builder.USE_AIA == true) {
+ X509CertImpl currCertImpl = null;
+ try {
+ currCertImpl = X509CertImpl.toImpl(currCert);
+ } catch (CertificateException ce) {
+ // ignore but log it
+ if (debug != null) {
+ debug.println("RevocationChecker.buildToNewKey: " +
+ "error decoding cert: " + ce);
+ }
+ }
+ AuthorityInfoAccessExtension aiaExt = null;
+ if (currCertImpl != null) {
+ aiaExt = currCertImpl.getAuthorityInfoAccessExtension();
+ }
+ if (aiaExt != null) {
+ List<AccessDescription> adList = aiaExt.getAccessDescriptions();
+ if (adList != null) {
+ for (AccessDescription ad : adList) {
+ CertStore cs = URICertStore.getInstance(ad);
+ if (cs != null) {
+ if (debug != null) {
+ debug.println("adding AIAext CertStore");
+ }
+ builderParams.addCertStore(cs);
+ }
+ }
+ }
+ }
+ }
+
+ CertPathBuilder builder = null;
+ try {
+ builder = CertPathBuilder.getInstance("PKIX");
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new CertPathValidatorException(nsae);
+ }
+ while (true) {
+ try {
+ if (debug != null) {
+ debug.println("RevocationChecker.buildToNewKey()" +
+ " about to try build ...");
+ }
+ PKIXCertPathBuilderResult cpbr =
+ (PKIXCertPathBuilderResult)builder.build(builderParams);
+
+ if (debug != null) {
+ debug.println("RevocationChecker.buildToNewKey()" +
+ " about to check revocation ...");
+ }
+ // Now check revocation of all certs in path, assuming that
+ // the stackedCerts are revoked.
+ if (stackedCerts == null) {
+ stackedCerts = new HashSet<X509Certificate>();
+ }
+ stackedCerts.add(currCert);
+ TrustAnchor ta = cpbr.getTrustAnchor();
+ PublicKey prevKey2 = ta.getCAPublicKey();
+ if (prevKey2 == null) {
+ prevKey2 = ta.getTrustedCert().getPublicKey();
+ }
+ boolean signFlag = true;
+ List<? extends Certificate> cpList =
+ cpbr.getCertPath().getCertificates();
+ try {
+ for (int i = cpList.size()-1; i >= 0; i-- ) {
+ X509Certificate cert = (X509Certificate)cpList.get(i);
+
+ if (debug != null) {
+ debug.println("RevocationChecker.buildToNewKey()"
+ + " index " + i + " checking "
+ + cert);
+ }
+ checkCRLs(cert, prevKey2, signFlag, true,
+ stackedCerts, newAnchors);
+ signFlag = certCanSignCrl(cert);
+ prevKey2 = cert.getPublicKey();
+ }
+ } catch (CertPathValidatorException cpve) {
+ // ignore it and try to get another key
+ badKeys.add(cpbr.getPublicKey());
+ continue;
+ }
+
+ if (debug != null) {
+ debug.println("RevocationChecker.buildToNewKey()" +
+ " got key " + cpbr.getPublicKey());
+ }
+ // Now check revocation on the current cert using that key.
+ // If it doesn't check out, try to find a different key.
+ // And if we can't find a key, then return false.
+ PublicKey newKey = cpbr.getPublicKey();
+ try {
+ checkCRLs(currCert, newKey, true, false, null,
+ params.trustAnchors());
+ // If that passed, the cert is OK!
+ return;
+ } catch (CertPathValidatorException cpve) {
+ // If it is revoked, rethrow exception
+ if (cpve.getReason() == BasicReason.REVOKED) {
+ throw cpve;
+ }
+ // Otherwise, ignore the exception and
+ // try to get another key.
+ }
+ badKeys.add(newKey);
+ } catch (InvalidAlgorithmParameterException iape) {
+ throw new CertPathValidatorException(iape);
+ } catch (CertPathBuilderException cpbe) {
+ throw new CertPathValidatorException
+ ("Could not determine revocation status", null, null,
+ -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
+ }
+ }
+ }
+
+ /*
+ * This inner class extends the X509CertSelector to add an additional
+ * check to make sure the subject public key isn't on a particular list.
+ * This class is used by buildToNewKey() to make sure the builder doesn't
+ * end up with a CertPath to a public key that has already been rejected.
+ */
+ private static class RejectKeySelector extends X509CertSelector {
+ private final Set<PublicKey> badKeySet;
+
+ /**
+ * Creates a new <code>RejectKeySelector</code>.
+ *
+ * @param badPublicKeys a <code>Set</code> of
+ * <code>PublicKey</code>s that
+ * should be rejected (or <code>null</code>
+ * if no such check should be done)
+ */
+ RejectKeySelector(Set<PublicKey> badPublicKeys) {
+ this.badKeySet = badPublicKeys;
+ }
+
+ /**
+ * Decides whether a <code>Certificate</code> should be selected.
+ *
+ * @param cert the <code>Certificate</code> to be checked
+ * @return <code>true</code> if the <code>Certificate</code> should be
+ * selected, <code>false</code> otherwise
+ */
+ @Override
+ public boolean match(Certificate cert) {
+ if (!super.match(cert))
+ return(false);
+
+ if (badKeySet.contains(cert.getPublicKey())) {
+ if (debug != null)
+ debug.println("RejectKeySelector.match: bad key");
+ return false;
+ }
+
+ if (debug != null)
+ debug.println("RejectKeySelector.match: returning true");
+ return true;
+ }
+
+ /**
+ * Return a printable representation of the <code>CertSelector</code>.
+ *
+ * @return a <code>String</code> describing the contents of the
+ * <code>CertSelector</code>
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("RejectKeySelector: [\n");
+ sb.append(super.toString());
+ sb.append(badKeySet);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+}
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java Thu May 31 17:07:28 2012 -0400
@@ -26,10 +26,8 @@
package sun.security.provider.certpath;
import java.io.IOException;
-import java.security.AccessController;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
-import java.security.Principal;
import java.security.PublicKey;
import java.security.cert.*;
import java.security.cert.PKIXReason;
@@ -37,7 +35,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -45,9 +42,8 @@
import java.util.Set;
import javax.security.auth.x500.X500Principal;
-import sun.security.action.GetBooleanSecurityPropertyAction;
-import sun.security.x509.X500Name;
-import sun.security.x509.PKIXExtensions;
+import sun.security.provider.certpath.PKIX.BuilderParams;
+import static sun.security.x509.PKIXExtensions.*;
import sun.security.util.Debug;
/**
@@ -78,16 +74,12 @@
/*
* private objects shared by methods
*/
- private PKIXBuilderParameters buildParams;
+ private BuilderParams buildParams;
private CertificateFactory cf;
private boolean pathCompleted = false;
- private X500Principal targetSubjectDN;
private PolicyNode policyTreeResult;
private TrustAnchor trustAnchor;
private PublicKey finalPublicKey;
- private X509CertSelector targetSel;
- private List<CertStore> orderedCertStores;
- private boolean onlyEECert = false;
/**
* Create an instance of <code>SunCertPathBuilder</code>.
@@ -100,9 +92,11 @@
} catch (CertificateException e) {
throw new CertPathBuilderException(e);
}
- onlyEECert = AccessController.doPrivileged(
- new GetBooleanSecurityPropertyAction
- ("com.sun.security.onlyCheckRevocationOfEECert"));
+ }
+
+ @Override
+ public CertPathChecker engineGetRevocationChecker() {
+ return new RevocationChecker();
}
/**
@@ -125,6 +119,7 @@
* @throws InvalidAlgorithmParameterException if the given parameters are
* inappropriate for this certification path builder.
*/
+ @Override
public CertPathBuilderResult engineBuild(CertPathParameters params)
throws CertPathBuilderException, InvalidAlgorithmParameterException {
@@ -132,66 +127,20 @@
debug.println("SunCertPathBuilder.engineBuild(" + params + ")");
}
- if (!(params instanceof PKIXBuilderParameters)) {
- throw new InvalidAlgorithmParameterException("inappropriate " +
- "parameter type, must be an instance of PKIXBuilderParameters");
- }
-
- boolean buildForward = true;
- if (params instanceof SunCertPathBuilderParameters) {
- buildForward =
- ((SunCertPathBuilderParameters)params).getBuildForward();
- }
-
- buildParams = (PKIXBuilderParameters)params;
-
- /* Check mandatory parameters */
-
- // Make sure that none of the trust anchors include name constraints
- // (not supported).
- for (TrustAnchor anchor : buildParams.getTrustAnchors()) {
- if (anchor.getNameConstraints() != null) {
- throw new InvalidAlgorithmParameterException
- ("name constraints in trust anchor not supported");
- }
- }
+ buildParams = PKIX.checkBuilderParams(params);
+ return build();
+ }
- CertSelector sel = buildParams.getTargetCertConstraints();
- if (!(sel instanceof X509CertSelector)) {
- throw new InvalidAlgorithmParameterException("the "
- + "targetCertConstraints parameter must be an "
- + "X509CertSelector");
- }
- targetSel = (X509CertSelector)sel;
- targetSubjectDN = targetSel.getSubject();
- if (targetSubjectDN == null) {
- X509Certificate targetCert = targetSel.getCertificate();
- if (targetCert != null) {
- targetSubjectDN = targetCert.getSubjectX500Principal();
- }
- }
- // reorder CertStores so that local CertStores are tried first
- orderedCertStores =
- new ArrayList<CertStore>(buildParams.getCertStores());
- Collections.sort(orderedCertStores, new CertStoreComparator());
- if (targetSubjectDN == null) {
- targetSubjectDN = getTargetSubjectDN(orderedCertStores, targetSel);
- }
- if (targetSubjectDN == null) {
- throw new InvalidAlgorithmParameterException
- ("Could not determine unique target subject");
- }
-
- List<List<Vertex>> adjList = new ArrayList<List<Vertex>>();
- CertPathBuilderResult result =
- buildCertPath(buildForward, false, adjList);
+ private PKIXCertPathBuilderResult build() throws CertPathBuilderException {
+ List<List<Vertex>> adjList = new ArrayList<>();
+ PKIXCertPathBuilderResult result = buildCertPath(false, adjList);
if (result == null) {
if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild: 2nd pass");
}
// try again
adjList.clear();
- result = buildCertPath(buildForward, true, adjList);
+ result = buildCertPath(true, adjList);
if (result == null) {
throw new SunCertPathBuilderException("unable to find valid "
+ "certification path to requested target",
@@ -201,24 +150,23 @@
return result;
}
- private CertPathBuilderResult buildCertPath(boolean buildForward,
- boolean searchAllCertStores, List<List<Vertex>> adjList)
- throws CertPathBuilderException {
-
+ private PKIXCertPathBuilderResult buildCertPath(boolean searchAllCertStores,
+ List<List<Vertex>> adjList)
+ throws CertPathBuilderException
+ {
// Init shared variables and build certification path
pathCompleted = false;
trustAnchor = null;
finalPublicKey = null;
policyTreeResult = null;
- LinkedList<X509Certificate> certPathList =
- new LinkedList<X509Certificate>();
+ LinkedList<X509Certificate> certPathList = new LinkedList<>();
try {
- if (buildForward) {
+ if (buildParams.buildForward()) {
buildForward(adjList, certPathList, searchAllCertStores);
} else {
buildReverse(adjList, certPathList);
}
- } catch (Exception e) {
+ } catch (GeneralSecurityException | IOException e) {
if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild() exception in "
+ "build");
@@ -242,11 +190,11 @@
Collections.reverse(certPathList);
return new SunCertPathBuilderResult(
- cf.generateCertPath(certPathList), this.trustAnchor,
+ cf.generateCertPath(certPathList), trustAnchor,
policyTreeResult, finalPublicKey,
new AdjacencyList(adjList));
}
- } catch (Exception e) {
+ } catch (CertificateException e) {
if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild() exception "
+ "in wrap-up");
@@ -264,12 +212,13 @@
* Private build reverse method.
*/
private void buildReverse(List<List<Vertex>> adjacencyList,
- LinkedList<X509Certificate> certPathList) throws Exception
+ LinkedList<X509Certificate> certPathList)
+ throws GeneralSecurityException, IOException
{
if (debug != null) {
debug.println("SunCertPathBuilder.buildReverse()...");
debug.println("SunCertPathBuilder.buildReverse() InitialPolicies: "
- + buildParams.getInitialPolicies());
+ + buildParams.initialPolicies());
}
ReverseState currentState = new ReverseState();
@@ -281,12 +230,12 @@
* Perform a search using each trust anchor, until a valid
* path is found
*/
- Iterator<TrustAnchor> iter = buildParams.getTrustAnchors().iterator();
+ Iterator<TrustAnchor> iter = buildParams.trustAnchors().iterator();
while (iter.hasNext()) {
TrustAnchor anchor = iter.next();
/* check if anchor satisfies target constraints */
- if (anchorIsTarget(anchor, targetSel)) {
+ if (anchorIsTarget(anchor, buildParams.targetCertConstraints())) {
this.trustAnchor = anchor;
this.pathCompleted = true;
this.finalPublicKey = anchor.getTrustedCert().getPublicKey();
@@ -294,22 +243,16 @@
}
/* Initialize current state */
- currentState.initState(buildParams.getMaxPathLength(),
- buildParams.isExplicitPolicyRequired(),
- buildParams.isPolicyMappingInhibited(),
- buildParams.isAnyPolicyInhibited(),
- buildParams.getCertPathCheckers());
- currentState.updateState(anchor);
- // init the crl checker
- currentState.crlChecker =
- new CrlRevocationChecker(null, buildParams, null, onlyEECert);
+ currentState.initState(buildParams);
+ currentState.updateState(anchor, buildParams);
+
currentState.algorithmChecker = new AlgorithmChecker(anchor);
currentState.untrustedChecker = new UntrustedChecker();
try {
depthFirstSearchReverse(null, currentState,
- new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
- certPathList);
- } catch (Exception e) {
+ new ReverseBuilder(buildParams),
+ adjacencyList, certPathList);
+ } catch (GeneralSecurityException | IOException e) {
// continue on error if more anchors to try
if (iter.hasNext())
continue;
@@ -335,7 +278,8 @@
* Private build forward method.
*/
private void buildForward(List<List<Vertex>> adjacencyList,
- LinkedList<X509Certificate> certPathList, boolean searchAllCertStores)
+ LinkedList<X509Certificate> certPathList,
+ boolean searchAllCertStores)
throws GeneralSecurityException, IOException
{
if (debug != null) {
@@ -344,21 +288,18 @@
/* Initialize current state */
ForwardState currentState = new ForwardState();
- currentState.initState(buildParams.getCertPathCheckers());
+ currentState.initState(buildParams.certPathCheckers());
/* Initialize adjacency list */
adjacencyList.clear();
adjacencyList.add(new LinkedList<Vertex>());
- // init the crl checker
- currentState.crlChecker
- = new CrlRevocationChecker(null, buildParams, null, onlyEECert);
currentState.untrustedChecker = new UntrustedChecker();
- depthFirstSearchForward(targetSubjectDN, currentState,
- new ForwardBuilder
- (buildParams, targetSubjectDN, searchAllCertStores, onlyEECert),
- adjacencyList, certPathList);
+ depthFirstSearchForward(buildParams.targetSubject(), currentState,
+ new ForwardBuilder(buildParams,
+ searchAllCertStores),
+ adjacencyList, certPathList);
}
/*
@@ -376,27 +317,28 @@
* @param dN the distinguished name being currently searched for certs
* @param currentState the current PKIX validation state
*/
- void depthFirstSearchForward(X500Principal dN, ForwardState currentState,
- ForwardBuilder builder, List<List<Vertex>> adjList,
- LinkedList<X509Certificate> certPathList)
+ private void depthFirstSearchForward(X500Principal dN,
+ ForwardState currentState,
+ ForwardBuilder builder,
+ List<List<Vertex>> adjList,
+ LinkedList<X509Certificate> cpList)
throws GeneralSecurityException, IOException
{
- //XXX This method should probably catch & handle exceptions
-
if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward(" + dN
- + ", " + currentState.toString() + ")");
+ + ", " + currentState.toString() + ")");
}
/*
* Find all the certificates issued to dN which
* satisfy the PKIX certification path constraints.
*/
- List<Vertex> vertices = addVertices
- (builder.getMatchingCerts(currentState, orderedCertStores), adjList);
+ Collection<X509Certificate> certs =
+ builder.getMatchingCerts(currentState, buildParams.certStores());
+ List<Vertex> vertices = addVertices(certs, adjList);
if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward(): "
- + "certs.size=" + vertices.size());
+ + "certs.size=" + vertices.size());
}
/*
@@ -416,14 +358,14 @@
* the next matching cert is tried.
*/
ForwardState nextState = (ForwardState) currentState.clone();
- X509Certificate cert = (X509Certificate) vertex.getCertificate();
+ X509Certificate cert = vertex.getCertificate();
try {
- builder.verifyCert(cert, nextState, certPathList);
+ builder.verifyCert(cert, nextState, cpList);
} catch (GeneralSecurityException gse) {
if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward()"
- + ": validation failed: " + gse);
+ + ": validation failed: " + gse);
gse.printStackTrace();
}
vertex.setThrowable(gse);
@@ -441,51 +383,44 @@
*/
if (builder.isPathCompleted(cert)) {
- BasicChecker basicChecker = null;
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchForward()"
- + ": commencing final verification");
+ + ": commencing final verification");
- ArrayList<X509Certificate> appendedCerts =
- new ArrayList<X509Certificate>(certPathList);
+ List<X509Certificate> appendedCerts = new ArrayList<>(cpList);
/*
* if the trust anchor selected is specified as a trusted
* public key rather than a trusted cert, then verify this
* cert (which is signed by the trusted public key), but
- * don't add it yet to the certPathList
+ * don't add it yet to the cpList
*/
if (builder.trustAnchor.getTrustedCert() == null) {
appendedCerts.add(0, cert);
}
- HashSet<String> initExpPolSet = new HashSet<String>(1);
- initExpPolSet.add(PolicyChecker.ANY_POLICY);
+ Set<String> initExpPolSet =
+ Collections.singleton(PolicyChecker.ANY_POLICY);
PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
+ List<PKIXCertPathChecker> checkers = new ArrayList<>();
PolicyChecker policyChecker
- = new PolicyChecker(buildParams.getInitialPolicies(),
- appendedCerts.size(),
- buildParams.isExplicitPolicyRequired(),
- buildParams.isPolicyMappingInhibited(),
- buildParams.isAnyPolicyInhibited(),
- buildParams.getPolicyQualifiersRejected(),
- rootNode);
+ = new PolicyChecker(buildParams.initialPolicies(),
+ appendedCerts.size(),
+ buildParams.explicitPolicyRequired(),
+ buildParams.policyMappingInhibited(),
+ buildParams.anyPolicyInhibited(),
+ buildParams.policyQualifiersRejected(),
+ rootNode);
- List<PKIXCertPathChecker> userCheckers = new
- ArrayList<PKIXCertPathChecker>
- (buildParams.getCertPathCheckers());
- int mustCheck = 0;
- userCheckers.add(mustCheck, policyChecker);
- mustCheck++;
+ checkers.add(policyChecker);
// add the algorithm checker
- userCheckers.add(mustCheck,
- new AlgorithmChecker(builder.trustAnchor));
- mustCheck++;
+ checkers.add(new AlgorithmChecker(builder.trustAnchor));
+ BasicChecker basicChecker = null;
if (nextState.keyParamsNeeded()) {
PublicKey rootKey = cert.getPublicKey();
if (builder.trustAnchor.getTrustedCert() == null) {
@@ -500,24 +435,38 @@
(cert.getSubjectX500Principal(), rootKey, null);
// add the basic checker
- basicChecker = new BasicChecker(anchor,
- builder.date,
- buildParams.getSigProvider(),
- true);
- userCheckers.add(mustCheck, basicChecker);
- mustCheck++;
+ basicChecker = new BasicChecker(anchor, buildParams.date(),
+ buildParams.sigProvider(),
+ true);
+ checkers.add(basicChecker);
+ }
+
+ buildParams.setCertPath(cf.generateCertPath(appendedCerts));
- // add the crl revocation checker
- if (buildParams.isRevocationEnabled()) {
- userCheckers.add(mustCheck, new CrlRevocationChecker
- (anchor, buildParams, null, onlyEECert));
- mustCheck++;
+ boolean revCheckerAdded = false;
+ List<PKIXCertPathChecker> ckrs = buildParams.certPathCheckers();
+ for (PKIXCertPathChecker ckr : ckrs) {
+ if (ckr instanceof PKIXRevocationChecker) {
+ revCheckerAdded = true;
+ // if it's our own, initialize it
+ if (ckr instanceof RevocationChecker)
+ ((RevocationChecker)ckr).init(builder.trustAnchor,
+ buildParams);
}
}
- // Why we don't need BasicChecker and CrlRevocationChecker
+ // only add a RevocationChecker if revocation is enabled and
+ // a PKIXRevocationChecker has not already been added
+ if (buildParams.revocationEnabled() && !revCheckerAdded) {
+ checkers.add(new RevocationChecker(builder.trustAnchor,
+ buildParams));
+ }
+
+ checkers.addAll(ckrs);
+
+ // Why we don't need BasicChecker and RevocationChecker
// if nextState.keyParamsNeeded() is false?
- for (int i=0; i<appendedCerts.size(); i++) {
+ for (int i = 0; i < appendedCerts.size(); i++) {
X509Certificate currCert = appendedCerts.get(i);
if (debug != null)
debug.println("current subject = "
@@ -528,18 +477,15 @@
unresCritExts = Collections.<String>emptySet();
}
- for (int j=0; j<userCheckers.size(); j++) {
- PKIXCertPathChecker currChecker = userCheckers.get(j);
- if (j < mustCheck ||
- !currChecker.isForwardCheckingSupported()) {
+ for (PKIXCertPathChecker currChecker : checkers) {
+ if (!currChecker.isForwardCheckingSupported()) {
if (i == 0) {
currChecker.init(false);
// The user specified
// AlgorithmChecker may not be
// able to set the trust anchor until now.
- if (j >= mustCheck &&
- currChecker instanceof AlgorithmChecker) {
+ if (currChecker instanceof AlgorithmChecker) {
((AlgorithmChecker)currChecker).
trySetTrustAnchor(builder.trustAnchor);
}
@@ -565,7 +511,7 @@
* are capable of processing.
*/
for (PKIXCertPathChecker checker :
- buildParams.getCertPathCheckers())
+ buildParams.certPathCheckers())
{
if (checker.isForwardCheckingSupported()) {
Set<String> suppExts =
@@ -577,24 +523,16 @@
}
if (!unresCritExts.isEmpty()) {
- unresCritExts.remove
- (PKIXExtensions.BasicConstraints_Id.toString());
- unresCritExts.remove
- (PKIXExtensions.NameConstraints_Id.toString());
- unresCritExts.remove
- (PKIXExtensions.CertificatePolicies_Id.toString());
- unresCritExts.remove
- (PKIXExtensions.PolicyMappings_Id.toString());
- unresCritExts.remove
- (PKIXExtensions.PolicyConstraints_Id.toString());
- unresCritExts.remove
- (PKIXExtensions.InhibitAnyPolicy_Id.toString());
- unresCritExts.remove(PKIXExtensions.
+ unresCritExts.remove(BasicConstraints_Id.toString());
+ unresCritExts.remove(NameConstraints_Id.toString());
+ unresCritExts.remove(CertificatePolicies_Id.toString());
+ unresCritExts.remove(PolicyMappings_Id.toString());
+ unresCritExts.remove(PolicyConstraints_Id.toString());
+ unresCritExts.remove(InhibitAnyPolicy_Id.toString());
+ unresCritExts.remove(
SubjectAlternativeName_Id.toString());
- unresCritExts.remove
- (PKIXExtensions.KeyUsage_Id.toString());
- unresCritExts.remove
- (PKIXExtensions.ExtendedKeyUsage_Id.toString());
+ unresCritExts.remove(KeyUsage_Id.toString());
+ unresCritExts.remove(ExtendedKeyUsage_Id.toString());
if (!unresCritExts.isEmpty()) {
throw new CertPathValidatorException
@@ -611,10 +549,10 @@
/*
* if the user specified a trusted public key rather than
* trusted certs, then add this cert (which is signed by
- * the trusted public key) to the certPathList
+ * the trusted public key) to the cpList
*/
if (builder.trustAnchor.getTrustedCert() == null)
- builder.addCertToPath(cert, certPathList);
+ builder.addCertToPath(cert, cpList);
// Save the trust anchor
this.trustAnchor = builder.trustAnchor;
@@ -625,10 +563,10 @@
finalPublicKey = basicChecker.getPublicKey();
} else {
Certificate finalCert;
- if (certPathList.size() == 0) {
+ if (cpList.isEmpty()) {
finalCert = builder.trustAnchor.getTrustedCert();
} else {
- finalCert = certPathList.get(certPathList.size()-1);
+ finalCert = cpList.getLast();
}
finalPublicKey = finalCert.getPublicKey();
}
@@ -636,7 +574,7 @@
policyTreeResult = policyChecker.getPolicyTree();
return;
} else {
- builder.addCertToPath(cert, certPathList);
+ builder.addCertToPath(cert, cpList);
}
/* Update the PKIX state */
@@ -650,8 +588,8 @@
vertex.setIndex(adjList.size() - 1);
/* recursively search for matching certs at next dN */
- depthFirstSearchForward(cert.getIssuerX500Principal(),
- nextState, builder, adjList, certPathList);
+ depthFirstSearchForward(cert.getIssuerX500Principal(), nextState,
+ builder, adjList, cpList);
/*
* If path has been completed, return ASAP!
@@ -667,8 +605,8 @@
*/
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchForward()"
- + ": backtracking");
- builder.removeFinalCertFromPath(certPathList);
+ + ": backtracking");
+ builder.removeFinalCertFromPath(cpList);
}
}
}
@@ -688,9 +626,11 @@
* @param dN the distinguished name being currently searched for certs
* @param currentState the current PKIX validation state
*/
- void depthFirstSearchReverse(X500Principal dN, ReverseState currentState,
- ReverseBuilder builder, List<List<Vertex>> adjList,
- LinkedList<X509Certificate> certPathList)
+ private void depthFirstSearchReverse(X500Principal dN,
+ ReverseState currentState,
+ ReverseBuilder builder,
+ List<List<Vertex>> adjList,
+ LinkedList<X509Certificate> cpList)
throws GeneralSecurityException, IOException
{
if (debug != null)
@@ -701,8 +641,9 @@
* Find all the certificates issued by dN which
* satisfy the PKIX certification path constraints.
*/
- List<Vertex> vertices = addVertices
- (builder.getMatchingCerts(currentState, orderedCertStores), adjList);
+ Collection<X509Certificate> certs =
+ builder.getMatchingCerts(currentState, buildParams.certStores());
+ List<Vertex> vertices = addVertices(certs, adjList);
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchReverse(): "
+ "certs.size=" + vertices.size());
@@ -722,9 +663,9 @@
* the next matching cert is tried.
*/
ReverseState nextState = (ReverseState) currentState.clone();
- X509Certificate cert = (X509Certificate) vertex.getCertificate();
+ X509Certificate cert = vertex.getCertificate();
try {
- builder.verifyCert(cert, nextState, certPathList);
+ builder.verifyCert(cert, nextState, cpList);
} catch (GeneralSecurityException gse) {
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
@@ -738,7 +679,7 @@
* self-signed cert) and update state
*/
if (!currentState.isInitial())
- builder.addCertToPath(cert, certPathList);
+ builder.addCertToPath(cert, cpList);
// save trust anchor
this.trustAnchor = currentState.trustAnchor;
@@ -787,7 +728,7 @@
/* recursively search for matching certs at next dN */
depthFirstSearchReverse(cert.getSubjectX500Principal(), nextState,
- builder, adjList, certPathList);
+ builder, adjList, cpList);
/*
* If path has been completed, return ASAP!
@@ -805,7 +746,7 @@
debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
+ ": backtracking");
if (!currentState.isInitial())
- builder.removeFinalCertFromPath(certPathList);
+ builder.removeFinalCertFromPath(cpList);
}
}
if (debug != null)
@@ -817,13 +758,14 @@
* Adds a collection of matching certificates to the
* adjacency list.
*/
- private List<Vertex> addVertices(Collection<X509Certificate> certs,
- List<List<Vertex>> adjList) {
+ private static List<Vertex> addVertices(Collection<X509Certificate> certs,
+ List<List<Vertex>> adjList)
+ {
List<Vertex> l = adjList.get(adjList.size() - 1);
for (X509Certificate cert : certs) {
- Vertex v = new Vertex(cert);
- l.add(v);
+ Vertex v = new Vertex(cert);
+ l.add(v);
}
return l;
@@ -833,53 +775,13 @@
* Returns true if trust anchor certificate matches specified
* certificate constraints.
*/
- private boolean anchorIsTarget(TrustAnchor anchor, X509CertSelector sel) {
+ private static boolean anchorIsTarget(TrustAnchor anchor,
+ CertSelector sel)
+ {
X509Certificate anchorCert = anchor.getTrustedCert();
if (anchorCert != null) {
return sel.match(anchorCert);
}
return false;
}
-
- /**
- * Comparator that orders CertStores so that local CertStores come before
- * remote CertStores.
- */
- private static class CertStoreComparator implements Comparator<CertStore> {
- public int compare(CertStore store1, CertStore store2) {
- if (Builder.isLocalCertStore(store1)) {
- return -1;
- } else {
- return 1;
- }
- }
- }
-
- /**
- * Returns the target subject DN from the first X509Certificate that
- * is fetched that matches the specified X509CertSelector.
- */
- private X500Principal getTargetSubjectDN(List<CertStore> stores,
- X509CertSelector targetSel) {
- for (CertStore store : stores) {
- try {
- Collection<? extends Certificate> targetCerts =
- (Collection<? extends Certificate>)
- store.getCertificates(targetSel);
- if (!targetCerts.isEmpty()) {
- X509Certificate targetCert =
- (X509Certificate)targetCerts.iterator().next();
- return targetCert.getSubjectX500Principal();
- }
- } catch (CertStoreException e) {
- // ignore but log it
- if (debug != null) {
- debug.println("SunCertPathBuilder.getTargetSubjectDN: " +
- "non-fatal exception retrieving certs: " + e);
- e.printStackTrace();
- }
- }
- }
- return null;
- }
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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,12 +25,11 @@
package sun.security.provider.certpath;
-import java.util.Set;
-
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.*;
+import java.util.Set;
/**
* This class specifies the set of parameters used as input for the Sun
@@ -120,8 +119,9 @@
*
* @return a formatted string describing the parameters.
*/
+ @Override
public String toString() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.append("[\n");
sb.append(super.toString());
sb.append(" Build Forward Flag: " + String.valueOf(buildForward) + "\n");
--- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, 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
@@ -213,6 +213,7 @@
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
+ @Override
@SuppressWarnings("unchecked")
public synchronized Collection<X509Certificate> engineGetCertificates
(CertSelector selector) throws CertStoreException {
@@ -322,6 +323,7 @@
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
+ @Override
@SuppressWarnings("unchecked")
public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException {
@@ -418,14 +420,14 @@
URICertStoreParameters(URI uri) {
this.uri = uri;
}
- public boolean equals(Object obj) {
+ @Override public boolean equals(Object obj) {
if (!(obj instanceof URICertStoreParameters)) {
return false;
}
URICertStoreParameters params = (URICertStoreParameters) obj;
return uri.equals(params.uri);
}
- public int hashCode() {
+ @Override public int hashCode() {
if (hashCode == 0) {
int result = 17;
result = 37*result + uri.hashCode();
@@ -433,7 +435,7 @@
}
return hashCode;
}
- public Object clone() {
+ @Override public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
--- a/jdk/src/share/classes/sun/security/provider/certpath/Vertex.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/Vertex.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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,12 +25,11 @@
package sun.security.provider.certpath;
-import sun.security.util.Debug;
-
-import java.security.cert.Certificate;
+import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
+import sun.security.util.Debug;
import sun.security.x509.AuthorityKeyIdentifierExtension;
import sun.security.x509.KeyIdentifier;
import sun.security.x509.SubjectKeyIdentifierExtension;
@@ -50,17 +49,17 @@
public class Vertex {
private static final Debug debug = Debug.getInstance("certpath");
- private Certificate cert;
- private int index;
- private Throwable throwable;
+ private X509Certificate cert;
+ private int index;
+ private Throwable throwable;
/**
* Constructor; creates vertex with index of -1
* Use setIndex method to set another index.
*
- * @param cert Certificate associated with vertex
+ * @param cert X509Certificate associated with vertex
*/
- Vertex(Certificate cert) {
+ Vertex(X509Certificate cert) {
this.cert = cert;
this.index = -1;
}
@@ -68,9 +67,9 @@
/**
* return the certificate for this vertex
*
- * @returns Certificate
+ * @returns X509Certificate
*/
- public Certificate getCertificate() {
+ public X509Certificate getCertificate() {
return cert;
}
@@ -121,6 +120,7 @@
*
* @returns String representation of vertex
*/
+ @Override
public String toString() {
return certToString() + throwableToString() + indexToString();
}
@@ -132,70 +132,65 @@
* @returns String representation of certificate info
*/
public String certToString() {
- String out = "";
- if (cert == null || ! (cert instanceof X509Certificate))
- return "Cert: Not an X509Certificate\n";
+ StringBuilder sb = new StringBuilder();
X509CertImpl x509Cert = null;
try {
- x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+ x509Cert = X509CertImpl.toImpl(cert);
} catch (CertificateException ce) {
if (debug != null) {
debug.println("Vertex.certToString() unexpected exception");
ce.printStackTrace();
}
- return out;
+ return sb.toString();
}
- out = "Issuer: " + x509Cert.getIssuerX500Principal() + "\n";
- out = out + "Subject: " + x509Cert.getSubjectX500Principal() + "\n";
- out = out + "SerialNum: " + (x509Cert.getSerialNumber()).toString(16) + "\n";
- out = out + "Expires: " + x509Cert.getNotAfter().toString() + "\n";
+ sb.append("Issuer: ").append
+ (x509Cert.getIssuerX500Principal()).append("\n");
+ sb.append("Subject: ").append
+ (x509Cert.getSubjectX500Principal()).append("\n");
+ sb.append("SerialNum: ").append
+ (x509Cert.getSerialNumber().toString(16)).append("\n");
+ sb.append("Expires: ").append
+ (x509Cert.getNotAfter().toString()).append("\n");
boolean[] iUID = x509Cert.getIssuerUniqueID();
if (iUID != null) {
- out = out + "IssuerUID: ";
- for (int i=0; i < iUID.length; i++) {
- out = out + (iUID[i]?1:0);
+ sb.append("IssuerUID: ");
+ for (boolean b : iUID) {
+ sb.append(b ? 1 : 0);
}
- out = out + "\n";
+ sb.append("\n");
}
boolean[] sUID = x509Cert.getSubjectUniqueID();
if (sUID != null) {
- out = out + "SubjectUID: ";
- for (int i=0; i< sUID.length; i++) {
- out = out + (sUID[i]?1:0);
+ sb.append("SubjectUID: ");
+ for (boolean b : sUID) {
+ sb.append(b ? 1 : 0);
}
- out = out + "\n";
+ sb.append("\n");
}
- SubjectKeyIdentifierExtension sKeyID = null;
try {
- sKeyID = x509Cert.getSubjectKeyIdentifierExtension();
+ SubjectKeyIdentifierExtension sKeyID =
+ x509Cert.getSubjectKeyIdentifierExtension();
if (sKeyID != null) {
KeyIdentifier keyID = sKeyID.get(
SubjectKeyIdentifierExtension.KEY_ID);
- out = out + "SubjKeyID: " + keyID.toString();
+ sb.append("SubjKeyID: ").append(keyID.toString());
}
- } catch (Exception e) {
+ AuthorityKeyIdentifierExtension aKeyID =
+ x509Cert.getAuthorityKeyIdentifierExtension();
+ if (aKeyID != null) {
+ KeyIdentifier keyID = (KeyIdentifier)aKeyID.get(
+ AuthorityKeyIdentifierExtension.KEY_ID);
+ sb.append("AuthKeyID: ").append(keyID.toString());
+ }
+ } catch (IOException e) {
if (debug != null) {
debug.println("Vertex.certToString() unexpected exception");
e.printStackTrace();
}
}
- AuthorityKeyIdentifierExtension aKeyID = null;
- try {
- aKeyID = x509Cert.getAuthorityKeyIdentifierExtension();
- if (aKeyID != null) {
- KeyIdentifier keyID = (KeyIdentifier)aKeyID.get(
- AuthorityKeyIdentifierExtension.KEY_ID);
- out = out + "AuthKeyID: " + keyID.toString();
- }
- } catch (Exception e) {
- if (debug != null) {
- debug.println("Vertex.certToString() 2 unexpected exception");
- e.printStackTrace();
- }
- }
- return out;
+ return sb.toString();
}
/**
@@ -205,13 +200,13 @@
* @returns String form of exception (or "none")
*/
public String throwableToString() {
- String out = "Exception: ";
+ StringBuilder sb = new StringBuilder("Exception: ");
if (throwable != null)
- out = out + throwable.toString();
+ sb.append(throwable.toString());
else
- out = out + "null";
- out = out + "\n";
- return out;
+ sb.append("null");
+ sb.append("\n");
+ return sb.toString();
}
/**
@@ -222,10 +217,10 @@
* @returns String form of index as "Last cert? [Yes/No]
*/
public String moreToString() {
- String out = "Last cert? ";
- out = out + ((index == -1)?"Yes":"No");
- out = out + "\n";
- return out;
+ StringBuilder sb = new StringBuilder("Last cert? ");
+ sb.append((index == -1) ? "Yes" : "No");
+ sb.append("\n");
+ return sb.toString();
}
/**
@@ -235,7 +230,6 @@
* @returns String form of index as "Index: [numeric index]"
*/
public String indexToString() {
- String out = "Index: " + index + "\n";
- return out;
+ return "Index: " + index + "\n";
}
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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,9 +33,10 @@
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
+import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.util.*;
-import java.security.cert.CertPath;
+
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@@ -44,7 +45,6 @@
import sun.security.util.DerOutputStream;
import sun.security.util.DerInputStream;
-
/**
* A {@link java.security.cert.CertPath CertPath} (certification path)
* consisting exclusively of
@@ -83,7 +83,7 @@
private static final Collection<String> encodingList;
static {
- List<String> list = new ArrayList<String>(2);
+ List<String> list = new ArrayList<>(2);
list.add(PKIPATH_ENCODING);
list.add(PKCS7_ENCODING);
encodingList = Collections.unmodifiableCollection(list);
@@ -272,6 +272,7 @@
* @return the encoded bytes
* @exception CertificateEncodingException if an encoding error occurs
*/
+ @Override
public byte[] getEncoded() throws CertificateEncodingException {
// @@@ Should cache the encoded form
return encodePKIPATH();
@@ -342,6 +343,7 @@
* @exception CertificateEncodingException if an encoding error occurs or
* the encoding requested is not supported
*/
+ @Override
public byte[] getEncoded(String encoding)
throws CertificateEncodingException {
switch (encoding) {
@@ -376,6 +378,7 @@
* @return an <code>Iterator</code> over the names of the supported
* encodings (as Strings)
*/
+ @Override
public Iterator<String> getEncodings() {
return getEncodingsStatic();
}
@@ -387,6 +390,7 @@
* @return an immutable <code>List</code> of <code>X509Certificate</code>s
* (may be empty, but not null)
*/
+ @Override
public List<X509Certificate> getCertificates() {
return certs;
}
--- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java Thu May 31 17:07:28 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -207,13 +207,14 @@
*
* @return A String describing the contents of the pair.
*/
+ @Override
public String toString() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.append("X.509 Certificate Pair: [\n");
if (forward != null)
- sb.append(" Forward: " + forward + "\n");
+ sb.append(" Forward: ").append(forward).append("\n");
if (reverse != null)
- sb.append(" Reverse: " + reverse + "\n");
+ sb.append(" Reverse: ").append(reverse).append("\n");
sb.append("]");
return sb.toString();
}
--- a/jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java Tue May 29 14:56:48 2012 -0700
+++ b/jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java Thu May 31 17:07:28 2012 -0400
@@ -31,6 +31,7 @@
import java.security.cert.X509CRLEntry;
import java.math.BigInteger;
import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@@ -500,6 +501,9 @@
}
public Map<String, java.security.cert.Extension> getExtensions() {
+ if (extensions == null) {
+ return Collections.emptyMap();
+ }
Collection<Extension> exts = extensions.getAllExtensions();
HashMap<String, java.security.cert.Extension> map =
new HashMap<String, java.security.cert.Extension>(exts.size());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java Thu May 31 17:07:28 2012 -0400
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6854712
+ * @summary Basic unit test for PKIXRevocationChecker
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertPathChecker;
+import java.security.cert.CertPathValidator;
+import java.security.cert.Extension;
+import java.security.cert.PKIXRevocationChecker;
+import java.security.cert.PKIXRevocationChecker.Option;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class UnitTest {
+
+ public static void main(String[] args) throws Exception {
+
+ CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+ CertPathChecker cpc = cpv.getRevocationChecker();
+ PKIXRevocationChecker prc = (PKIXRevocationChecker)cpc;
+
+ System.out.println("Testing that get methods return null or " +
+ "empty lists/sets/maps");
+ requireNull(prc.getOCSPResponder(), "getOCSPResponder()");
+ requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()");
+ requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()");
+ requireEmpty(prc.getOCSPStapledResponses(),
+ "getOCSPStapledResponses()");
+ requireEmpty(prc.getOptions(), "getOptions()");
+
+ System.out.println("Testing that get methods return same parameters " +
+ "that are passed to set methods");
+ URI uri = new URI("http://localhost");
+ prc.setOCSPResponder(uri);
+ requireEquals(uri, prc.getOCSPResponder(), "getOCSPResponder()");
+
+ X509Certificate cert = getCert();
+ prc.setOCSPResponderCert(cert);
+ requireEquals(cert, prc.getOCSPResponderCert(),
+ "getOCSPResponderCert()");
+
+ List<Extension> exts = new ArrayList<>();
+ for (String oid : cert.getNonCriticalExtensionOIDs()) {
+ System.out.println(oid);
+ exts.add(new ExtensionImpl(oid,
+ cert.getExtensionValue(oid), false));
+ }
+ prc.setOCSPExtensions(exts);
+ requireEquals(exts, prc.getOCSPExtensions(), "getOCSPExtensions()");
+
+ Set<Option> options = EnumSet.of(Option.ONLY_END_ENTITY);
+ prc.setOptions(options);
+ requireEquals(options, prc.getOptions(), "getOptions()");
+
+ System.out.println("Testing that parameters are re-initialized to " +
+ "default values if null is passed to set methods");
+ prc.setOCSPResponder(null);
+ requireNull(prc.getOCSPResponder(), "getOCSPResponder()");
+ prc.setOCSPResponderCert(null);
+ requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()");
+ prc.setOCSPExtensions(null);
+ requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()");
+ prc.setOCSPStapledResponses(null);
+ requireEmpty(prc.getOCSPStapledResponses(),
+ "getOCSPStapledResponses()");
+ prc.setOptions(null);
+ requireEmpty(prc.getOptions(), "getOptions()");
+ }
+
+ static void requireNull(Object o, String msg) throws Exception {
+ if (o != null) {
+ throw new Exception("FAILED: " + msg + " must return null");
+ }
+ }
+
+ static void requireEmpty(Map<?,?> m, String msg) throws Exception {
+ if (!m.isEmpty()) {
+ throw new Exception("FAILED: " + msg + " must return an empty map");
+ }
+ }
+
+ static void requireEmpty(List<?> l, String msg) throws Exception {
+ if (!l.isEmpty()) {
+ throw new Exception("FAILED: " + msg +" must return an empty list");
+ }
+ }
+
+ static void requireEmpty(Set<?> s, String msg) throws Exception {
+ if (!s.isEmpty()) {
+ throw new Exception("FAILED: " + msg + " must return an empty set");
+ }
+ }
+
+ static void requireEquals(Object a, Object b, String msg) throws Exception {
+ if (!a.equals(b)) {
+ throw new Exception("FAILED: " + msg + " does not return the " +
+ "same object that was set");
+ }
+ }
+
+ static X509Certificate getCert() throws Exception {
+ String b64 =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBLTCB2KADAgECAgEDMA0GCSqGSIb3DQEBBAUAMA0xCzAJBgNVBAMTAkNBMB4X\n" +
+ "DTAyMTEwNzExNTcwM1oXDTIyMTEwNzExNTcwM1owFTETMBEGA1UEAxMKRW5kIEVu\n" +
+ "dGl0eTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDVBDfF+uBr5s5jzzDs1njKlZNt\n" +
+ "h8hHzEt3ASh67Peos+QrDzgpUyFXT6fdW2h7iPf0ifjM8eW2xa+3EnPjjU5jAgMB\n" +
+ "AAGjGzAZMBcGA1UdIAQQMA4wBgYEVR0gADAEBgIqADANBgkqhkiG9w0BAQQFAANB\n" +
+ "AFo//WOboCNOCcA1fvcWW9oc4MvV8ZPvFIAbyEbgyFd4id5lGDTRbRPvvNZRvdsN\n" +
+ "NM2gXYr+f87NHIXc9EF3pzw=\n" +
+ "-----END CERTIFICATE-----";
+
+ InputStream is = new ByteArrayInputStream(b64.getBytes("UTF-8"));
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ return (X509Certificate)cf.generateCertificate(is);
+ }
+
+ static class ExtensionImpl implements Extension {
+ private final String oid;
+ private final byte[] val;
+ private final boolean critical;
+
+ ExtensionImpl(String oid, byte[] val, boolean critical) {
+ this.oid = oid;
+ this.val = val;
+ this.critical = critical;
+ }
+
+ public void encode(OutputStream out) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getId() {
+ return oid;
+ }
+
+ public byte[] getValue() {
+ return val.clone();
+ }
+
+ public boolean isCritical() {
+ return critical;
+ }
+ }
+}