]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add new public API for checking certificate times.
authorBob Beck <beck@openssl.org>
Fri, 14 Nov 2025 20:36:56 +0000 (13:36 -0700)
committerNeil Horman <nhorman@openssl.org>
Thu, 18 Dec 2025 18:34:58 +0000 (13:34 -0500)
Fixes: #1631
This changes the previously internal ossl_x509_check_certificate_times()
to be the public X509_check_certificate_times(). It adds documentation
for the new function and marks X509_cmp_time, X509_cmp_timeframe,
and X509_cmp_current_time as deprecated in 4.0, as discussed in #1631.

Since the function is now public, we can replace the remaining
uses of deprecated stuff with this function.

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/29152)

16 files changed:
apps/lib/apps.c
apps/x509.c
crypto/cmp/cmp_genm.c
crypto/cmp/cmp_vfy.c
crypto/ocsp/ocsp_cl.c
crypto/x509/t_x509.c
crypto/x509/x509_vfy.c
doc/build.info
doc/man3/X509_check_certificate_times.pod [moved from doc/man3/X509_cmp_time.pod with 54% similarity]
include/crypto/x509.h
include/openssl/macros.h
include/openssl/x509.h.in
test/recipes/25-test_x509.t
test/x509_internal_test.c
test/x509_time_test.c
util/libcrypto.num

index eea7bd79b3ba8c214a2e4c14361ca133f0098bb8..ae9ecfff39dc9ab7acd224463c128846b1b3b075 100644 (file)
@@ -675,18 +675,16 @@ static void warn_cert_msg(const char *uri, X509 *cert, const char *msg)
 static void warn_cert(const char *uri, X509 *cert, int warn_EE,
     X509_VERIFY_PARAM *vpm)
 {
+    int error;
     uint32_t ex_flags = X509_get_extension_flags(cert);
-    /*
-     * This should not be used as as example for how to verify
-     * certificates. This treats an invalid not before or an invalid
-     * not after time in the certificate as infinitely valid, which
-     * you don't want outside of a toy testing function like this.
-     */
-    int res = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
-        X509_get0_notAfter(cert));
 
-    if (res != 0)
-        warn_cert_msg(uri, cert, res > 0 ? "has expired" : "not yet valid");
+    if (!X509_check_certificate_times(vpm, cert, &error)) {
+        char msg[128];
+
+        ERR_error_string_n(error, msg, sizeof(msg));
+        warn_cert_msg(uri, cert, msg);
+    }
+
     if (warn_EE && (ex_flags & EXFLAG_V1) == 0 && (ex_flags & EXFLAG_CA) == 0)
         warn_cert_msg(uri, cert, "is not a CA cert");
 }
index 665d5b85db5c92dd498747dbde9ec84e79369cb5..85c87518e4be21f74bd62685a682e4b3fbe86328 100644 (file)
@@ -1146,19 +1146,37 @@ cert_loop:
     }
 
     if (checkend) {
+        X509_VERIFY_PARAM *vpm;
         time_t tcheck = time(NULL) + checkoffset;
-        int expired = X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0;
+        int expired = 0;
+        int error, valid;
 
-        if (expired)
+        if ((vpm = X509_VERIFY_PARAM_new()) == NULL) {
+            BIO_printf(out, "Malloc failed\n");
+            goto end_cert_loop;
+        }
+        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_CHECK_TIME);
+        X509_VERIFY_PARAM_set_time(vpm, tcheck);
+
+        valid = X509_check_certificate_times(vpm, x, &error);
+        if (!valid) {
+            char msg[128];
+
+            ERR_error_string_n(error, msg, sizeof(msg));
+            BIO_printf(out, "%s\n", msg);
+        }
+        if (error == X509_V_ERR_CERT_HAS_EXPIRED) {
             BIO_printf(out, "Certificate will expire\n");
-        else
+            expired = 1;
+        } else {
             BIO_printf(out, "Certificate will not expire\n");
-
+        }
         if (multi && k > 0)
             ret |= expired;
         else
             ret = expired;
 
+        X509_VERIFY_PARAM_free(vpm);
         if (multi && k < sk_X509_num(certs) - 1)
             goto end_cert_loop;
         else
index 1966be60ece8dc16e1e76be68fd72860f73e43ab..67b053167571afad58413ae2cdb0cb65f114dcd5 100644 (file)
@@ -39,7 +39,7 @@ static int ossl_X509_check(OSSL_CMP_CTX *ctx, const char *source, X509 *cert,
     int ret, err;
     OSSL_CMP_severity level = vpm == NULL ? OSSL_CMP_LOG_WARNING : OSSL_CMP_LOG_ERR;
 
-    ret = ossl_x509_check_certificate_times(vpm, cert, &err);
+    ret = X509_check_certificate_times(vpm, cert, &err);
     if (!ret) {
         const char *msg;
 
index 6d11c7ec0c03b10f627ae89fd08c0385e6d87991..01c7422c38700b60b65f021df3e15c4c13802ce2 100644 (file)
@@ -265,7 +265,7 @@ static int cert_acceptable(const OSSL_CMP_CTX *ctx,
         return 0;
     }
 
-    if (!ossl_x509_check_certificate_times(vpm, cert, &err)) {
+    if (!X509_check_certificate_times(vpm, cert, &err)) {
         const char *message;
 
         switch (err) {
index 22d6692a9151d231313929cc3e91f962f44aa80a..a4f954f9a4fdf6966fa77e11b695e0ff54ade3a1 100644 (file)
@@ -16,6 +16,7 @@
 #include <openssl/pem.h>
 #include <openssl/x509v3.h>
 #include <openssl/ocsp.h>
+#include <openssl/posix_time.h>
 #include "ocsp_local.h"
 
 /*
@@ -288,6 +289,20 @@ int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
     return 1;
 }
 
+static int gentime_to_posix(ASN1_GENERALIZEDTIME *time, int64_t *out_time)
+{
+    struct tm ctm;
+
+    if (!ASN1_GENERALIZEDTIME_check(time))
+        return 0;
+    if (!ASN1_TIME_to_tm(time, &ctm))
+        return 0;
+    if (!OPENSSL_tm_to_posix(&ctm, out_time))
+        return 0;
+
+    return 1;
+}
+
 /*
  * Check validity of thisUpdate and nextUpdate fields. It is possible that
  * the request will take a few seconds to process and/or the time won't be
@@ -299,55 +314,52 @@ int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
 int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
     ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec)
 {
-    int ret = 1;
-    time_t t_now, t_tmp;
+    int64_t t_now, this_time, next_time;
+    int ret = 0;
+
+    if (nsec < 0)
+        nsec = 0;
 
-    time(&t_now);
-    /* Check thisUpdate is valid and not more than nsec in the future */
-    if (!ASN1_GENERALIZEDTIME_check(thisupd)) {
+    t_now = (int64_t)time(NULL);
+    /* Check thisUpdate is valid */
+    if (!gentime_to_posix(thisupd, &this_time)) {
         ERR_raise(ERR_LIB_OCSP, OCSP_R_ERROR_IN_THISUPDATE_FIELD);
-        ret = 0;
-    } else {
-        t_tmp = t_now + nsec;
-        if (X509_cmp_time(thisupd, &t_tmp) > 0) {
-            ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_NOT_YET_VALID);
-            ret = 0;
+        goto err;
+    }
+    /* Check if thisUpdate is more than nsec in the future */
+    if (this_time > t_now + nsec) {
+        ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_NOT_YET_VALID);
+        goto err;
+    }
+    /*
+     * If maxsec specified check thisUpdate is not more than maxsec in
+     * the past
+     */
+    if (maxsec >= 0 && this_time < t_now - maxsec) {
+        ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_TOO_OLD);
+        goto err;
+    }
+    if (nextupd != NULL) {
+        /* Check nextUpdate is valid */
+        if (!gentime_to_posix(nextupd, &next_time)) {
+            ERR_raise(ERR_LIB_OCSP, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD);
+            goto err;
         }
-
-        /*
-         * If maxsec specified check thisUpdate is not more than maxsec in
-         * the past
-         */
-        if (maxsec >= 0) {
-            t_tmp = t_now - maxsec;
-            if (X509_cmp_time(thisupd, &t_tmp) < 0) {
-                ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_TOO_OLD);
-                ret = 0;
-            }
+        /* Check nextUpdate is not more than nsec in the past */
+        if (next_time < t_now - nsec) {
+            ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_NOT_YET_VALID);
+            goto err;
         }
-    }
-
-    if (nextupd == NULL)
-        return ret;
-
-    /* Check nextUpdate is valid and not more than nsec in the past */
-    if (!ASN1_GENERALIZEDTIME_check(nextupd)) {
-        ERR_raise(ERR_LIB_OCSP, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD);
-        ret = 0;
-    } else {
-        t_tmp = t_now - nsec;
-        if (X509_cmp_time(nextupd, &t_tmp) < 0) {
-            ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_EXPIRED);
-            ret = 0;
+        /* Also don't allow nextUpdate to precede thisUpdate */
+        if (next_time < this_time) {
+            ERR_raise(ERR_LIB_OCSP, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
+            goto err;
         }
     }
 
-    /* Also don't allow nextUpdate to precede thisUpdate */
-    if (ASN1_STRING_cmp(nextupd, thisupd) < 0) {
-        ERR_raise(ERR_LIB_OCSP, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
-        ret = 0;
-    }
+    ret = 1;
 
+err:
     return ret;
 }
 
index c4927d357bc2a7dcc3a992ba9b37bc002acea3e0..0c43c50fe6bb7a808737ddab1b0fae1ea3d58875 100644 (file)
@@ -381,31 +381,45 @@ int X509_aux_print(BIO *out, const X509 *x, int indent)
 int ossl_x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags)
 {
     unsigned long flags = ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN;
+    X509_VERIFY_PARAM *vpm = X509_VERIFY_PARAM_new();
+    int error, ret = 0;
 
-    if (cert == NULL)
-        return BIO_printf(bio, "    (no certificate)\n") > 0;
+    if (vpm == NULL) {
+        ret = BIO_printf(bio, "    (malloc failed)\n") > 0;
+        goto err;
+    }
+    if (cert == NULL) {
+        ret = BIO_printf(bio, "    (no certificate)\n") > 0;
+        goto err;
+    }
     if (BIO_printf(bio, "    certificate\n") <= 0
         || !X509_print_ex(bio, cert, flags, ~X509_FLAG_NO_SUBJECT))
-        return 0;
+        goto err;
     if (X509_check_issued((X509 *)cert, cert) == X509_V_OK) {
         if (BIO_printf(bio, "        self-issued\n") <= 0)
-            return 0;
+            goto err;
     } else {
         if (BIO_printf(bio, " ") <= 0
             || !X509_print_ex(bio, cert, flags, ~X509_FLAG_NO_ISSUER))
-            return 0;
+            goto err;
     }
     if (!X509_print_ex(bio, cert, flags,
             ~(X509_FLAG_NO_SERIAL | X509_FLAG_NO_VALIDITY)))
-        return 0;
-    if (X509_cmp_current_time(X509_get0_notBefore(cert)) > 0)
-        if (BIO_printf(bio, "        not yet valid\n") <= 0)
-            return 0;
-    if (X509_cmp_current_time(X509_get0_notAfter(cert)) < 0)
-        if (BIO_printf(bio, "        no more valid\n") <= 0)
-            return 0;
-    return X509_print_ex(bio, cert, flags,
+        goto err;
+
+    if (!X509_check_certificate_times(vpm, cert, &error)) {
+        char msg[128];
+
+        ERR_error_string_n(error, msg, sizeof(msg));
+        if (BIO_printf(bio, "        %s\n", msg) <= 0)
+            goto err;
+    }
+    ret = X509_print_ex(bio, cert, flags,
         ~neg_cflags & ~X509_FLAG_EXTENSIONS_ONLY_KID);
+
+err:
+    X509_VERIFY_PARAM_free(vpm);
+    return ret;
 }
 
 static int print_certs(BIO *bio, const STACK_OF(X509) *certs)
index c535334f24b4d001d79354e5255a054627a15bea..ef15131e821fe4172136f700599acb567f3f9bc4 100644 (file)
@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
+#define OPENSSL_SUPPRESS_DEPRECATED
 #include "internal/deprecated.h"
 
 #include <stdio.h>
@@ -2126,9 +2127,13 @@ memerr:
 /*-
  * Check certificate validity times.
  *
- * Return 1 on success, 0 otherwise.
+ * Returns 1 if the certificate |x| is temporally valid at the
+ * verification time requested by |vpm|, or 0 otherwise. if |error| is
+ * non-NULL, |*error| will be set to 0 when the certificate is
+ * temporally valid, otherwise it will be set to a non-zero error
+ * code.
  */
-int ossl_x509_check_certificate_times(const X509_VERIFY_PARAM *vpm, X509 *x,
+int X509_check_certificate_times(const X509_VERIFY_PARAM *vpm, const X509 *x,
     int *error)
 {
     int ret = 0, err = 0;
@@ -2352,6 +2357,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
     return 1;
 }
 
+#if !defined(OPENSSL_NO_DEPRECATED_4_0)
 int X509_cmp_current_time(const ASN1_TIME *ctm)
 {
     return X509_cmp_time(ctm, NULL);
@@ -2421,6 +2427,7 @@ int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
         return -1;
     return 0;
 }
+#endif /* !defined(OPENSSL_NO_DEPRECATED_4_0) */
 
 ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
 {
index 7b03b5b97baa0442627da88ec56668e00c70d4dd..fdaa35df76dda1e003f2af9793e84a836c3c777e 100644 (file)
@@ -3023,6 +3023,10 @@ DEPEND[html/man3/X509_check_ca.html]=man3/X509_check_ca.pod
 GENERATE[html/man3/X509_check_ca.html]=man3/X509_check_ca.pod
 DEPEND[man/man3/X509_check_ca.3]=man3/X509_check_ca.pod
 GENERATE[man/man3/X509_check_ca.3]=man3/X509_check_ca.pod
+DEPEND[html/man3/X509_check_certificate_times.html]=man3/X509_check_certificate_times.pod
+GENERATE[html/man3/X509_check_certificate_times.html]=man3/X509_check_certificate_times.pod
+DEPEND[man/man3/X509_check_certificate_times.3]=man3/X509_check_certificate_times.pod
+GENERATE[man/man3/X509_check_certificate_times.3]=man3/X509_check_certificate_times.pod
 DEPEND[html/man3/X509_check_host.html]=man3/X509_check_host.pod
 GENERATE[html/man3/X509_check_host.html]=man3/X509_check_host.pod
 DEPEND[man/man3/X509_check_host.3]=man3/X509_check_host.pod
@@ -3043,10 +3047,6 @@ DEPEND[html/man3/X509_cmp.html]=man3/X509_cmp.pod
 GENERATE[html/man3/X509_cmp.html]=man3/X509_cmp.pod
 DEPEND[man/man3/X509_cmp.3]=man3/X509_cmp.pod
 GENERATE[man/man3/X509_cmp.3]=man3/X509_cmp.pod
-DEPEND[html/man3/X509_cmp_time.html]=man3/X509_cmp_time.pod
-GENERATE[html/man3/X509_cmp_time.html]=man3/X509_cmp_time.pod
-DEPEND[man/man3/X509_cmp_time.3]=man3/X509_cmp_time.pod
-GENERATE[man/man3/X509_cmp_time.3]=man3/X509_cmp_time.pod
 DEPEND[html/man3/X509_digest.html]=man3/X509_digest.pod
 GENERATE[html/man3/X509_digest.html]=man3/X509_digest.pod
 DEPEND[man/man3/X509_digest.3]=man3/X509_digest.pod
@@ -3801,12 +3801,12 @@ html/man3/X509_STORE_set_verify_cb_func.html \
 html/man3/X509_VERIFY_PARAM_set_flags.html \
 html/man3/X509_add_cert.html \
 html/man3/X509_check_ca.html \
+html/man3/X509_check_certificate_times.html \
 html/man3/X509_check_host.html \
 html/man3/X509_check_issued.html \
 html/man3/X509_check_private_key.html \
 html/man3/X509_check_purpose.html \
 html/man3/X509_cmp.html \
-html/man3/X509_cmp_time.html \
 html/man3/X509_digest.html \
 html/man3/X509_dup.html \
 html/man3/X509_get0_distinguishing_id.html \
@@ -4473,12 +4473,12 @@ man/man3/X509_STORE_set_verify_cb_func.3 \
 man/man3/X509_VERIFY_PARAM_set_flags.3 \
 man/man3/X509_add_cert.3 \
 man/man3/X509_check_ca.3 \
+man/man3/X509_check_certificate_times.3 \
 man/man3/X509_check_host.3 \
 man/man3/X509_check_issued.3 \
 man/man3/X509_check_private_key.3 \
 man/man3/X509_check_purpose.3 \
 man/man3/X509_cmp.3 \
-man/man3/X509_cmp_time.3 \
 man/man3/X509_digest.3 \
 man/man3/X509_dup.3 \
 man/man3/X509_get0_distinguishing_id.3 \
similarity index 54%
rename from doc/man3/X509_cmp_time.pod
rename to doc/man3/X509_check_certificate_times.pod
index 52b1722c9f25986b3c588acd3d0cc55ca3e5ffd4..fa991784f6a9f8f9179d4dcc1890387c73c95c42 100644 (file)
@@ -2,23 +2,43 @@
 
 =head1 NAME
 
-X509_cmp_time, X509_cmp_current_time, X509_cmp_timeframe,
-X509_time_adj, X509_time_adj_ex, X509_gmtime_adj
-- X509 time functions
+X509_check_certificate_times, X509_time_adj, X509_time_adj_ex, X509_gmtime_adj,
+X509_cmp_time, X509_cmp_current_time, X509_cmp_timeframe - X509 time functions
 
 =head1 SYNOPSIS
 
- int X509_cmp_time(const ASN1_TIME *asn1_time, time_t *in_tm);
- int X509_cmp_current_time(const ASN1_TIME *asn1_time);
- int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
-                        const ASN1_TIME *start, const ASN1_TIME *end);
+ int X509_check_certificate_times(const X509_VERIFY_PARAM *vpm, const X509 *x,
+                                  int *error);
  ASN1_TIME *X509_time_adj(ASN1_TIME *asn1_time, long offset_sec, time_t *in_tm);
  ASN1_TIME *X509_time_adj_ex(ASN1_TIME *asn1_time, int offset_day, long
                              offset_sec, time_t *in_tm);
  ASN1_TIME *X509_gmtime_adj(ASN1_TIME *asn1_time, long offset_sec);
 
+The following functions have been deprecated since OpenSSL 4.0, and can be
+hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
+see L<openssl_user_macros(7)>:
+
+ int X509_cmp_time(const ASN1_TIME *asn1_time, time_t *in_tm);
+ int X509_cmp_current_time(const ASN1_TIME *asn1_time);
+ int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
+                        const ASN1_TIME *start, const ASN1_TIME *end);
+
 =head1 DESCRIPTION
 
+X509_check_certificate_times() compares the notBefore and notAfter
+times in certificate I<x> to check the certificate for temporal validity.
+The time used for the check will be the current system time, unless
+The the reference time included in the verification parameter I<vpm>
+is non NULL and I<vpm> has the flag B<X509_V_FLAG_USE_CHECK_TIME> set.
+
+The notBefore and notAfter times in the certificate will be accepted
+only if they are either the format of a GeneralizedTime
+(YYYYMMDDHHMMSSZ), or a UTCTime (YYMMDDHHMMSSZ) as per RFC5280, with
+the exception that the requirement: "CAs conforming to this profile
+MUST always encode certificate validity dates through the year 2049 as
+UTCTime; certificate validity dates in 2050 or later MUST be encoded
+as GeneralizedTime." is not enforced.
+
 X509_cmp_time() compares the ASN1_TIME in I<asn1_time> with the time
 in <in_tm>.
 
@@ -52,11 +72,35 @@ X509_time_adj() with the last parameter as NULL.
 
 =head1 BUGS
 
-Unlike many standard comparison functions, X509_cmp_time() and
-X509_cmp_current_time() return 0 on error.
+Unlike many standard comparison functions, The deprecated functions
+X509_cmp_time() and X509_cmp_current_time() return 0 on error, and
+return -1 when the values are equal.
+
+The deprecated function X509_cmp_timeframe() may accept invalid
+certificate times as infinitely valid.
 
 =head1 RETURN VALUES
 
+X509_check_certiticate_times() returns 1 if the certificate is
+temporally valid at the verification time as per the rules from RFC
+5280. It returns 0 otherwise. if I<error> is non NULL, the integer
+value it points to will be set to an error code when the certificate
+is not temporally valid, or 0 when the certificate is temporally valid.
+
+The integer pointed to by I<error> will be set to
+X509_V_ERROR_ERROR_IN_CERT_NOT_BEFORE_FIELD
+or
+X509_V_ERROR_ERROR_IN_CERT_NOT_AFTER_FIELD
+if the certificate has an invalid notBefore or notAfter field, respectively.
+
+The integer pointed to by I<error> will be set to
+X509_V_ERR_CERT_NOT_YET_VALID
+or
+X509_V_ERR_CERT_HAS_EXPIRED
+if the
+verification time is outside of the certificate's correctly encoded
+validity window as per RFC5280.
+
 X509_cmp_time() and X509_cmp_current_time() return -1 if I<asn1_time>
 is earlier than, or equal to, I<in_tm> (resp. current time), and 1
 otherwise. These methods return 0 on error.
@@ -85,13 +129,31 @@ as valid forever.
 X509_time_adj(), X509_time_adj_ex() and X509_gmtime_adj() return a pointer to
 the updated ASN1_TIME structure, and NULL on error.
 
+=head1 SEE ALSO
+
+L<ASN1_GENERALIZEDTIME_check(3)>
+L<ASN1_UTCTIME_check(3)>
+L<ASN1_TIME_to_tm(3)>
+L<OPENSSL_tm_to_posix(3)> L<OPENSSL_posix_to_tm(3)>
+L<ERR_error_string_n(3)>
+
 =head1 HISTORY
 
-X509_cmp_timeframe() was added in OpenSSL 3.0.
+X509_cmp_timeframe(), X509_cmp_current_time(), and
+X509_cmp_timeframe() were deprecated in OpenSSL 4.0
+
+For replacement, consider using X509_check_certificate_times() for use
+with X509 certificates. For applications checking individual ASN1_TIME
+values, consider using ASN1_TIME_to_tm(3) with appropriate validity
+checking of the I<ASN1_TIME> value for your application, and subsequent
+comparison of either the resulting I<tm> structure, or conversion to
+posix seconds via OPENSSL_tm_to_posix(3)
+
+X509_check_certificate_times() was added in OpenSSL 4.0.
 
 =head1 COPYRIGHT
 
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2025 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
index 608b78dc1581c041dc0a12c0d929dca1f0cfddd6..95367b8ff25b21fc08c62cb1a5d928a538297019 100644 (file)
@@ -399,8 +399,6 @@ int ossl_serial_number_print(BIO *out, const ASN1_INTEGER *bs, int indent);
 int ossl_bio_print_hex(BIO *out, unsigned char *buf, int len);
 int ossl_x509_compare_asn1_time(const X509_VERIFY_PARAM *vpm,
     const ASN1_TIME *time, int *comparison);
-int ossl_x509_check_certificate_times(const X509_VERIFY_PARAM *vpm, X509 *x,
-    int *error);
 /* No error callback if depth < 0 */
 int ossl_x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth);
 int ossl_x509_check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify);
index e149a27f6e13119988eea210ca5b6c96348687ad..653b1926b23aed637fc78ded33793b9127567663 100644 (file)
@@ -49,6 +49,9 @@
 #define OSSL_DEPRECATED_FOR(since, message) __declspec(deprecated)
 #define OSSL_DEPRECATED_MESSAGE(message) __declspec(deprecated)
 #endif
+#define OSSL_BEGIN_ALLOW_DEPRECATED \
+    __pragma(warning(push)) __pragma(warning(disable : 4996))
+#define OSSL_END_ALLOW_DEPRECATED __pragma(warning(pop))
 #elif defined(__GNUC__)
 /*
  * According to GCC documentation, deprecations with message appeared in
 #define OSSL_DEPRECATED_FOR(since, message) __attribute__((deprecated))
 #define OSSL_DEPRECATED_MESSAGE(message) __attribute__((deprecated))
 #endif
+#define OSSL_BEGIN_ALLOW_DEPRECATED \
+    _Pragma("GCC diagnostic push")  \
+        _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#define OSSL_END_ALLOW_DEPRECATED _Pragma("GCC diagnostic pop")
 #elif defined(__SUNPRO_C)
 #if (__SUNPRO_C >= 0x5130)
 #define OSSL_DEPRECATED(since) __attribute__((deprecated))
 #define OSSL_DEPRECATED_FOR(since, message) __attribute__((deprecated))
 #define OSSL_DEPRECATED_MESSAGE(message) __attribute__((deprecated))
 #endif
+#define OSSL_BEGIN_ALLOW_DEPRECATED \
+    #pragma error_messages(off, E_DEPRECATED_ATT, E_DEPRECATED_ATT_MESS)
+#define OSSL_END_ALLOW_DEPRECATED \
+    #pragma error_messages(on, E_DEPRECATED_ATT, E_DEPRECATED_ATT_MESS)
 #endif
 #endif
 #endif
index a0e17b862b7b8a72aeb7c9286b0619251e45a80d..9c99332fee5842adb3f61856eef14d6450ab38cb 100644 (file)
@@ -495,10 +495,15 @@ int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src);
 DECLARE_ASN1_DUP_FUNCTION(X509_NAME)
 DECLARE_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
 
-int X509_cmp_time(const ASN1_TIME *s, time_t *t);
-int X509_cmp_current_time(const ASN1_TIME *s);
-int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
-    const ASN1_TIME *start, const ASN1_TIME *end);
+#ifndef OPENSSL_NO_DEPRECATED_4_0
+OSSL_DEPRECATEDIN_4_0 int X509_cmp_time(const ASN1_TIME *s, time_t *t);
+OSSL_DEPRECATEDIN_4_0 int X509_cmp_current_time(const ASN1_TIME *s);
+OSSL_DEPRECATEDIN_4_0 int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
+    const ASN1_TIME *start,
+    const ASN1_TIME *end);
+#endif
+int X509_check_certificate_times(const X509_VERIFY_PARAM *vpm, const X509 *x,
+    int *error);
 ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
 ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
     int offset_day, long offset_sec, time_t *t);
index 665ea164c6384d5dec5895cebacaf55f2afb132d..34a6d17be15483d473979ce6ab9ac778542a2da6 100644 (file)
@@ -670,8 +670,9 @@ ok(!run(app(["openssl", "x509", "-checkend", $delta_early + 3600,
 # Single + expiring at boundary
 # Test may fail erroneously due to sequential now() calls
 # See https://github.com/openssl/openssl/pull/29155
+# Certificate should be valid at exact NotAfter time.
 my $delta_exact = Time::Piece->strptime( get_field($c_early, "Not After "),
-                    "%b %d %T %Y %Z")->epoch - Time::Piece->gmtime->epoch;
+                    "%b %d %T %Y %Z")->epoch - Time::Piece->gmtime->epoch + 1;
 ok(!run(app(["openssl", "x509", "-checkend", $delta_exact, "-in", $c_early])),
     "Single cert + expiring at -checkend boundary");
 # Multi + none expiring
index 8482e6b47d4bd26b722f935503b897cf5843e495..ecd6d7651ea358a62408e9809b219f56e73bd007 100644 (file)
@@ -308,8 +308,8 @@ static int test_a_time(X509_STORE_CTX *ctx, X509 *x509,
         return 1;
     }
     error = 0;
-    if (ossl_x509_check_certificate_times(vpm, x509, &error) != expected_value) {
-        TEST_info("%s:%d - ossl_X509_check_certificate_times %s unexpectedly "
+    if (X509_check_certificate_times(vpm, x509, &error) != expected_value) {
+        TEST_info("%s:%d - X509_check_certificate_times %s unexpectedly "
                   "when verifying notBefore %lld, notAfter %lld at time %lld\n",
             file, line,
             expected_value ? "failed" : "succeeded",
index b96a627bb5af0d4ca7b500addfadf637baba0380..4737876de478d1a69be4ab4a909e9ef3d4b1c528 100644 (file)
@@ -214,6 +214,7 @@ static TESTDATA_FORMAT x509_format_tests[] = {
     },
 };
 
+#if !defined(OPENSSL_NO_DEPRECATED_4_0)
 static TESTDATA x509_cmp_tests[] = {
     {
         "20170217180154Z",
@@ -413,7 +414,9 @@ static int test_x509_cmp_time(int idx)
     t.length = (int)strlen(x509_cmp_tests[idx].data);
     t.flags = 0;
 
+    OSSL_BEGIN_ALLOW_DEPRECATED
     result = X509_cmp_time(&t, &x509_cmp_tests[idx].cmp_time);
+    OSSL_END_ALLOW_DEPRECATED
     if (!TEST_int_eq(result, x509_cmp_tests[idx].expected)) {
         TEST_info("test_x509_cmp_time(%d) failed: expected %d, got %d\n",
             idx, x509_cmp_tests[idx].expected, result);
@@ -434,6 +437,7 @@ static int test_x509_cmp_time_current(void)
     asn1_now = ASN1_TIME_adj(NULL, now, 0, 0);
 
     /* X509_cmp_time is expected to return -1 for equal */
+    OSSL_BEGIN_ALLOW_DEPRECATED
     cmp_result = X509_cmp_time(asn1_now, &now);
     if (!TEST_int_eq(cmp_result, -1))
         failed = 1;
@@ -445,6 +449,7 @@ static int test_x509_cmp_time_current(void)
     cmp_result = X509_cmp_time(asn1_after, &now);
     if (!TEST_int_eq(cmp_result, 1))
         failed = 1;
+    OSSL_END_ALLOW_DEPRECATED
 
     ASN1_TIME_free(asn1_before);
     ASN1_TIME_free(asn1_after);
@@ -462,6 +467,7 @@ static int test_X509_cmp_timeframe_vpm(const X509_VERIFY_PARAM *vpm,
         && (X509_VERIFY_PARAM_get_flags(vpm) & X509_V_FLAG_USE_CHECK_TIME) == 0
         && (X509_VERIFY_PARAM_get_flags(vpm) & X509_V_FLAG_NO_CHECK_TIME) != 0;
 
+    OSSL_BEGIN_ALLOW_DEPRECATED
     return asn1_before != NULL && asn1_mid != NULL && asn1_after != NULL
         && TEST_int_eq(X509_cmp_timeframe(vpm, asn1_before, asn1_after), 0)
         && TEST_int_eq(X509_cmp_timeframe(vpm, asn1_before, NULL), 0)
@@ -473,6 +479,7 @@ static int test_X509_cmp_timeframe_vpm(const X509_VERIFY_PARAM *vpm,
             always_0 ? 0 : 1)
         && TEST_int_eq(X509_cmp_timeframe(vpm, asn1_after, asn1_before),
             always_0 ? 0 : 1);
+    OSSL_END_ALLOW_DEPRECATED
 }
 
 static int test_X509_cmp_timeframe(void)
@@ -504,6 +511,7 @@ finish:
 
     return res;
 }
+#endif /* !defined(OPENSSL_NO_DEPRECATED_4_0) */
 
 static int test_x509_time(int idx)
 {
@@ -749,9 +757,11 @@ err:
 
 int setup_tests(void)
 {
+#if !defined(OPENSSL_NO_DEPRECATED_4_0)
     ADD_TEST(test_x509_cmp_time_current);
     ADD_TEST(test_X509_cmp_timeframe);
     ADD_ALL_TESTS(test_x509_cmp_time, OSSL_NELEM(x509_cmp_tests));
+#endif /* !defined(OPENSSL_NO_DEPRECATED_4_0) */
     ADD_ALL_TESTS(test_x509_time, OSSL_NELEM(x509_format_tests));
     ADD_ALL_TESTS(test_days, OSSL_NELEM(day_of_week_tests));
     ADD_ALL_TESTS(test_x509_time_print_rfc_822, OSSL_NELEM(x509_print_tests_rfc_822));
index 5e4e18b0fe7e75410274a44c2adb10c227b6b5f6..16a60ba98cb6de26dfa0758fbacc2d78645a7738 100644 (file)
@@ -4427,9 +4427,10 @@ X509_ALGOR_cmp                          ?        4_0_0   EXIST::FUNCTION:
 X509_ALGOR_copy                         ?      4_0_0   EXIST::FUNCTION:
 X509_NAME_dup                           ?      4_0_0   EXIST::FUNCTION:
 X509_NAME_ENTRY_dup                     ?      4_0_0   EXIST::FUNCTION:
-X509_cmp_time                           ?      4_0_0   EXIST::FUNCTION:
-X509_cmp_current_time                   ?      4_0_0   EXIST::FUNCTION:
-X509_cmp_timeframe                      ?      4_0_0   EXIST::FUNCTION:
+X509_cmp_time                           ?      4_0_0   EXIST::FUNCTION:DEPRECATEDIN_4_0
+X509_cmp_current_time                   ?      4_0_0   EXIST::FUNCTION:DEPRECATEDIN_4_0
+X509_cmp_timeframe                      ?      4_0_0   EXIST::FUNCTION:DEPRECATEDIN_4_0
+X509_check_certificate_times            ?      4_0_0   EXIST::FUNCTION:
 X509_time_adj                           ?      4_0_0   EXIST::FUNCTION:
 X509_time_adj_ex                        ?      4_0_0   EXIST::FUNCTION:
 X509_gmtime_adj                         ?      4_0_0   EXIST::FUNCTION: