Skip to content

Commit b018323

Browse files
committed
Use plaform OCSP implementation by default, move custom OCSP implementation to eu.webeid.ocsp and make it optional
WE2-1030 Signed-off-by: Mart Somermaa <[email protected]>
1 parent 4379d59 commit b018323

36 files changed

+561
-483
lines changed

.github/workflows/coverity-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- uses: actions/setup-java@v4
2121
with:
2222
distribution: zulu
23-
java-version: 11
23+
java-version: 17
2424

2525
- name: Cache Maven packages
2626
uses: actions/cache@v4

.github/workflows/maven-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- uses: actions/setup-java@v4
2121
with:
2222
distribution: zulu
23-
java-version: 11
23+
java-version: 17
2424

2525
- name: Cache Maven packages
2626
uses: actions/cache@v4

.github/workflows/maven-deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- uses: actions/setup-java@v4
1515
with:
1616
distribution: zulu
17-
java-version: 11
17+
java-version: 17
1818

1919
- name: Cache Maven packages
2020
uses: actions/cache@v4

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
<modelVersion>4.0.0</modelVersion>
66
<artifactId>authtoken-validation</artifactId>
77
<groupId>eu.webeid.security</groupId>
8-
<version>3.2.0</version>
8+
<version>4.0.0-SNAPSHOT</version>
99
<packaging>jar</packaging>
1010
<name>authtoken-validation</name>
1111
<description>Web eID authentication token validation library for Java</description>
1212

1313
<properties>
14-
<java.version>11</java.version>
14+
<java.version>17</java.version>
1515
<jjwt.version>0.12.6</jjwt.version>
1616
<bouncycastle.version>1.81</bouncycastle.version>
1717
<jackson.version>2.19.1</jackson.version>

src/main/java/eu/webeid/security/validator/certvalidators/SubjectCertificateNotRevokedValidator.java renamed to src/main/java/eu/webeid/ocsp/DefaultOcspCertificateRevocationChecker.java

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,19 @@
2020
* SOFTWARE.
2121
*/
2222

23-
package eu.webeid.security.validator.certvalidators;
23+
package eu.webeid.ocsp;
2424

25+
import eu.webeid.ocsp.client.OcspClient;
26+
import eu.webeid.ocsp.protocol.DigestCalculatorImpl;
27+
import eu.webeid.ocsp.protocol.OcspRequestBuilder;
28+
import eu.webeid.ocsp.protocol.OcspResponseValidator;
2529
import eu.webeid.security.exceptions.AuthTokenException;
2630
import eu.webeid.security.exceptions.UserCertificateOCSPCheckFailedException;
2731
import eu.webeid.security.util.DateAndTime;
28-
import eu.webeid.security.validator.ocsp.DigestCalculatorImpl;
29-
import eu.webeid.security.validator.ocsp.OcspClient;
30-
import eu.webeid.security.validator.ocsp.OcspRequestBuilder;
31-
import eu.webeid.security.validator.ocsp.OcspResponseValidator;
32-
import eu.webeid.security.validator.ocsp.OcspServiceProvider;
33-
import eu.webeid.security.validator.ocsp.service.OcspService;
32+
import eu.webeid.ocsp.service.OcspServiceProvider;
33+
import eu.webeid.ocsp.service.OcspService;
34+
import eu.webeid.security.validator.revocationcheck.OcspCertificateRevocationChecker;
35+
import eu.webeid.security.validator.revocationcheck.RevocationInfo;
3436
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
3537
import org.bouncycastle.asn1.ocsp.OCSPResponseStatus;
3638
import org.bouncycastle.asn1.x509.Extension;
@@ -55,13 +57,18 @@
5557
import java.security.cert.X509Certificate;
5658
import java.time.Duration;
5759
import java.util.Date;
58-
import java.util.Objects;
60+
import java.util.Map;
5961

60-
public final class SubjectCertificateNotRevokedValidator {
62+
import static eu.webeid.security.util.DateAndTime.requirePositiveDuration;
63+
import static java.util.Objects.requireNonNull;
6164

62-
private static final Logger LOG = LoggerFactory.getLogger(SubjectCertificateNotRevokedValidator.class);
65+
public final class DefaultOcspCertificateRevocationChecker implements OcspCertificateRevocationChecker {
66+
67+
public static final Duration DEFAULT_TIME_SKEW = Duration.ofMinutes(15);
68+
public static final Duration DEFAULT_THIS_UPDATE_AGE = Duration.ofMinutes(2);
69+
70+
private static final Logger LOG = LoggerFactory.getLogger(DefaultOcspCertificateRevocationChecker.class);
6371

64-
private final SubjectCertificateTrustedValidator trustValidator;
6572
private final OcspClient ocspClient;
6673
private final OcspServiceProvider ocspServiceProvider;
6774
private final Duration allowedOcspResponseTimeSkew;
@@ -71,30 +78,31 @@ public final class SubjectCertificateNotRevokedValidator {
7178
Security.addProvider(new BouncyCastleProvider());
7279
}
7380

74-
public SubjectCertificateNotRevokedValidator(SubjectCertificateTrustedValidator trustValidator,
75-
OcspClient ocspClient,
76-
OcspServiceProvider ocspServiceProvider,
77-
Duration allowedOcspResponseTimeSkew,
78-
Duration maxOcspResponseThisUpdateAge) {
79-
this.trustValidator = trustValidator;
80-
this.ocspClient = ocspClient;
81-
this.ocspServiceProvider = ocspServiceProvider;
82-
this.allowedOcspResponseTimeSkew = allowedOcspResponseTimeSkew;
83-
this.maxOcspResponseThisUpdateAge = maxOcspResponseThisUpdateAge;
81+
public DefaultOcspCertificateRevocationChecker(OcspClient ocspClient,
82+
OcspServiceProvider ocspServiceProvider,
83+
Duration allowedOcspResponseTimeSkew,
84+
Duration maxOcspResponseThisUpdateAge) {
85+
this.ocspClient = requireNonNull(ocspClient, "ocspClient");
86+
this.ocspServiceProvider = requireNonNull(ocspServiceProvider, "ocspServiceProvider");
87+
this.allowedOcspResponseTimeSkew = requirePositiveDuration(allowedOcspResponseTimeSkew, "allowedOcspResponseTimeSkew");
88+
this.maxOcspResponseThisUpdateAge = requirePositiveDuration(maxOcspResponseThisUpdateAge, "maxOcspResponseThisUpdateAge");
8489
}
8590

8691
/**
87-
* Validates that the user certificate from the authentication token is not revoked with OCSP.
92+
* Validates with OCSP that the user certificate from the authentication token is not revoked.
8893
*
8994
* @param subjectCertificate user certificate to be validated
9095
* @throws AuthTokenException when user certificate is revoked or revocation check fails.
9196
*/
92-
public void validateCertificateNotRevoked(X509Certificate subjectCertificate) throws AuthTokenException {
97+
@Override
98+
public RevocationInfo validateCertificateNotRevoked(X509Certificate subjectCertificate, X509Certificate issuerCertificate) throws AuthTokenException {
99+
requireNonNull(subjectCertificate, "subjectCertificate");
100+
requireNonNull(issuerCertificate, "issuerCertificate");
101+
93102
try {
94103
OcspService ocspService = ocspServiceProvider.getService(subjectCertificate);
95104

96-
final CertificateID certificateId = getCertificateId(subjectCertificate,
97-
Objects.requireNonNull(trustValidator.getSubjectCertificateIssuerCertificate()));
105+
final CertificateID certificateId = getCertificateId(subjectCertificate, issuerCertificate);
98106

99107
final OCSPReq request = new OcspRequestBuilder()
100108
.withCertificateId(certificateId)
@@ -106,7 +114,7 @@ public void validateCertificateNotRevoked(X509Certificate subjectCertificate) th
106114
}
107115

108116
LOG.debug("Sending OCSP request");
109-
final OCSPResp response = Objects.requireNonNull(ocspClient.request(ocspService.getAccessLocation(), request));
117+
final OCSPResp response = requireNonNull(ocspClient.request(ocspService.getAccessLocation(), request), "OCSPResp");
110118
if (response.getStatus() != OCSPResponseStatus.SUCCESSFUL) {
111119
throw new UserCertificateOCSPCheckFailedException("Response status: " + ocspStatusToString(response.getStatus()));
112120
}
@@ -119,6 +127,10 @@ public void validateCertificateNotRevoked(X509Certificate subjectCertificate) th
119127
if (ocspService.doesSupportNonce()) {
120128
checkNonce(request, basicResponse);
121129
}
130+
131+
// TODO: @madislm, just an example, please amend according to your requirements.
132+
return new RevocationInfo(ocspService.getAccessLocation(), Map.of("BasicOCSPResp", basicResponse));
133+
122134
} catch (OCSPException | CertificateException | OperatorCreationException | IOException e) {
123135
throw new UserCertificateOCSPCheckFailedException(e);
124136
}
@@ -202,20 +214,14 @@ private static CertificateID getCertificateId(X509Certificate subjectCertificate
202214
}
203215

204216
private static String ocspStatusToString(int status) {
205-
switch (status) {
206-
case OCSPResp.MALFORMED_REQUEST:
207-
return "malformed request";
208-
case OCSPResp.INTERNAL_ERROR:
209-
return "internal error";
210-
case OCSPResp.TRY_LATER:
211-
return "service unavailable";
212-
case OCSPResp.SIG_REQUIRED:
213-
return "request signature missing";
214-
case OCSPResp.UNAUTHORIZED:
215-
return "unauthorized";
216-
default:
217-
return "unknown";
218-
}
217+
return switch (status) {
218+
case OCSPResp.MALFORMED_REQUEST -> "malformed request";
219+
case OCSPResp.INTERNAL_ERROR -> "internal error";
220+
case OCSPResp.TRY_LATER -> "service unavailable";
221+
case OCSPResp.SIG_REQUIRED -> "request signature missing";
222+
case OCSPResp.UNAUTHORIZED -> "unauthorized";
223+
default -> "unknown";
224+
};
219225
}
220226

221227
}

src/main/java/eu/webeid/security/validator/ocsp/OcspClient.java renamed to src/main/java/eu/webeid/ocsp/client/OcspClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
package eu.webeid.security.validator.ocsp;
23+
package eu.webeid.ocsp.client;
2424

2525
import org.bouncycastle.cert.ocsp.OCSPReq;
2626
import org.bouncycastle.cert.ocsp.OCSPResp;

src/main/java/eu/webeid/security/validator/ocsp/OcspClientImpl.java renamed to src/main/java/eu/webeid/ocsp/client/OcspClientImpl.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
package eu.webeid.security.validator.ocsp;
23+
package eu.webeid.ocsp.client;
2424

2525
import org.bouncycastle.cert.ocsp.OCSPReq;
2626
import org.bouncycastle.cert.ocsp.OCSPResp;
@@ -34,6 +34,9 @@
3434
import java.net.http.HttpResponse;
3535
import java.time.Duration;
3636

37+
import static eu.webeid.security.util.DateAndTime.requirePositiveDuration;
38+
import static java.util.Objects.requireNonNull;
39+
3740
public class OcspClientImpl implements OcspClient {
3841

3942
private static final Logger LOG = LoggerFactory.getLogger(OcspClientImpl.class);
@@ -45,6 +48,7 @@ public class OcspClientImpl implements OcspClient {
4548
private final Duration ocspRequestTimeout;
4649

4750
public static OcspClient build(Duration ocspRequestTimeout) {
51+
requirePositiveDuration(ocspRequestTimeout, "ocspRequestTimeout");
4852
return new OcspClientImpl(
4953
HttpClient.newBuilder()
5054
.connectTimeout(ocspRequestTimeout)
@@ -91,8 +95,8 @@ public OCSPResp request(URI uri, OCSPReq ocspReq) throws IOException {
9195
}
9296

9397
public OcspClientImpl(HttpClient httpClient, Duration ocspRequestTimeout) {
94-
this.httpClient = httpClient;
95-
this.ocspRequestTimeout = ocspRequestTimeout;
98+
this.httpClient = requireNonNull(httpClient, "httpClient");
99+
this.ocspRequestTimeout = requirePositiveDuration(ocspRequestTimeout, "ocspRequestTimeout");
96100
}
97101

98102
}

src/main/java/eu/webeid/security/validator/ocsp/DigestCalculatorImpl.java renamed to src/main/java/eu/webeid/ocsp/protocol/DigestCalculatorImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
package eu.webeid.security.validator.ocsp;
23+
package eu.webeid.ocsp.protocol;
2424

2525
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
2626
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;

src/main/java/eu/webeid/security/validator/ocsp/OcspRequestBuilder.java renamed to src/main/java/eu/webeid/ocsp/protocol/OcspRequestBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
package eu.webeid.security.validator.ocsp;
23+
package eu.webeid.ocsp.protocol;
2424

2525
import org.bouncycastle.asn1.DEROctetString;
2626
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;

src/main/java/eu/webeid/security/validator/ocsp/OcspResponseValidator.java renamed to src/main/java/eu/webeid/ocsp/protocol/OcspResponseValidator.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
package eu.webeid.security.validator.ocsp;
23+
package eu.webeid.ocsp.protocol;
2424

2525
import eu.webeid.security.exceptions.OCSPCertificateException;
2626
import eu.webeid.security.exceptions.UserCertificateOCSPCheckFailedException;
@@ -121,8 +121,7 @@ public static void validateSubjectCertificateStatus(SingleResp certStatusRespons
121121
if (status == null) {
122122
return;
123123
}
124-
if (status instanceof RevokedStatus) {
125-
RevokedStatus revokedStatus = (RevokedStatus) status;
124+
if (status instanceof RevokedStatus revokedStatus) {
126125
throw (revokedStatus.hasRevocationReason() ?
127126
new UserCertificateRevokedException("Revocation reason: " + revokedStatus.getRevocationReason()) :
128127
new UserCertificateRevokedException());

0 commit comments

Comments
 (0)