Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring CmsValidator (internal CRL resolution) #2635

Merged
merged 2 commits into from
Aug 16, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Refactoring CmsValidator (internal CRL resolution)
Signed-off-by: Lucas Saldanha <lucascrsaldanha@gmail.com>
  • Loading branch information
lucassaldanha committed Aug 14, 2021
commit 33acdfda1e5b4fdcf2d91b09e9cc864dbf6735fb
42 changes: 28 additions & 14 deletions pki/src/main/java/org/hyperledger/besu/pki/cms/CmsValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertStore;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXRevocationChecker;
import java.security.cert.PKIXRevocationChecker.Option;
Expand Down Expand Up @@ -54,11 +55,9 @@ public class CmsValidator {
private static final Logger LOGGER = LogManager.getLogger();

private final KeyStoreWrapper truststore;
private final Optional<CertStore> crlCertStore;

public CmsValidator(final KeyStoreWrapper truststore, final CertStore crlCertStore) {
public CmsValidator(final KeyStoreWrapper truststore) {
this.truststore = truststore;
this.crlCertStore = Optional.ofNullable(crlCertStore);
}

/**
Expand Down Expand Up @@ -146,17 +145,18 @@ private boolean isCertificateTrusted(
new PKIXBuilderParameters(truststore.getKeyStore(), targetConstraints);

// Adding CertStore with CRLs (if present, otherwise disabling revocation check)
crlCertStore.ifPresentOrElse(
CRLs -> {
params.addCertStore(CRLs);
PKIXRevocationChecker rc = (PKIXRevocationChecker) cpb.getRevocationChecker();
rc.setOptions(EnumSet.of(Option.PREFER_CRLS));
params.addCertPathChecker(rc);
},
() -> {
LOGGER.warn("No CRL CertStore provided. CRL validation will be disabled.");
params.setRevocationEnabled(false);
});
loadCRLs(truststore)
.ifPresentOrElse(
CRLs -> {
params.addCertStore(CRLs);
PKIXRevocationChecker rc = (PKIXRevocationChecker) cpb.getRevocationChecker();
rc.setOptions(EnumSet.of(Option.PREFER_CRLS));
params.addCertPathChecker(rc);
},
() -> {
LOGGER.warn("No CRL CertStore provided. CRL validation will be disabled.");
params.setRevocationEnabled(false);
});

// Read certificates sent on the CMS message and adding it to the path building algorithm
final CertStore cmsCertificates =
Expand All @@ -178,4 +178,18 @@ private boolean isCertificateTrusted(
throw new RuntimeException("Error validating certificate chain", e);
}
}

private Optional<CertStore> loadCRLs(final KeyStoreWrapper truststore) {
Copy link
Contributor

@jframe jframe Aug 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't really loading CRL as such, maybe createCertStore?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed there is CRLUtil that does something similar to this function, should that be used instead or this replaces that one?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRLUtil is used when loading the CRL pem file. Not for the truststore. They are similar but not the same.

if (truststore.getCRLs() != null) {
try {
return Optional.of(
CertStore.getInstance(
"Collection", new CollectionCertStoreParameters(truststore.getCRLs())));
} catch (final Exception e) {
throw new RuntimeException("Error loading CRLs from Truststore", e);
}
} else {
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,22 @@
import static org.hyperledger.besu.pki.util.TestCertificateUtils.createKeyPair;
import static org.hyperledger.besu.pki.util.TestCertificateUtils.createSelfSignedCertificate;
import static org.hyperledger.besu.pki.util.TestCertificateUtils.issueCertificate;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import org.hyperledger.besu.pki.keystore.KeyStoreWrapper;
import org.hyperledger.besu.pki.keystore.SoftwareKeyStoreWrapper;

import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.apache.tuweni.bytes.Bytes;
Expand All @@ -54,10 +55,12 @@

public class CmsCreationAndValidationTest {

private static KeyStoreWrapper keystoreWrapper;
private static KeyStoreWrapper truststoreWrapper;
private static CertStore CRLs;
private static KeyStore keystore;
private static KeyStore truststore;
private static List<X509CRL> CRLs;

private KeyStoreWrapper keystoreWrapper;
private KeyStoreWrapper truststoreWrapper;
private CmsValidator cmsValidator;

@BeforeClass
Expand Down Expand Up @@ -150,19 +153,17 @@ Create untrusted chain (untrusted_selfsigned -> unstrusted_partner)
/*
Create truststore wrapper with 3 trusted certificates: 'ca', 'interca' and 'selfsigned'
*/
final KeyStore truststore = KeyStore.getInstance("PKCS12");
truststore = KeyStore.getInstance("PKCS12");
truststore.load(null, null);

truststore.setCertificateEntry("ca", caCertificate);
truststore.setCertificateEntry("interca", interCACertificate);
truststore.setCertificateEntry("selfsigned", selfsignedCertificate);

truststoreWrapper = new SoftwareKeyStoreWrapper(truststore, "");

/*
Create keystore with certificates used in tests
*/
final KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore = KeyStore.getInstance("PKCS12");
keystore.load(null, null);

keystore.setKeyEntry(
Expand Down Expand Up @@ -195,7 +196,6 @@ Create untrusted chain (untrusted_selfsigned -> unstrusted_partner)
untrustedIntermediateKeyPair.getPrivate(),
"".toCharArray(),
new Certificate[] {untrustedIntermediateCertificate, untrustedSelfsignedCertificate});
keystoreWrapper = new SoftwareKeyStoreWrapper(keystore, "");

/*
Create CRLs for all CA certificates (mostly empty, only ca has one revoked certificate)
Expand All @@ -207,17 +207,17 @@ Create CRLs for all CA certificates (mostly empty, only ca has one revoked certi
createCRL(partnerACACertificate, partnerACAPair, Collections.emptyList());
final X509CRL selfsignedCRL =
createCRL(selfsignedCertificate, selfsignedKeyPair, Collections.emptyList());

CRLs =
CertStore.getInstance(
"Collection",
new CollectionCertStoreParameters(
Set.of(caCRL, intercaCRL, partnerACACRL, selfsignedCRL)));
CRLs = List.of(caCRL, intercaCRL, partnerACACRL, selfsignedCRL);
}

@Before
public void before() {
cmsValidator = new CmsValidator(truststoreWrapper, CRLs);
keystoreWrapper = new SoftwareKeyStoreWrapper(keystore, "");

truststoreWrapper = spy(new SoftwareKeyStoreWrapper(truststore, ""));
when(truststoreWrapper.getCRLs()).thenReturn(CRLs);

cmsValidator = new CmsValidator(truststoreWrapper);
}

@Test
Expand Down Expand Up @@ -285,10 +285,13 @@ public void cmsValidationWithoutCRLConfigDisablesCRLCheck() {
final CmsCreator cmsCreator = new CmsCreator(keystoreWrapper, "revoked");
final Bytes data = Bytes.random(32);

// Removing CRLs
when(truststoreWrapper.getCRLs()).thenReturn(null);

final Bytes cms = cmsCreator.create(data);

// Overriding validator with instance without CRL CertStore
cmsValidator = new CmsValidator(truststoreWrapper, null);
cmsValidator = new CmsValidator(truststoreWrapper);

// Because we don't have a CRL CertStore, revocation is not checked
assertThat(cmsValidator.validate(cms, data)).isTrue();
Expand Down