From 264ea74c871c12e0d2ed6be56f3d2ff458139243 Mon Sep 17 00:00:00 2001 From: Marco Fargetta Date: Wed, 10 Apr 2024 10:44:58 +0200 Subject: [PATCH 1/3] Enable certification verification using CRL-DP Currently certificates can be validated only using OCSP with a configured responder or using the AIA certificate extension. If the responder cannot be used verification is not possible. This is the case for the startup certificates of the responder. The new policy add a verification using the CRL-DP extension defined in the certificate. If AIA extension is defined it has precedence over the CRLs and if no other check are performed. This new method takes place when OCSP is configured without a default responder and the PKIX verification method is adopted (with the policy OCSP_LEAF_AND_CHAIN_POLICY). At least a verification method, defined in the certificate, has to return success to accept the certificate. --- .../main/native/org/mozilla/jss/ssl/common.c | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/native/src/main/native/org/mozilla/jss/ssl/common.c b/native/src/main/native/org/mozilla/jss/ssl/common.c index c1b407deb..83fc40dcf 100644 --- a/native/src/main/native/org/mozilla/jss/ssl/common.c +++ b/native/src/main/native/org/mozilla/jss/ssl/common.c @@ -936,16 +936,19 @@ JSSL_verifyCertPKIXInternal(CERTCertificate *cert, CERTVerifyLog *log, SECCertificateUsage *usage, CERTCertList *trustedCertList) { - /* Put the first set of possible flags internally here first. Later - * there could be a more complete list to choose from; for now we only - * support our hard core fetch AIA OCSP policy. Note that we disable - * CRL fetching as Dogtag doesn't support it. Additionally, enable OCSP - * checking on the chained CA certificates. Since NSS/PKIX's - * CERT_GetClassicOCSPEnabledHardFailurePolicy doesn't do what we want, - * we construct the policy ourselves. */ + /* Since NSS/PKIX's CERT_GetClassicOCSPEnabledHardFailurePolicy doesn't + * do what we want, we construct the policy ourselves. + * + * When enabled the checking on the chained CA certificates. + * With this policy the verification process does: + * - if one between AIA and CRL-DP is present then it will be used; + * - if AIA and CRL-DP are both presents only AIA is used and in case + * freshin formation cannot be retrieved it fails the validation; + * - it no AIA and CRL-DP are present no revocation check is performed.*/ PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = { /* crl */ - CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD, + CERT_REV_M_TEST_USING_THIS_METHOD | + CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO, /* ocsp */ CERT_REV_M_TEST_USING_THIS_METHOD | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO @@ -953,7 +956,8 @@ JSSL_verifyCertPKIXInternal(CERTCertificate *cert, PRUint64 ocsp_Enabled_Hard_Policy_ChainFlags[2] = { /* crl */ - CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD, + CERT_REV_M_TEST_USING_THIS_METHOD | + CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO, /* ocsp */ CERT_REV_M_TEST_USING_THIS_METHOD | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO From 332041bc7b51b7f99fc43ec82c1fa97d2e9b6e40 Mon Sep 17 00:00:00 2001 From: Marco Fargetta Date: Thu, 11 Apr 2024 15:00:19 +0200 Subject: [PATCH 2/3] Rename enableOCSP to enableRevocationCheck Since verification with CRL-DP is introduced and it is enabled using this parameter the name is modified to be not related only to OCSP. --- docs/changes/v5.6.0/Parameter-Changes.adoc | 5 ++ .../jss/tomcat/Http11NioProtocol.java | 14 ++++-- .../org/dogtagpki/jss/tomcat/TomcatJSS.java | 46 +++++++++++-------- 3 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 docs/changes/v5.6.0/Parameter-Changes.adoc diff --git a/docs/changes/v5.6.0/Parameter-Changes.adoc b/docs/changes/v5.6.0/Parameter-Changes.adoc new file mode 100644 index 000000000..1c6f718a5 --- /dev/null +++ b/docs/changes/v5.6.0/Parameter-Changes.adoc @@ -0,0 +1,5 @@ += Paramater Changes = + +== Rename enableOCSP to enableRevocationCheck == + +The `enableOCSP` param has been deprecated. Use `enableRevocationCheck` instead. \ No newline at end of file diff --git a/tomcat/src/main/java/org/dogtagpki/jss/tomcat/Http11NioProtocol.java b/tomcat/src/main/java/org/dogtagpki/jss/tomcat/Http11NioProtocol.java index f8a06c7af..84f228278 100644 --- a/tomcat/src/main/java/org/dogtagpki/jss/tomcat/Http11NioProtocol.java +++ b/tomcat/src/main/java/org/dogtagpki/jss/tomcat/Http11NioProtocol.java @@ -73,12 +73,20 @@ public void setServerCertNickFile(String serverCertNickFile) { tomcatjss.setServerCertNickFile(serverCertNickFile); } - public boolean getEnabledOCSP() { - return tomcatjss.getEnableOCSP(); + public boolean getEnableOCSP() { + return tomcatjss.getEnableRevocationCheck(); } public void setEnableOCSP(boolean enableOCSP) { - tomcatjss.setEnableOCSP(enableOCSP); + tomcatjss.setEnableRevocationCheck(enableOCSP); + } + + public boolean getEnableRevocationCheck() { + return tomcatjss.getEnableRevocationCheck(); + } + + public void setEnableRevocationCheck(boolean enableRevocationCheck) { + tomcatjss.setEnableRevocationCheck(enableRevocationCheck); } public String getOcspResponderURL() { diff --git a/tomcat/src/main/java/org/dogtagpki/jss/tomcat/TomcatJSS.java b/tomcat/src/main/java/org/dogtagpki/jss/tomcat/TomcatJSS.java index 41de1235b..c20ead584 100644 --- a/tomcat/src/main/java/org/dogtagpki/jss/tomcat/TomcatJSS.java +++ b/tomcat/src/main/java/org/dogtagpki/jss/tomcat/TomcatJSS.java @@ -88,7 +88,7 @@ public class TomcatJSS implements SSLSocketListener { boolean requireClientAuth; boolean wantClientAuth; - boolean enableOCSP; + boolean enableRevocationCheck; String ocspResponderURL; String ocspResponderCertNickname; int ocspCacheSize = 1000; // entries @@ -183,12 +183,12 @@ public boolean getWantClientAuth() { return wantClientAuth; } - public boolean getEnableOCSP() { - return enableOCSP; + public boolean getEnableRevocationCheck() { + return enableRevocationCheck; } - public void setEnableOCSP(boolean enableOCSP) { - this.enableOCSP = enableOCSP; + public void setEnableRevocationCheck(boolean enableRevocationCheck) { + this.enableRevocationCheck = enableRevocationCheck; } public String getOcspResponderURL() { @@ -269,7 +269,11 @@ public void loadJSSConfig(Properties config) { String enableOCSPProp = config.getProperty("enableOCSP"); if (enableOCSPProp != null) - setEnableOCSP(Boolean.parseBoolean(enableOCSPProp)); + setEnableRevocationCheck(Boolean.parseBoolean(enableOCSPProp)); + + String enableRevocationCheckProp = config.getProperty("enableRevocationCheck"); + if (enableRevocationCheckProp != null) + setEnableRevocationCheck(Boolean.parseBoolean(enableRevocationCheckProp)); String ocspResponderURLProp = config.getProperty("ocspResponderURL"); if (ocspResponderURLProp != null) @@ -328,31 +332,35 @@ public void loadTomcatConfig(Document document) throws XPathExpressionException } String certDbProp = connector.getAttribute("certdbDir"); - if (certDbProp != null) + if (StringUtils.isNotEmpty(certDbProp)) setCertdbDir(certDbProp); String passwordClassProp = connector.getAttribute("passwordClass"); - if (passwordClassProp != null) + if (StringUtils.isNotEmpty(passwordClassProp)) setPasswordClass(passwordClassProp); String passwordFileProp = connector.getAttribute("passwordFile"); - if (passwordFileProp != null) + if (StringUtils.isNotEmpty(passwordFileProp)) setPasswordFile(passwordFileProp); String serverCertNickFileProp = connector.getAttribute("serverCertNickFile"); - if (serverCertNickFileProp != null) + if (StringUtils.isNotEmpty(serverCertNickFileProp)) setServerCertNickFile(serverCertNickFileProp); String enableOCSPProp = connector.getAttribute("enableOCSP"); - if (enableOCSPProp != null) - setEnableOCSP(Boolean.parseBoolean(enableOCSPProp)); + if (StringUtils.isNotEmpty(enableOCSPProp)) + setEnableRevocationCheck(Boolean.parseBoolean(enableOCSPProp)); + + String enableRevocationCheckProp = connector.getAttribute("enableRevocationCheck"); + if (StringUtils.isNotEmpty(enableRevocationCheckProp)) + setEnableRevocationCheck(Boolean.parseBoolean(enableRevocationCheckProp)); String ocspResponderURLProp = connector.getAttribute("ocspResponderURL"); - if (ocspResponderURLProp != null) + if (StringUtils.isNotEmpty(ocspResponderURLProp)) setOcspResponderURL(ocspResponderURLProp); String ocspResponderCertNicknameProp = connector.getAttribute("ocspResponderCertNickname"); - if (ocspResponderCertNicknameProp != null) + if (StringUtils.isNotEmpty(ocspResponderCertNicknameProp)) setOcspResponderCertNickname(ocspResponderCertNicknameProp); String ocspCacheSizeProp = connector.getAttribute("ocspCacheSize"); @@ -469,7 +477,7 @@ public void init() throws KeyDatabaseException, CertDatabaseException, GeneralSe logger.debug("wantClientAuth: {}", wantClientAuth); if (requireClientAuth || wantClientAuth) { - configureOCSP(); + configureRevocationCheck(); } // 12 hours = 43200 seconds @@ -549,12 +557,12 @@ public CryptoToken getToken(String tag) throws NoSuchTokenException { return null; } - public void configureOCSP() throws GeneralSecurityException, ConfigurationException { + public void configureRevocationCheck() throws GeneralSecurityException, ConfigurationException { - logger.info("configuring OCSP"); + logger.info("configuring Revocation Check"); - logger.debug("enableOCSP: {}", enableOCSP); - if (!enableOCSP) { + logger.debug("enableCertificateCheck: {}", enableRevocationCheck); + if (!enableRevocationCheck) { return; } From ff5589a4f1e5026f4cb622830bf0c0cfeb9bcb1b Mon Sep 17 00:00:00 2001 From: Marco Fargetta Date: Fri, 12 Apr 2024 16:02:52 +0200 Subject: [PATCH 3/3] Add revocation check fallback for PKIX based verification In case of CRLDP and AIA extensions available in the certificate the PKIX verification flags do not allow to implement a fallback mechanism because the fallback remain active also for certificate with only one extension with unexpected behaviour. A more dynamic approach is introduced verifying the presence of the CRLDP extension and setting the flags accordingly. --- .../main/native/org/mozilla/jss/ssl/common.c | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/native/src/main/native/org/mozilla/jss/ssl/common.c b/native/src/main/native/org/mozilla/jss/ssl/common.c index 83fc40dcf..8e2058e24 100644 --- a/native/src/main/native/org/mozilla/jss/ssl/common.c +++ b/native/src/main/native/org/mozilla/jss/ssl/common.c @@ -929,6 +929,21 @@ CERTCertificate *getRoot(CERTCertificate *cert, return root; } + +/* Verify if the CRLDP extension is defined in the certificate. */ +static PRBool JSSL_isCRLDPExtensionInCert(CERTCertificate *cert) +{ + SECStatus rv = CERT_FindCertExtension(cert, + SEC_OID_X509_CRL_DIST_POINTS, + NULL); + if (rv == SECSuccess) { + return PR_TRUE; + } + return PR_FALSE; +} + + + /* Internal helper for the below call. */ static SECStatus JSSL_verifyCertPKIXInternal(CERTCertificate *cert, @@ -941,10 +956,10 @@ JSSL_verifyCertPKIXInternal(CERTCertificate *cert, * * When enabled the checking on the chained CA certificates. * With this policy the verification process does: - * - if one between AIA and CRL-DP is present then it will be used; - * - if AIA and CRL-DP are both presents only AIA is used and in case - * freshin formation cannot be retrieved it fails the validation; - * - it no AIA and CRL-DP are present no revocation check is performed.*/ + * - if only an AIA or an CRL-DP is present, the respective validation method is used; + * - if AIA and CRL-DP are both presents the execution order is: AIA first followed by + * CRL only in case OCSP endpoint does not provide fresh information; + * - if no AIA and CRL-DP are present no revocation check is performed.*/ PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = { /* crl */ CERT_REV_M_TEST_USING_THIS_METHOD | @@ -963,6 +978,14 @@ JSSL_verifyCertPKIXInternal(CERTCertificate *cert, CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO }; + /* if CRL-dp is present in the cert, disable CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO for ocsp */ + if (JSSL_isCRLDPExtensionInCert(cert)) { + ocsp_Enabled_Hard_Policy_LeafFlags[1] = + CERT_REV_M_TEST_USING_THIS_METHOD; + ocsp_Enabled_Hard_Policy_ChainFlags[1] = + CERT_REV_M_TEST_USING_THIS_METHOD; + } + CERTRevocationMethodIndex ocsp_Enabled_Hard_Policy_Method_Preference[1] = { cert_revocation_method_ocsp };