1
package org.bouncycastle.jce.provider;
3
import java.io.IOException;
4
import java.security.InvalidAlgorithmParameterException;
5
import java.security.Principal;
6
import java.security.cert.CertPath;
7
import java.security.cert.CertPathBuilderException;
8
import java.security.cert.CertPathBuilderResult;
9
import java.security.cert.CertPathBuilderSpi;
10
import java.security.cert.CertPathParameters;
11
import java.security.cert.CertPathValidator;
12
import java.security.cert.CertificateFactory;
13
import java.security.cert.CertificateParsingException;
14
import java.security.cert.PKIXBuilderParameters;
15
import java.security.cert.PKIXCertPathBuilderResult;
16
import java.security.cert.PKIXCertPathValidatorResult;
17
import java.security.cert.X509Certificate;
18
import java.util.ArrayList;
19
import java.util.Collection;
20
import java.util.HashSet;
21
import java.util.Iterator;
22
import java.util.List;
25
import javax.security.auth.x500.X500Principal;
27
import org.bouncycastle.jce.exception.ExtCertPathBuilderException;
28
import org.bouncycastle.util.Selector;
29
import org.bouncycastle.x509.ExtendedPKIXBuilderParameters;
30
import org.bouncycastle.x509.X509AttributeCertStoreSelector;
31
import org.bouncycastle.x509.X509AttributeCertificate;
32
import org.bouncycastle.x509.X509CertStoreSelector;
34
public class PKIXAttrCertPathBuilderSpi
35
extends CertPathBuilderSpi
39
* Build and validate a CertPath using the given parameter.
41
* @param params PKIXBuilderParameters object containing all information to
44
public CertPathBuilderResult engineBuild(CertPathParameters params)
45
throws CertPathBuilderException, InvalidAlgorithmParameterException
47
if (!(params instanceof PKIXBuilderParameters)
48
&& !(params instanceof ExtendedPKIXBuilderParameters))
50
throw new InvalidAlgorithmParameterException(
51
"Parameters must be an instance of "
52
+ PKIXBuilderParameters.class.getName() + " or "
53
+ ExtendedPKIXBuilderParameters.class.getName()
57
ExtendedPKIXBuilderParameters pkixParams;
58
if (params instanceof ExtendedPKIXBuilderParameters)
60
pkixParams = (ExtendedPKIXBuilderParameters) params;
64
pkixParams = (ExtendedPKIXBuilderParameters) ExtendedPKIXBuilderParameters
65
.getInstance((PKIXBuilderParameters) params);
70
List certPathList = new ArrayList();
71
X509AttributeCertificate cert;
73
// search target certificates
75
Selector certSelect = pkixParams.getTargetConstraints();
76
if (!(certSelect instanceof X509AttributeCertStoreSelector))
78
throw new CertPathBuilderException(
79
"TargetConstraints must be an instance of "
80
+ X509AttributeCertStoreSelector.class.getName()
81
+ " for "+this.getClass().getName()+" class.");
86
targets = CertPathValidatorUtilities.findCertificates((X509AttributeCertStoreSelector)certSelect, pkixParams.getStores());
88
catch (AnnotatedException e)
90
throw new ExtCertPathBuilderException("Error finding target attribute certificate.", e);
93
if (targets.isEmpty())
95
throw new CertPathBuilderException(
96
"No attribute certificate found matching targetContraints.");
99
CertPathBuilderResult result = null;
101
// check all potential target certificates
102
targetIter = targets.iterator();
103
while (targetIter.hasNext() && result == null)
105
cert = (X509AttributeCertificate) targetIter.next();
107
X509CertStoreSelector selector = new X509CertStoreSelector();
108
Principal[] principals = cert.getIssuer().getPrincipals();
109
Set issuers = new HashSet();
110
for (int i = 0; i < principals.length; i++)
114
if (principals[i] instanceof X500Principal)
116
selector.setSubject(((X500Principal)principals[i]).getEncoded());
118
issuers.addAll(CertPathValidatorUtilities.findCertificates(selector, pkixParams.getStores()));
119
issuers.addAll(CertPathValidatorUtilities.findCertificates(selector, pkixParams.getCertStores()));
121
catch (AnnotatedException e)
123
throw new ExtCertPathBuilderException(
124
"Public key certificate for attribute certificate cannot be searched.",
127
catch (IOException e)
129
throw new ExtCertPathBuilderException(
130
"cannot encode X500Principal.",
134
if (issuers.isEmpty())
136
throw new CertPathBuilderException(
137
"Public key certificate for attribute certificate cannot be found.");
139
Iterator it = issuers.iterator();
140
while (it.hasNext() && result == null)
142
result = build(cert, (X509Certificate)it.next(), pkixParams, certPathList);
146
if (result == null && certPathException != null)
148
throw new ExtCertPathBuilderException(
149
"Possible certificate chain could not be validated.",
153
if (result == null && certPathException == null)
155
throw new CertPathBuilderException(
156
"Unable to find certificate chain.");
162
private Exception certPathException;
164
private CertPathBuilderResult build(X509AttributeCertificate attrCert, X509Certificate tbvCert,
165
ExtendedPKIXBuilderParameters pkixParams, List tbvPath)
168
// If tbvCert is readily present in tbvPath, it indicates having run
169
// into a cycle in the
171
if (tbvPath.contains(tbvCert))
175
// step out, the certificate is not allowed to appear in a certification
177
if (pkixParams.getExcludedCerts().contains(tbvCert))
181
// test if certificate path exceeds maximum length
182
if (pkixParams.getMaxPathLength() != -1)
184
if (tbvPath.size() - 1 > pkixParams.getMaxPathLength())
190
tbvPath.add(tbvCert);
192
CertificateFactory cFact;
193
CertPathValidator validator;
194
CertPathBuilderResult builderResult = null;
198
cFact = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
199
validator = CertPathValidator.getInstance("RFC3281", BouncyCastleProvider.PROVIDER_NAME);
204
throw new RuntimeException(
205
"Exception creating support classes.");
210
// check whether the issuer of <tbvCert> is a TrustAnchor
211
if (CertPathValidatorUtilities.findTrustAnchor(tbvCert, pkixParams.getTrustAnchors(),
212
pkixParams.getSigProvider()) != null)
215
PKIXCertPathValidatorResult result;
218
certPath = cFact.generateCertPath(tbvPath);
222
throw new AnnotatedException(
223
"Certification path could not be constructed from certificate list.",
229
result = (PKIXCertPathValidatorResult) validator.validate(
230
certPath, pkixParams);
234
throw new AnnotatedException(
235
"Certification path could not be validated.",
239
return new PKIXCertPathBuilderResult(certPath, result
240
.getTrustAnchor(), result.getPolicyTree(), result
246
// add additional X.509 stores from locations in certificate
249
CertPathValidatorUtilities.addAdditionalStoresFromAltNames(tbvCert, pkixParams);
251
catch (CertificateParsingException e)
253
throw new AnnotatedException(
254
"No additional X.509 stores can be added from certificate locations.",
257
Collection issuers = new HashSet();
258
// try to get the issuer certificate from one
262
issuers.addAll(CertPathValidatorUtilities.findIssuerCerts(tbvCert, pkixParams));
264
catch (AnnotatedException e)
266
throw new AnnotatedException(
267
"Cannot find issuer certificate for certificate in certification path.",
270
if (issuers.isEmpty())
272
throw new AnnotatedException(
273
"No issuer certificate for certificate in certification path found.");
275
Iterator it = issuers.iterator();
277
while (it.hasNext() && builderResult == null)
279
X509Certificate issuer = (X509Certificate) it.next();
280
// TODO Use CertPathValidatorUtilities.isSelfIssued(issuer)?
281
// if untrusted self signed certificate continue
282
if (issuer.getIssuerX500Principal().equals(
283
issuer.getSubjectX500Principal()))
287
builderResult = build(attrCert, issuer, pkixParams, tbvPath);
291
catch (AnnotatedException e)
293
certPathException = new AnnotatedException(
294
"No valid certification path could be build.", e);
296
if (builderResult == null)
298
tbvPath.remove(tbvCert);
300
return builderResult;