aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathBuilderSpi.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathBuilderSpi.java')
-rw-r--r--libraries/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathBuilderSpi.java261
1 files changed, 261 insertions, 0 deletions
diff --git a/libraries/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathBuilderSpi.java b/libraries/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathBuilderSpi.java
new file mode 100644
index 000000000..e060b4f02
--- /dev/null
+++ b/libraries/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathBuilderSpi.java
@@ -0,0 +1,261 @@
+package org.spongycastle.jce.provider;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathBuilderException;
+import java.security.cert.CertPathBuilderResult;
+import java.security.cert.CertPathBuilderSpi;
+import java.security.cert.CertPathParameters;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXCertPathBuilderResult;
+import java.security.cert.PKIXCertPathValidatorResult;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.spongycastle.jce.exception.ExtCertPathBuilderException;
+import org.spongycastle.util.Selector;
+import org.spongycastle.x509.ExtendedPKIXBuilderParameters;
+import org.spongycastle.x509.X509CertStoreSelector;
+
+/**
+ * Implements the PKIX CertPathBuilding algorithm for BouncyCastle.
+ *
+ * @see CertPathBuilderSpi
+ */
+public class PKIXCertPathBuilderSpi
+ extends CertPathBuilderSpi
+{
+ /**
+ * Build and validate a CertPath using the given parameter.
+ *
+ * @param params PKIXBuilderParameters object containing all information to
+ * build the CertPath
+ */
+ public CertPathBuilderResult engineBuild(CertPathParameters params)
+ throws CertPathBuilderException, InvalidAlgorithmParameterException
+ {
+ if (!(params instanceof PKIXBuilderParameters)
+ && !(params instanceof ExtendedPKIXBuilderParameters))
+ {
+ throw new InvalidAlgorithmParameterException(
+ "Parameters must be an instance of "
+ + PKIXBuilderParameters.class.getName() + " or "
+ + ExtendedPKIXBuilderParameters.class.getName() + ".");
+ }
+
+ ExtendedPKIXBuilderParameters pkixParams = null;
+ if (params instanceof ExtendedPKIXBuilderParameters)
+ {
+ pkixParams = (ExtendedPKIXBuilderParameters) params;
+ }
+ else
+ {
+ pkixParams = (ExtendedPKIXBuilderParameters) ExtendedPKIXBuilderParameters
+ .getInstance((PKIXBuilderParameters) params);
+ }
+
+ Collection targets;
+ Iterator targetIter;
+ List certPathList = new ArrayList();
+ X509Certificate cert;
+
+ // search target certificates
+
+ Selector certSelect = pkixParams.getTargetConstraints();
+ if (!(certSelect instanceof X509CertStoreSelector))
+ {
+ throw new CertPathBuilderException(
+ "TargetConstraints must be an instance of "
+ + X509CertStoreSelector.class.getName() + " for "
+ + this.getClass().getName() + " class.");
+ }
+
+ try
+ {
+ targets = CertPathValidatorUtilities.findCertificates((X509CertStoreSelector)certSelect, pkixParams.getStores());
+ targets.addAll(CertPathValidatorUtilities.findCertificates((X509CertStoreSelector)certSelect, pkixParams.getCertStores()));
+ }
+ catch (AnnotatedException e)
+ {
+ throw new ExtCertPathBuilderException(
+ "Error finding target certificate.", e);
+ }
+
+ if (targets.isEmpty())
+ {
+
+ throw new CertPathBuilderException(
+ "No certificate found matching targetContraints.");
+ }
+
+ CertPathBuilderResult result = null;
+
+ // check all potential target certificates
+ targetIter = targets.iterator();
+ while (targetIter.hasNext() && result == null)
+ {
+ cert = (X509Certificate) targetIter.next();
+ result = build(cert, pkixParams, certPathList);
+ }
+
+ if (result == null && certPathException != null)
+ {
+ if (certPathException instanceof AnnotatedException)
+ {
+ throw new CertPathBuilderException(certPathException.getMessage(), certPathException.getCause());
+ }
+ throw new CertPathBuilderException(
+ "Possible certificate chain could not be validated.",
+ certPathException);
+ }
+
+ if (result == null && certPathException == null)
+ {
+ throw new CertPathBuilderException(
+ "Unable to find certificate chain.");
+ }
+
+ return result;
+ }
+
+ private Exception certPathException;
+
+ protected CertPathBuilderResult build(X509Certificate tbvCert,
+ ExtendedPKIXBuilderParameters pkixParams, List tbvPath)
+ {
+ // If tbvCert is readily present in tbvPath, it indicates having run
+ // into a cycle in the
+ // PKI graph.
+ if (tbvPath.contains(tbvCert))
+ {
+ return null;
+ }
+ // step out, the certificate is not allowed to appear in a certification
+ // chain.
+ if (pkixParams.getExcludedCerts().contains(tbvCert))
+ {
+ return null;
+ }
+ // test if certificate path exceeds maximum length
+ if (pkixParams.getMaxPathLength() != -1)
+ {
+ if (tbvPath.size() - 1 > pkixParams.getMaxPathLength())
+ {
+ return null;
+ }
+ }
+
+ tbvPath.add(tbvCert);
+
+ CertificateFactory cFact;
+ CertPathValidator validator;
+ CertPathBuilderResult builderResult = null;
+
+ try
+ {
+ cFact = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
+ validator = CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME);
+ }
+ catch (Exception e)
+ {
+ // cannot happen
+ throw new RuntimeException("Exception creating support classes.");
+ }
+
+ try
+ {
+ // check whether the issuer of <tbvCert> is a TrustAnchor
+ if (CertPathValidatorUtilities.findTrustAnchor(tbvCert, pkixParams.getTrustAnchors(),
+ pkixParams.getSigProvider()) != null)
+ {
+ // exception message from possibly later tried certification
+ // chains
+ CertPath certPath = null;
+ PKIXCertPathValidatorResult result = null;
+ try
+ {
+ certPath = cFact.generateCertPath(tbvPath);
+ }
+ catch (Exception e)
+ {
+ throw new AnnotatedException(
+ "Certification path could not be constructed from certificate list.",
+ e);
+ }
+
+ try
+ {
+ result = (PKIXCertPathValidatorResult) validator.validate(
+ certPath, pkixParams);
+ }
+ catch (Exception e)
+ {
+ throw new AnnotatedException(
+ "Certification path could not be validated.", e);
+ }
+
+ return new PKIXCertPathBuilderResult(certPath, result
+ .getTrustAnchor(), result.getPolicyTree(), result
+ .getPublicKey());
+
+ }
+ else
+ {
+ // add additional X.509 stores from locations in certificate
+ try
+ {
+ CertPathValidatorUtilities.addAdditionalStoresFromAltNames(
+ tbvCert, pkixParams);
+ }
+ catch (CertificateParsingException e)
+ {
+ throw new AnnotatedException(
+ "No additiontal X.509 stores can be added from certificate locations.",
+ e);
+ }
+ Collection issuers = new HashSet();
+ // try to get the issuer certificate from one
+ // of the stores
+ try
+ {
+ issuers.addAll(CertPathValidatorUtilities.findIssuerCerts(tbvCert, pkixParams));
+ }
+ catch (AnnotatedException e)
+ {
+ throw new AnnotatedException(
+ "Cannot find issuer certificate for certificate in certification path.",
+ e);
+ }
+ if (issuers.isEmpty())
+ {
+ throw new AnnotatedException(
+ "No issuer certificate for certificate in certification path found.");
+ }
+ Iterator it = issuers.iterator();
+
+ while (it.hasNext() && builderResult == null)
+ {
+ X509Certificate issuer = (X509Certificate) it.next();
+ builderResult = build(issuer, pkixParams, tbvPath);
+ }
+ }
+ }
+ catch (AnnotatedException e)
+ {
+ certPathException = e;
+ }
+ if (builderResult == null)
+ {
+ tbvPath.remove(tbvCert);
+ }
+ return builderResult;
+ }
+
+}