Skip to content

Commit 3bfa591

Browse files
committed
JCE: allow CertPathBuilder to work without CertStores provided
1 parent 5f9da4a commit 3bfa591

2 files changed

Lines changed: 108 additions & 24 deletions

File tree

src/main/java/com/wolfssl/provider/jce/WolfCryptPKIXCertPathBuilder.java

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,11 @@ private void checkSignerKeyConstraints(
284284
/**
285285
* Find the target certificate based on the X509CertSelector in params.
286286
*
287-
* Searches through all CertStores for a certificate matching the
288-
* target constraints.
287+
* Searches for a certificate matching the target constraints in the
288+
* following order:
289+
* 1. Directly set in the selector via setCertificate()
290+
* 2. In CertStores attached to the parameters
291+
* 3. Among trust anchor certificates
289292
*
290293
* @param params PKIXBuilderParameters containing target selector
291294
*
@@ -302,8 +305,7 @@ private X509Certificate findTargetCertificate(PKIXBuilderParameters params)
302305
List<CertStore> certStores = null;
303306

304307
if (params == null) {
305-
throw new CertPathBuilderException(
306-
"PKIXBuilderParameters is null");
308+
throw new CertPathBuilderException("PKIXBuilderParameters is null");
307309
}
308310

309311
selector = params.getTargetCertConstraints();
@@ -319,7 +321,8 @@ private X509Certificate findTargetCertificate(PKIXBuilderParameters params)
319321
}
320322

321323
x509Selector = (X509CertSelector)selector;
322-
log("searching for target certificate with selector: " + x509Selector);
324+
log("searching for target certificate with selector: " +
325+
x509Selector);
323326

324327
/* Check if target cert is directly set in selector */
325328
targetCert = x509Selector.getCertificate();
@@ -330,32 +333,42 @@ private X509Certificate findTargetCertificate(PKIXBuilderParameters params)
330333

331334
/* Search through CertStores for matching certificate */
332335
certStores = params.getCertStores();
333-
if (certStores == null || certStores.isEmpty()) {
334-
throw new CertPathBuilderException(
335-
"No CertStores provided in PKIXBuilderParameters");
336-
}
336+
if (certStores != null) {
337+
for (CertStore store : certStores) {
338+
try {
339+
Collection<? extends Certificate> certs =
340+
store.getCertificates(x509Selector);
337341

338-
for (CertStore store : certStores) {
339-
try {
340-
Collection<? extends Certificate> certs =
341-
store.getCertificates(x509Selector);
342-
343-
if (certs != null && !certs.isEmpty()) {
344-
/* Return first matching certificate */
345-
targetCert = (X509Certificate) certs.iterator().next();
346-
log("found target certificate: " +
347-
targetCert.getSubjectX500Principal().getName());
348-
return targetCert;
342+
if (certs != null && !certs.isEmpty()) {
343+
targetCert = (X509Certificate)certs.iterator().next();
344+
log("found target certificate in CertStore: " +
345+
targetCert.getSubjectX500Principal().getName());
346+
return targetCert;
347+
}
348+
349+
} catch (CertStoreException e) {
350+
log("error searching CertStore: " + e.getMessage());
351+
/* Continue to next store */
349352
}
353+
}
354+
}
350355

351-
} catch (CertStoreException e) {
352-
log("error searching CertStore: " + e.getMessage());
353-
/* Continue to next store */
356+
/* Search trust anchor certificates as fallback */
357+
Set<TrustAnchor> anchors = params.getTrustAnchors();
358+
if (anchors != null) {
359+
for (TrustAnchor anchor : anchors) {
360+
X509Certificate anchorCert = anchor.getTrustedCert();
361+
if ((anchorCert != null) && x509Selector.match(anchorCert)) {
362+
363+
log("found target certificate in trust anchors: " +
364+
anchorCert.getSubjectX500Principal().getName());
365+
return anchorCert;
366+
}
354367
}
355368
}
356369

357370
throw new CertPathBuilderException(
358-
"Target certificate not found in CertStores");
371+
"Target certificate not found matching selector");
359372
}
360373

361374
/**

src/test/java/com/wolfssl/provider/jce/test/WolfCryptPKIXCertPathBuilderTest.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import java.security.cert.CollectionCertStoreParameters;
6767
import java.lang.IllegalArgumentException;
6868
import java.util.Calendar;
69+
import java.util.Collections;
6970
import java.util.Date;
7071

7172
import com.wolfssl.wolfcrypt.WolfCrypt;
@@ -4407,5 +4408,75 @@ public void testAlgorithmConstraintsAllowValidChain()
44074408
}
44084409
}
44094410
}
4411+
4412+
/**
4413+
* Test that building a cert path with no CertStores fails gracefully with
4414+
* CertPathBuilderException instead of throwing an early error about
4415+
* missing CertStores. Uses a non-matching subject selector so the target
4416+
* cert cannot be found.
4417+
*/
4418+
@Test
4419+
public void testBuildWithNoCertStoresFailsGracefully()
4420+
throws Exception {
4421+
4422+
X509Certificate caCert = null;
4423+
TrustAnchor anchor = null;
4424+
4425+
caCert = loadCertFromFile(caCertDer);
4426+
anchor = new TrustAnchor(caCert, null);
4427+
4428+
/* Selector with non-matching subject, no CertStores */
4429+
X509CertSelector selector = new X509CertSelector();
4430+
selector.setSubject("CN=NonExistent, O=NoOrg, C=US");
4431+
4432+
PKIXBuilderParameters params =
4433+
new PKIXBuilderParameters(Collections.singleton(anchor), selector);
4434+
params.setRevocationEnabled(false);
4435+
4436+
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX", provider);
4437+
4438+
try {
4439+
cpb.build(params);
4440+
fail("Expected CertPathBuilderException when target cert " +
4441+
"not found");
4442+
} catch (CertPathBuilderException e) {
4443+
/* Expected: should fail because target cert can't be found,
4444+
* not because of missing CertStores */
4445+
assertNotNull("Exception message should not be null",
4446+
e.getMessage());
4447+
assertTrue("Exception should mention target not found, got: " +
4448+
e.getMessage(), e.getMessage().contains("not found"));
4449+
}
4450+
}
4451+
4452+
/**
4453+
* Test that building a cert path with no CertStores succeeds when the
4454+
* target cert matches a trust anchor. The builder should find the target
4455+
* among trust anchors as a fallback.
4456+
*/
4457+
@Test
4458+
public void testBuildWithNoCertStoresFindsAnchor()
4459+
throws Exception {
4460+
4461+
X509Certificate caCert = null;
4462+
TrustAnchor anchor = null;
4463+
4464+
caCert = loadCertFromFile(caCertDer);
4465+
anchor = new TrustAnchor(caCert, null);
4466+
4467+
/* Selector matching the trust anchor cert, no CertStores */
4468+
X509CertSelector selector = new X509CertSelector();
4469+
selector.setCertificate(caCert);
4470+
4471+
PKIXBuilderParameters params =
4472+
new PKIXBuilderParameters(Collections.singleton(anchor), selector);
4473+
params.setRevocationEnabled(false);
4474+
4475+
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX", provider);
4476+
CertPathBuilderResult result = cpb.build(params);
4477+
4478+
assertNotNull("CertPathBuilderResult should not be null", result);
4479+
checkPKIXCertPathBuilderResult(result, caCert, caCert.getPublicKey());
4480+
}
44104481
}
44114482

0 commit comments

Comments
 (0)