Skip to content

Commit 86afabf

Browse files
committed
Refactor CertPathValidatorUtilities.findTrustAnchor
1 parent bad4f4e commit 86afabf

2 files changed

Lines changed: 99 additions & 119 deletions

File tree

‎prov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java‎

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -175,104 +175,97 @@ protected static TrustAnchor findTrustAnchor(
175175
}
176176

177177
/**
178-
* Search the given Set of TrustAnchor's for one that is the
179-
* issuer of the given X509 certificate. Uses the specified
180-
* provider for signature verification, or the default provider
181-
* if null.
178+
* Return the first of the given trust anchors that names the issuer of the given certificate and whose public
179+
* key verifies it, or null if there is none. Uses the specified provider for signature verification, or the
180+
* default provider if null.
182181
*
183182
* @param cert the X509 certificate
184183
* @param trustAnchors a Set of TrustAnchor's
185184
* @param sigProvider the provider to use for signature verification
186185
* @return the <code>TrustAnchor</code> object if found or
187186
* <code>null</code> if not.
188-
* @throws AnnotatedException if a TrustAnchor was found but the signature verification
189-
* on the given certificate has thrown an exception.
187+
* @throws AnnotatedException if a trust anchor named the issuer, but none of those that did verified the
188+
* certificate.
190189
*/
191190
protected static TrustAnchor findTrustAnchor(
192191
X509Certificate cert,
193192
Set trustAnchors,
194193
String sigProvider)
195194
throws AnnotatedException
196195
{
197-
TrustAnchor trust = null;
198-
PublicKey trustPublicKey = null;
199-
Exception invalidKeyEx = null;
196+
X500Principal certIssuer = cert.getIssuerX500Principal();
197+
X500Name certIssuerName = null;
200198

201-
X509CertSelector certSelectX509 = new X509CertSelector();
199+
Exception invalidKeyEx = null;
202200

203-
final X500Principal certIssuerPrincipal = cert.getIssuerX500Principal();
204-
certSelectX509.setSubject(certIssuerPrincipal);
201+
for (Iterator it = trustAnchors.iterator(); it.hasNext();)
202+
{
203+
TrustAnchor trust = (TrustAnchor)it.next();
205204

206-
X500Name certIssuerName = null;
205+
PublicKey trustPublicKey;
207206

208-
Iterator iter = trustAnchors.iterator();
209-
while (iter.hasNext() && trust == null)
210-
{
211-
trust = (TrustAnchor)iter.next();
212-
if (trust.getTrustedCert() != null)
207+
// A TrustAnchor is built either from a trusted certificate, or from a name and a public key, so when
208+
// there is no trusted certificate both the CA name and its public key are present.
209+
X509Certificate trustedCert = trust.getTrustedCert();
210+
if (trustedCert != null)
213211
{
214-
if (certSelectX509.match(trust.getTrustedCert()))
215-
{
216-
trustPublicKey = trust.getTrustedCert().getPublicKey();
217-
}
218-
else
212+
if (!certIssuer.equals(trustedCert.getSubjectX500Principal()))
219213
{
220-
trust = null;
214+
continue;
221215
}
216+
217+
trustPublicKey = trustedCert.getPublicKey();
222218
}
223-
else if (trust.getCA() != null
224-
&& trust.getCAName() != null
225-
&& trust.getCAPublicKey() != null)
219+
else
226220
{
227221
if (certIssuerName == null)
228222
{
229-
certIssuerName = X500Name.getInstance(certIssuerPrincipal.getEncoded());
223+
certIssuerName = X500Name.getInstance(certIssuer.getEncoded());
230224
}
231225

232-
try
233-
{
234-
X500Name caName = X500Name.getInstance(trust.getCA().getEncoded());
235-
236-
if (certIssuerName.equals(caName))
237-
{
238-
trustPublicKey = trust.getCAPublicKey();
239-
}
240-
else
241-
{
242-
trust = null;
243-
}
244-
}
245-
catch (IllegalArgumentException ex)
226+
if (!isCAName(certIssuerName, trust))
246227
{
247-
trust = null;
228+
continue;
248229
}
230+
231+
trustPublicKey = trust.getCAPublicKey();
249232
}
250-
else
233+
234+
try
251235
{
252-
trust = null;
236+
verifyX509Certificate(cert, trustPublicKey, sigProvider);
237+
return trust;
253238
}
254-
255-
if (trustPublicKey != null)
239+
catch (Exception e)
256240
{
257-
try
241+
// Anchors sharing the issuer's subject DN can fail in turn; report the first failure.
242+
if (invalidKeyEx == null)
258243
{
259-
verifyX509Certificate(cert, trustPublicKey, sigProvider);
260-
}
261-
catch (Exception ex)
262-
{
263-
invalidKeyEx = ex;
264-
trust = null;
265-
trustPublicKey = null;
244+
invalidKeyEx = e;
266245
}
267246
}
268247
}
269248

270-
if (trust == null && invalidKeyEx != null)
249+
if (invalidKeyEx != null)
271250
{
272251
throw new AnnotatedException("TrustAnchor found but certificate validation failed.", invalidKeyEx);
273252
}
274253

275-
return trust;
254+
return null;
255+
}
256+
257+
private static boolean isCAName(X500Name certIssuerName, TrustAnchor trust)
258+
{
259+
try
260+
{
261+
X500Name caName = X500Name.getInstance(trust.getCA().getEncoded());
262+
263+
return certIssuerName.equals(caName);
264+
}
265+
catch (IllegalArgumentException e)
266+
{
267+
return false;
268+
}
276269
}
277270

278271
static boolean isIssuerTrustAnchor(

‎prov/src/main/jdk1.4/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java‎

Lines changed: 49 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -175,110 +175,97 @@ protected static TrustAnchor findTrustAnchor(
175175
}
176176

177177
/**
178-
* Search the given Set of TrustAnchor's for one that is the
179-
* issuer of the given X509 certificate. Uses the specified
180-
* provider for signature verification, or the default provider
181-
* if null.
178+
* Return the first of the given trust anchors that names the issuer of the given certificate and whose public
179+
* key verifies it, or null if there is none. Uses the specified provider for signature verification, or the
180+
* default provider if null.
182181
*
183182
* @param cert the X509 certificate
184183
* @param trustAnchors a Set of TrustAnchor's
185184
* @param sigProvider the provider to use for signature verification
186185
* @return the <code>TrustAnchor</code> object if found or
187186
* <code>null</code> if not.
188-
* @throws AnnotatedException if a TrustAnchor was found but the signature verification
189-
* on the given certificate has thrown an exception.
187+
* @throws AnnotatedException if a trust anchor named the issuer, but none of those that did verified the
188+
* certificate.
190189
*/
191190
protected static TrustAnchor findTrustAnchor(
192191
X509Certificate cert,
193192
Set trustAnchors,
194193
String sigProvider)
195194
throws AnnotatedException
196195
{
197-
TrustAnchor trust = null;
198-
PublicKey trustPublicKey = null;
199-
Exception invalidKeyEx = null;
196+
X500Principal certIssuer = cert.getIssuerX500Principal();
197+
X500Name certIssuerName = null;
200198

201-
X509CertSelector certSelectX509 = new X509CertSelector();
199+
Exception invalidKeyEx = null;
202200

203-
final X500Principal certIssuerPrincipal = cert.getIssuerX500Principal();
204-
try
205-
{
206-
certSelectX509.setSubject(certIssuerPrincipal.getEncoded());
207-
}
208-
catch (IOException e)
201+
for (Iterator it = trustAnchors.iterator(); it.hasNext();)
209202
{
210-
throw new AnnotatedException(e.getMessage(), e);
211-
}
203+
TrustAnchor trust = (TrustAnchor)it.next();
212204

213-
X500Name certIssuerName = null;
205+
PublicKey trustPublicKey;
214206

215-
Iterator iter = trustAnchors.iterator();
216-
while (iter.hasNext() && trust == null)
217-
{
218-
trust = (TrustAnchor)iter.next();
219-
if (trust.getTrustedCert() != null)
207+
// A TrustAnchor is built either from a trusted certificate, or from a name and a public key, so when
208+
// there is no trusted certificate both the CA name and its public key are present.
209+
X509Certificate trustedCert = trust.getTrustedCert();
210+
if (trustedCert != null)
220211
{
221-
if (certSelectX509.match(trust.getTrustedCert()))
222-
{
223-
trustPublicKey = trust.getTrustedCert().getPublicKey();
224-
}
225-
else
212+
if (!certIssuer.equals(trustedCert.getSubjectX500Principal()))
226213
{
227-
trust = null;
214+
continue;
228215
}
216+
217+
trustPublicKey = trustedCert.getPublicKey();
229218
}
230-
else if (trust.getCAName() != null
231-
&& trust.getCAPublicKey() != null)
219+
else
232220
{
233221
if (certIssuerName == null)
234222
{
235-
certIssuerName = X500Name.getInstance(certIssuerPrincipal.getEncoded());
223+
certIssuerName = X500Name.getInstance(certIssuer.getEncoded());
236224
}
237225

238-
try
226+
if (!isCAName(certIssuerName, trust))
239227
{
240-
X500Name caName = X500Name.getInstance(new X500Principal(trust.getCAName()).getEncoded());
241-
242-
if (certIssuerName.equals(caName))
243-
{
244-
trustPublicKey = trust.getCAPublicKey();
245-
}
246-
else
247-
{
248-
trust = null;
249-
}
250-
}
251-
catch (IllegalArgumentException ex)
252-
{
253-
trust = null;
228+
continue;
254229
}
230+
231+
trustPublicKey = trust.getCAPublicKey();
255232
}
256-
else
233+
234+
try
257235
{
258-
trust = null;
236+
verifyX509Certificate(cert, trustPublicKey, sigProvider);
237+
return trust;
259238
}
260-
261-
if (trustPublicKey != null)
239+
catch (Exception e)
262240
{
263-
try
264-
{
265-
verifyX509Certificate(cert, trustPublicKey, sigProvider);
266-
}
267-
catch (Exception ex)
241+
// Anchors sharing the issuer's subject DN can fail in turn; report the first failure.
242+
if (invalidKeyEx == null)
268243
{
269-
invalidKeyEx = ex;
270-
trust = null;
271-
trustPublicKey = null;
244+
invalidKeyEx = e;
272245
}
273246
}
274247
}
275248

276-
if (trust == null && invalidKeyEx != null)
249+
if (invalidKeyEx != null)
277250
{
278251
throw new AnnotatedException("TrustAnchor found but certificate validation failed.", invalidKeyEx);
279252
}
280253

281-
return trust;
254+
return null;
255+
}
256+
257+
private static boolean isCAName(X500Name certIssuerName, TrustAnchor trust)
258+
{
259+
try
260+
{
261+
X500Name caName = X500Name.getInstance(new X500Principal(trust.getCAName()).getEncoded());
262+
263+
return certIssuerName.equals(caName);
264+
}
265+
catch (IllegalArgumentException e)
266+
{
267+
return false;
268+
}
282269
}
283270

284271
static boolean isIssuerTrustAnchor(

0 commit comments

Comments
 (0)