summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXAttrCertPathBuilderSpi.java
diff options
context:
space:
mode:
authorSergio Giro <sgiro@google.com>2016-02-01 18:52:42 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2016-02-01 18:52:42 +0000
commit9218edabd1ef9852bc2f13115dcadc81b442dd6c (patch)
tree8229ff72c8cbb06f49dce3a8382930919fa6fc2b /bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXAttrCertPathBuilderSpi.java
parent9b30eb05e5be69d51881a0d1b31e503e97acd784 (diff)
parent397d32894b89b506dc318e0f83446187c9b76ebe (diff)
downloadandroid_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.tar.gz
android_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.tar.bz2
android_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.zip
Merge "Merge remote-tracking branch 'aosp/upstream-master' into merge-152-from-upstream"
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXAttrCertPathBuilderSpi.java')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXAttrCertPathBuilderSpi.java361
1 files changed, 361 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXAttrCertPathBuilderSpi.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXAttrCertPathBuilderSpi.java
new file mode 100644
index 0000000..115c198
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXAttrCertPathBuilderSpi.java
@@ -0,0 +1,361 @@
+package org.bouncycastle.jce.provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.Principal;
+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.CertStore;
+import java.security.cert.CertStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+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 java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.jcajce.PKIXCertStoreSelector;
+import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters;
+import org.bouncycastle.jce.exception.ExtCertPathBuilderException;
+import org.bouncycastle.util.Encodable;
+import org.bouncycastle.util.Selector;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.util.StoreException;
+import org.bouncycastle.x509.ExtendedPKIXBuilderParameters;
+import org.bouncycastle.x509.ExtendedPKIXParameters;
+import org.bouncycastle.x509.X509AttributeCertStoreSelector;
+import org.bouncycastle.x509.X509AttributeCertificate;
+import org.bouncycastle.x509.X509CertStoreSelector;
+import org.bouncycastle.x509.X509Store;
+
+public class PKIXAttrCertPathBuilderSpi
+ 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)
+ && !(params instanceof PKIXExtendedBuilderParameters))
+ {
+ throw new InvalidAlgorithmParameterException(
+ "Parameters must be an instance of "
+ + PKIXBuilderParameters.class.getName() + " or "
+ + PKIXExtendedBuilderParameters.class.getName()
+ + ".");
+ }
+
+ List targetStores = new ArrayList();
+
+ PKIXExtendedBuilderParameters paramsPKIX;
+ if (params instanceof PKIXBuilderParameters)
+ {
+ PKIXExtendedBuilderParameters.Builder paramsPKIXBldr = new PKIXExtendedBuilderParameters.Builder((PKIXBuilderParameters)params);
+
+ if (params instanceof ExtendedPKIXParameters)
+ {
+ ExtendedPKIXBuilderParameters extPKIX = (ExtendedPKIXBuilderParameters)params;
+
+ paramsPKIXBldr.addExcludedCerts(extPKIX.getExcludedCerts());
+ paramsPKIXBldr.setMaxPathLength(extPKIX.getMaxPathLength());
+ targetStores = extPKIX.getStores();
+ }
+
+ paramsPKIX = paramsPKIXBldr.build();
+ }
+ else
+ {
+ paramsPKIX = (PKIXExtendedBuilderParameters)params;
+ }
+
+ Collection targets;
+ Iterator targetIter;
+ List certPathList = new ArrayList();
+ X509AttributeCertificate cert;
+
+ // search target certificates
+
+ Selector certSelect = paramsPKIX.getBaseParameters().getTargetConstraints();
+ if (!(certSelect instanceof X509AttributeCertStoreSelector))
+ {
+ throw new CertPathBuilderException(
+ "TargetConstraints must be an instance of "
+ + X509AttributeCertStoreSelector.class.getName()
+ + " for "+this.getClass().getName()+" class.");
+ }
+
+
+ try
+ {
+ targets = findCertificates((X509AttributeCertStoreSelector)certSelect, targetStores);
+ }
+ catch (AnnotatedException e)
+ {
+ throw new ExtCertPathBuilderException("Error finding target attribute certificate.", e);
+ }
+
+ if (targets.isEmpty())
+ {
+ throw new CertPathBuilderException(
+ "No attribute certificate found matching targetContraints.");
+ }
+
+ CertPathBuilderResult result = null;
+
+ // check all potential target certificates
+ targetIter = targets.iterator();
+ while (targetIter.hasNext() && result == null)
+ {
+ cert = (X509AttributeCertificate) targetIter.next();
+
+ X509CertStoreSelector selector = new X509CertStoreSelector();
+ Principal[] principals = cert.getIssuer().getPrincipals();
+ Set issuers = new HashSet();
+ for (int i = 0; i < principals.length; i++)
+ {
+ try
+ {
+ if (principals[i] instanceof X500Principal)
+ {
+ selector.setSubject(((X500Principal)principals[i]).getEncoded());
+ }
+ PKIXCertStoreSelector certStoreSelector = new PKIXCertStoreSelector.Builder(selector).build();
+ issuers.addAll(CertPathValidatorUtilities.findCertificates(certStoreSelector, paramsPKIX.getBaseParameters().getCertStores()));
+ issuers.addAll(CertPathValidatorUtilities.findCertificates(certStoreSelector, paramsPKIX.getBaseParameters().getCertificateStores()));
+ }
+ catch (AnnotatedException e)
+ {
+ throw new ExtCertPathBuilderException(
+ "Public key certificate for attribute certificate cannot be searched.",
+ e);
+ }
+ catch (IOException e)
+ {
+ throw new ExtCertPathBuilderException(
+ "cannot encode X500Principal.",
+ e);
+ }
+ }
+ if (issuers.isEmpty())
+ {
+ throw new CertPathBuilderException(
+ "Public key certificate for attribute certificate cannot be found.");
+ }
+ Iterator it = issuers.iterator();
+ while (it.hasNext() && result == null)
+ {
+ result = build(cert, (X509Certificate)it.next(), paramsPKIX, certPathList);
+ }
+ }
+
+ if (result == null && certPathException != null)
+ {
+ throw new ExtCertPathBuilderException(
+ "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;
+
+ private CertPathBuilderResult build(X509AttributeCertificate attrCert, X509Certificate tbvCert,
+ PKIXExtendedBuilderParameters 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("RFC3281", 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.getBaseParameters().getTrustAnchors(),
+ pkixParams.getBaseParameters().getSigProvider()) != null)
+ {
+ CertPath certPath;
+ PKIXCertPathValidatorResult result;
+ 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
+ {
+ List stores = new ArrayList();
+
+ stores.addAll(pkixParams.getBaseParameters().getCertificateStores());
+ // add additional X.509 stores from locations in certificate
+ try
+ {
+ stores.addAll(CertPathValidatorUtilities.getAdditionalStoresFromAltNames(tbvCert.getExtensionValue(Extension.issuerAlternativeName.getId()), pkixParams.getBaseParameters().getNamedCertificateStoreMap()));
+ }
+ catch (CertificateParsingException e)
+ {
+ throw new AnnotatedException(
+ "No additional 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.getBaseParameters().getCertStores(), stores));
+ }
+ 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();
+ // TODO Use CertPathValidatorUtilities.isSelfIssued(issuer)?
+ // if untrusted self signed certificate continue
+ if (issuer.getIssuerX500Principal().equals(
+ issuer.getSubjectX500Principal()))
+ {
+ continue;
+ }
+ builderResult = build(attrCert, issuer, pkixParams, tbvPath);
+ }
+ }
+ }
+ catch (AnnotatedException e)
+ {
+ certPathException = new AnnotatedException(
+ "No valid certification path could be build.", e);
+ }
+ if (builderResult == null)
+ {
+ tbvPath.remove(tbvCert);
+ }
+ return builderResult;
+ }
+
+ protected static Collection findCertificates(X509AttributeCertStoreSelector certSelect,
+ List certStores)
+ throws AnnotatedException
+ {
+ Set certs = new HashSet();
+ Iterator iter = certStores.iterator();
+
+ while (iter.hasNext())
+ {
+ Object obj = iter.next();
+
+ if (obj instanceof Store)
+ {
+ Store certStore = (Store)obj;
+ try
+ {
+ certs.addAll(certStore.getMatches(certSelect));
+ }
+ catch (StoreException e)
+ {
+ throw new AnnotatedException(
+ "Problem while picking certificates from X.509 store.", e);
+ }
+ }
+ }
+ return certs;
+ }
+}