Add new public API for checking certificate times.
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)
This commit is contained in:
parent
5cbbced70d
commit
4036f4b0e3
16 changed files with 238 additions and 101 deletions
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
26
apps/x509.c
26
apps/x509.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
time(&t_now);
|
||||
/* Check thisUpdate is valid and not more than nsec in the future */
|
||||
if (!ASN1_GENERALIZEDTIME_check(thisupd)) {
|
||||
if (nsec < 0)
|
||||
nsec = 0;
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
/* 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);
|
||||
ret = 0;
|
||||
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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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 (ASN1_STRING_cmp(nextupd, thisupd) < 0) {
|
||||
ERR_raise(ERR_LIB_OCSP, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
|
||||
ret = 0;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -65,12 +68,20 @@
|
|||
#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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue