From e3c771798441ef9d20786cf5f3703106fabf8765 Mon Sep 17 00:00:00 2001 From: Mart Somermaa Date: Tue, 23 Feb 2021 19:47:11 +0200 Subject: [PATCH] feat: make using nonce extension configurable during OCSP requests Signed-off-by: Mart Somermaa --- README.md | 2 +- pom.xml | 2 +- .../org/webeid/security/util/OcspUrls.java | 12 +++++++++++ .../AuthTokenValidationConfiguration.java | 16 +++++++++++---- .../validator/AuthTokenValidatorImpl.java | 2 +- .../validator/ocsp/OcspRequestBuilder.java | 20 ++++++++++++++++--- ...SubjectCertificateNotRevokedValidator.java | 10 +++++++++- 7 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/webeid/security/util/OcspUrls.java diff --git a/README.md b/README.md index 0e5dcff1..5dbfb66e 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ The token validation process consists of three stages: ## Basic usage -The builder class need a *javax.cache.Cache* instance (use *Hazelcast* or *Infinispan* if you do use a cluster, or *Caffeine* if you don't): +The builder class needs a *javax.cache.Cache* instance (use *Hazelcast* or *Infinispan* if you use a cluster, or *Caffeine* or *Ehcache* if you don't): ```java Cache cache = // TODO: create new cache instance here ``` diff --git a/pom.xml b/pom.xml index b4f13721..de256ccb 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 authtoken-validation org.webeid.security - 1.0.0 + 1.0.1 jar authtoken-validation Web eID authentication token validation library for Java diff --git a/src/main/java/org/webeid/security/util/OcspUrls.java b/src/main/java/org/webeid/security/util/OcspUrls.java new file mode 100644 index 00000000..67c6e984 --- /dev/null +++ b/src/main/java/org/webeid/security/util/OcspUrls.java @@ -0,0 +1,12 @@ +package org.webeid.security.util; + +import java.net.URI; + +public class OcspUrls { + public static final URI ESTEID_2015 = URI.create("http://aia.sk.ee/esteid2015"); + + private OcspUrls() { + throw new IllegalStateException("Constants class"); + } + +} diff --git a/src/main/java/org/webeid/security/validator/AuthTokenValidationConfiguration.java b/src/main/java/org/webeid/security/validator/AuthTokenValidationConfiguration.java index 0fdc73fe..8a1e304d 100644 --- a/src/main/java/org/webeid/security/validator/AuthTokenValidationConfiguration.java +++ b/src/main/java/org/webeid/security/validator/AuthTokenValidationConfiguration.java @@ -36,6 +36,7 @@ import java.util.Objects; import static org.webeid.security.nonce.NonceGeneratorBuilder.requirePositiveDuration; +import static org.webeid.security.util.OcspUrls.ESTEID_2015; import static org.webeid.security.util.SubjectCertificatePolicies.EST_MOBILE_ID_POLICY; /** @@ -53,6 +54,8 @@ final class AuthTokenValidationConfiguration { private String siteCertificateSha256Fingerprint; // Don't allow Estonian Mobile-ID policy by default. private Collection disallowedSubjectCertificatePolicies = Sets.newHashSet(EST_MOBILE_ID_POLICY); + // Disable OCSP nonce extension for EstEID 2015 cards by default. + private Collection nonceDisabledOcspUrls = Sets.newHashSet(ESTEID_2015); AuthTokenValidationConfiguration() { } @@ -67,6 +70,7 @@ private AuthTokenValidationConfiguration(AuthTokenValidationConfiguration other) this.isSiteCertificateFingerprintValidationEnabled = other.isSiteCertificateFingerprintValidationEnabled; this.siteCertificateSha256Fingerprint = other.siteCertificateSha256Fingerprint; this.disallowedSubjectCertificatePolicies = new HashSet<>(other.disallowedSubjectCertificatePolicies); + this.nonceDisabledOcspUrls = new HashSet<>(other.nonceDisabledOcspUrls); } void setSiteOrigin(URI siteOrigin) { @@ -126,6 +130,14 @@ public String getSiteCertificateSha256Fingerprint() { return siteCertificateSha256Fingerprint; } + public Collection getDisallowedSubjectCertificatePolicies() { + return disallowedSubjectCertificatePolicies; + } + + public Collection getNonceDisabledOcspUrls() { + return nonceDisabledOcspUrls; + } + /** * Checks that the configuration parameters are valid. * @@ -151,8 +163,4 @@ AuthTokenValidationConfiguration copy() { return new AuthTokenValidationConfiguration(this); } - public Collection getDisallowedSubjectCertificatePolicies() { - return disallowedSubjectCertificatePolicies; - } - } diff --git a/src/main/java/org/webeid/security/validator/AuthTokenValidatorImpl.java b/src/main/java/org/webeid/security/validator/AuthTokenValidatorImpl.java index 17367d8b..52b79176 100644 --- a/src/main/java/org/webeid/security/validator/AuthTokenValidatorImpl.java +++ b/src/main/java/org/webeid/security/validator/AuthTokenValidatorImpl.java @@ -132,7 +132,7 @@ private ValidatorBatch getCertTrustValidators() { return ValidatorBatch.createFrom( certTrustedValidator::validateCertificateTrusted ).addOptional(configuration.isUserCertificateRevocationCheckWithOcspEnabled(), - new SubjectCertificateNotRevokedValidator(certTrustedValidator, httpClientSupplier.get())::validateCertificateNotRevoked + new SubjectCertificateNotRevokedValidator(certTrustedValidator, httpClientSupplier.get(), configuration.getNonceDisabledOcspUrls())::validateCertificateNotRevoked ); } } diff --git a/src/main/java/org/webeid/security/validator/ocsp/OcspRequestBuilder.java b/src/main/java/org/webeid/security/validator/ocsp/OcspRequestBuilder.java index a24a6a00..3805cbb5 100644 --- a/src/main/java/org/webeid/security/validator/ocsp/OcspRequestBuilder.java +++ b/src/main/java/org/webeid/security/validator/ocsp/OcspRequestBuilder.java @@ -70,6 +70,7 @@ public final class OcspRequestBuilder { private DigestCalculator digestCalculator = Digester.sha1(); private X509Certificate subjectCertificate; private X509Certificate issuerCertificate; + private boolean ocspNonceEnabled = true; public OcspRequestBuilder generator(SecureRandom generator) { this.randomGenerator = generator; @@ -91,12 +92,16 @@ public OcspRequestBuilder issuer(X509Certificate issuer) { return this; } + public OcspRequestBuilder enableOcspNonce(boolean ocspNonceEnabled) { + this.ocspNonceEnabled = ocspNonceEnabled; + return this; + } + /** * ATTENTION: The returned {@link OCSPReq} is not re-usable/cacheable! It contains a one-time nonce * and CA's will (should) reject subsequent requests that have the same nonce value. */ public OCSPReq build() throws OCSPException, IOException, CertificateEncodingException { - final SecureRandom generator = Objects.requireNonNull(this.randomGenerator, "randomGenerator"); final DigestCalculator calculator = Objects.requireNonNull(this.digestCalculator, "digestCalculator"); final X509Certificate certificate = Objects.requireNonNull(this.subjectCertificate, "subjectCertificate"); final X509Certificate issuer = Objects.requireNonNull(this.issuerCertificate, "issuerCertificate"); @@ -109,6 +114,16 @@ public OCSPReq build() throws OCSPException, IOException, CertificateEncodingExc final OCSPReqBuilder builder = new OCSPReqBuilder(); builder.addRequest(certId); + if (ocspNonceEnabled) { + addNonce(builder); + } + + return builder.build(); + } + + private void addNonce(OCSPReqBuilder builder) { + final SecureRandom generator = Objects.requireNonNull(this.randomGenerator, "randomGenerator"); + final byte[] nonce = new byte[8]; generator.nextBytes(nonce); @@ -118,7 +133,6 @@ public OCSPReq build() throws OCSPException, IOException, CertificateEncodingExc }; builder.setRequestExtensions(new Extensions(extensions)); - - return builder.build(); } + } diff --git a/src/main/java/org/webeid/security/validator/validators/SubjectCertificateNotRevokedValidator.java b/src/main/java/org/webeid/security/validator/validators/SubjectCertificateNotRevokedValidator.java index c9e90b45..d72e52ba 100644 --- a/src/main/java/org/webeid/security/validator/validators/SubjectCertificateNotRevokedValidator.java +++ b/src/main/java/org/webeid/security/validator/validators/SubjectCertificateNotRevokedValidator.java @@ -38,6 +38,7 @@ import java.net.URI; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; +import java.util.Collection; import java.util.Objects; public final class SubjectCertificateNotRevokedValidator { @@ -46,10 +47,12 @@ public final class SubjectCertificateNotRevokedValidator { private final SubjectCertificateTrustedValidator trustValidator; private final OkHttpClient httpClient; + private final Collection nonceDisabledOcspUrls; - public SubjectCertificateNotRevokedValidator(SubjectCertificateTrustedValidator trustValidator, OkHttpClient httpClient) { + public SubjectCertificateNotRevokedValidator(SubjectCertificateTrustedValidator trustValidator, OkHttpClient httpClient, Collection nonceDisabledOcspUrls) { this.trustValidator = trustValidator; this.httpClient = httpClient; + this.nonceDisabledOcspUrls = nonceDisabledOcspUrls; } /** @@ -66,9 +69,14 @@ public void validateCertificateNotRevoked(AuthTokenValidatorData actualTokenData if (uri == null) { throw new UserCertificateRevocationCheckFailedException("The CA/certificate doesn't have an OCSP responder"); } + final boolean ocspNonceDisabled = nonceDisabledOcspUrls.contains(uri); + if (ocspNonceDisabled) { + LOG.debug("Disabling OCSP nonce extension"); + } final OCSPReq request = new OcspRequestBuilder() .certificate(certificate) + .enableOcspNonce(!ocspNonceDisabled) .issuer(Objects.requireNonNull(trustValidator.getSubjectCertificateIssuerCertificate())) .build();