cmp_vfy.c: Use verification callback if cert_acceptable() finds expired cert
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Thu, 6 May 2021 16:49:54 +0000 (18:49 +0200)
committerPauli <pauli@openssl.org>
Thu, 21 Sep 2023 01:15:49 +0000 (11:15 +1000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21656)

crypto/cmp/cmp_vfy.c
doc/man3/OSSL_CMP_validate_msg.pod

index 2d7b2388ced41a792e5e797bf7d0f6b25e24dcca..1869fae696357bb1aab7860416461d1b152b9c2a 100644 (file)
@@ -139,6 +139,24 @@ int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
     return valid;
 }
 
+static int verify_cb_cert(X509_STORE *ts, X509 *cert, int err)
+{
+    X509_STORE_CTX_verify_cb verify_cb;
+    X509_STORE_CTX *csc;
+    int ok = 0;
+
+    if (ts == NULL || (verify_cb = X509_STORE_get_verify_cb(ts)) == NULL)
+        return ok;
+    if ((csc = X509_STORE_CTX_new()) != NULL
+            && X509_STORE_CTX_init(csc, ts, cert, NULL)) {
+        X509_STORE_CTX_set_error(csc, err);
+        X509_STORE_CTX_set_current_cert(csc, cert);
+        ok = (*verify_cb)(0, csc);
+    }
+    X509_STORE_CTX_free(csc);
+    return ok;
+}
+
 /* Return 0 if expect_name != NULL and there is no matching actual_name */
 static int check_name(const OSSL_CMP_CTX *ctx, int log_success,
                       const char *actual_desc, const X509_NAME *actual_name,
@@ -256,9 +274,14 @@ static int cert_acceptable(const OSSL_CMP_CTX *ctx,
     time_cmp = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
                                   X509_get0_notAfter(cert));
     if (time_cmp != 0) {
+        int err = time_cmp > 0 ? X509_V_ERR_CERT_HAS_EXPIRED
+                               : X509_V_ERR_CERT_NOT_YET_VALID;
+
         ossl_cmp_warn(ctx, time_cmp > 0 ? "cert has expired"
                                         : "cert is not yet valid");
-        return 0;
+        if (ctx->log_cb != NULL /* logging not temporarily disabled */
+                && verify_cb_cert(ts, cert, err) <= 0)
+            return 0;
     }
 
     if (!check_name(ctx, 1,
@@ -432,12 +455,6 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
     return ret;
 }
 
-static int no_log_cb(const char *func, const char *file, int line,
-                     OSSL_CMP_severity level, const char *msg)
-{
-    return 1;
-}
-
 /*-
  * Verify message signature with any acceptable and valid candidate cert.
  * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
@@ -465,7 +482,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
 
     /* enable clearing irrelevant errors in attempts to validate sender certs */
     (void)ERR_set_mark();
-    ctx->log_cb = no_log_cb; /* temporarily disable logging */
+    ctx->log_cb = NULL; /* temporarily disable logging */
 
     /*
      * try first cached scrt, used successfully earlier in same transaction,
index 9fe7f4385f0f12c9ff757ad48a9a3bac2eaf74dc..7dbe3f74ca1ebf3c9625eaf1efd33678aa30f22c 100644 (file)
@@ -30,10 +30,12 @@ is preferably the one provided by a call to L<OSSL_CMP_CTX_set1_srvCert(3)>.
 If no such sender cert has been pinned then candidate sender certificates are
 taken from the list of certificates received in the I<msg> extraCerts, then any
 certificates provided before via L<OSSL_CMP_CTX_set1_untrusted(3)>, and
-then all trusted certificates provided via L<OSSL_CMP_CTX_set0_trusted(3)>,
-where a candidate is acceptable only if has not expired, its subject DN matches
+then all trusted certificates provided via L<OSSL_CMP_CTX_set0_trusted(3)>.
+A candidate certificate is acceptable only if it is currently valid
+(or the trust store contains a verification callback that overrides the verdict
+that the certificate is expired or not yet valid), its subject DN matches
 the I<msg> sender DN (as far as present), and its subject key identifier
-is present and matches the senderKID (as far as the latter present).
+is present and matches the senderKID (as far as the latter is present).
 Each acceptable cert is tried in the given order to see if the message
 signature check succeeds and the cert and its path can be verified
 using any trust store set via L<OSSL_CMP_CTX_set0_trusted(3)>.