Cache sha512 hash and parsed not_before and not_after with X509 cert.
authorbeck <beck@openbsd.org>
Thu, 4 Nov 2021 23:52:34 +0000 (23:52 +0000)
committerbeck <beck@openbsd.org>
Thu, 4 Nov 2021 23:52:34 +0000 (23:52 +0000)
Replace sha1 hash use with sha512 for certificate comparisons internal
to the library. use the cached sha512 for the validator's verification
cache.

Reduces our recomputation of hashes, and heavy use of time1 time
conversion functions noticed bu claudio@ in rpki client.

ok jsing@ tb@

lib/libcrypto/ts/ts_rsp_sign.c
lib/libcrypto/ts/ts_rsp_verify.c
lib/libcrypto/x509/x509_cmp.c
lib/libcrypto/x509/x509_internal.h
lib/libcrypto/x509/x509_lcl.h
lib/libcrypto/x509/x509_purp.c
lib/libcrypto/x509/x509_verify.c
lib/libcrypto/x509/x509_verify.h
lib/libcrypto/x509/x509_vfy.c

index 828407a..cbd7039 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ts_rsp_sign.c,v 1.24 2021/11/01 20:53:08 tb Exp $ */
+/* $OpenBSD: ts_rsp_sign.c,v 1.25 2021/11/04 23:52:34 beck Exp $ */
 /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
  * project 2002.
  */
@@ -849,14 +849,18 @@ ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
 {
        ESS_CERT_ID *cid = NULL;
        GENERAL_NAME *name = NULL;
+       unsigned char cert_hash[TS_HASH_LEN];
 
        /* Recompute SHA1 hash of certificate if necessary (side effect). */
        X509_check_purpose(cert, -1, 0);
 
        if (!(cid = ESS_CERT_ID_new()))
                goto err;
-       if (!ASN1_OCTET_STRING_set(cid->hash, cert->sha1_hash,
-           sizeof(cert->sha1_hash)))
+
+       if (!X509_digest(cert, TS_HASH_EVP, cert_hash, NULL))
+               goto err;
+
+       if (!ASN1_OCTET_STRING_set(cid->hash, cert_hash, sizeof(cert_hash)))
                goto err;
 
        /* Setting the issuer/serial if requested. */
index 2e72ff4..0757894 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ts_rsp_verify.c,v 1.22 2021/11/01 20:53:08 tb Exp $ */
+/* $OpenBSD: ts_rsp_verify.c,v 1.23 2021/11/04 23:52:34 beck Exp $ */
 /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
  * project 2002.
  */
@@ -325,10 +325,14 @@ static int
 TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
 {
        int i;
+       unsigned char cert_hash[TS_HASH_LEN];
 
        if (!cert_ids || !cert)
                return -1;
 
+       if (!X509_digest(cert, TS_HASH_EVP, cert_hash, NULL))
+               return -1;
+
        /* Recompute SHA1 hash of certificate if necessary (side effect). */
        X509_check_purpose(cert, -1, 0);
 
@@ -337,9 +341,8 @@ TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
                ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i);
 
                /* Check the SHA-1 hash first. */
-               if (cid->hash->length == sizeof(cert->sha1_hash) &&
-                   !memcmp(cid->hash->data, cert->sha1_hash,
-                       sizeof(cert->sha1_hash))) {
+               if (cid->hash->length == TS_HASH_LEN && !memcmp(cid->hash->data,
+                   cert_hash, TS_HASH_LEN)) {
                        /* Check the issuer/serial as well if specified. */
                        ESS_ISSUER_SERIAL *is = cid->issuer_serial;
                        if (!is || !TS_issuer_serial_cmp(is, cert->cert_info))
index 134a082..bc944b7 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509_cmp.c,v 1.36 2021/11/01 20:53:08 tb Exp $ */
+/* $OpenBSD: x509_cmp.c,v 1.37 2021/11/04 23:52:34 beck Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -215,7 +215,7 @@ X509_cmp(const X509 *a, const X509 *b)
        X509_check_purpose((X509 *)a, -1, 0);
        X509_check_purpose((X509 *)b, -1, 0);
 
-       return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+       return memcmp(a->hash, b->hash, X509_CERT_HASH_LEN);
 }
 #endif
 
index 7ca67a8..a9b584b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509_internal.h,v 1.14 2021/11/01 20:53:08 tb Exp $ */
+/* $OpenBSD: x509_internal.h,v 1.15 2021/11/04 23:52:34 beck Exp $ */
 /*
  * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
  *
@@ -96,8 +96,7 @@ int x509_vfy_callback_indicate_success(X509_STORE_CTX *ctx);
 void x509v3_cache_extensions(X509 *x);
 X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x);
 
-int x509_verify_asn1_time_to_tm(const ASN1_TIME *atime, struct tm *tm,
-    int notafter);
+time_t x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notafter);
 
 struct x509_verify_ctx *x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc);
 
@@ -132,6 +131,7 @@ int x509_constraints_check(struct x509_constraints_names *names,
     struct x509_constraints_names *excluded, int *error);
 int x509_constraints_chain(STACK_OF(X509) *chain, int *error,
     int *depth);
+void x509_verify_cert_info_populate(X509 *cert);
 
 __END_HIDDEN_DECLS
 
index 1b352ae..804fff4 100644 (file)
 
 __BEGIN_HIDDEN_DECLS
 
+#define TS_HASH_EVP            EVP_sha1()
+#define TS_HASH_LEN            SHA_DIGEST_LENGTH
+
+#define X509_CERT_HASH_EVP     EVP_sha512()
+#define X509_CERT_HASH_LEN     SHA512_DIGEST_LENGTH
+
 struct X509_pubkey_st {
        X509_ALGOR *algor;
        ASN1_BIT_STRING *public_key;
@@ -177,9 +183,9 @@ struct x509_st {
        STACK_OF(IPAddressFamily) *rfc3779_addr;
        struct ASIdentifiers_st *rfc3779_asid;
 #endif
-#ifndef OPENSSL_NO_SHA
-       unsigned char sha1_hash[SHA_DIGEST_LENGTH];
-#endif
+       unsigned char hash[X509_CERT_HASH_LEN];
+       time_t not_before;
+       time_t not_after;
        X509_CERT_AUX *aux;
 } /* X509 */;
 
index 67a7b51..a05c038 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509_purp.c,v 1.12 2021/11/01 20:53:08 tb Exp $ */
+/* $OpenBSD: x509_purp.c,v 1.13 2021/11/04 23:52:34 beck Exp $ */
 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2001.
  */
@@ -65,6 +65,7 @@
 #include <openssl/x509v3.h>
 #include <openssl/x509_vfy.h>
 
+#include "x509_internal.h"
 #include "x509_lcl.h"
 
 #define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
@@ -449,9 +450,7 @@ x509v3_cache_extensions(X509 *x)
        if (x->ex_flags & EXFLAG_SET)
                return;
 
-#ifndef OPENSSL_NO_SHA
-       X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
-#endif
+       X509_digest(x, X509_CERT_HASH_EVP, x->hash, NULL);
 
        /* V1 should mean no extensions ... */
        if (!X509_get_version(x))
@@ -618,6 +617,9 @@ x509v3_cache_extensions(X509 *x)
                        break;
                }
        }
+
+       x509_verify_cert_info_populate(x);
+
        x->ex_flags |= EXFLAG_SET;
 }
 
index 8bcc647..b9ba2be 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509_verify.c,v 1.50 2021/10/26 15:14:18 job Exp $ */
+/* $OpenBSD: x509_verify.c,v 1.51 2021/11/04 23:52:34 beck Exp $ */
 /*
  * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org>
  *
@@ -38,7 +38,58 @@ static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert,
     size_t depth, int error, int ok);
 static void x509_verify_chain_free(struct x509_verify_chain *chain);
 
-#define X509_VERIFY_CERT_HASH (EVP_sha512())
+/*
+ * Parse an asn1 to a representable time_t as per RFC 5280 rules.
+ * Returns -1 if that can't be done for any reason.
+ */
+time_t
+x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notAfter)
+{
+       struct tm tm = { 0 };
+       int type;
+
+       type = ASN1_time_parse(atime->data, atime->length, &tm, atime->type);
+       if (type == -1)
+               return -1;
+
+       /* RFC 5280 section 4.1.2.5 */
+       if (tm.tm_year < 150 && type != V_ASN1_UTCTIME)
+               return -1;
+       if (tm.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME)
+               return -1;
+
+       if (notAfter) {
+               /*
+                * If we are a completely broken operating system with a
+                * 32 bit time_t, and we have been told this is a notAfter
+                * date, limit the date to a 32 bit representable value.
+                */
+               if (!ASN1_time_tm_clamp_notafter(&tm))
+                       return -1;
+       }
+
+       /*
+        * Defensively fail if the time string is not representable as
+        * a time_t. A time_t must be sane if you care about times after
+        * Jan 19 2038.
+        */
+       return timegm(&tm);
+}
+
+/*
+ * Cache certificate hash, and values parsed out of an X509.
+ * called from cache_extensions()
+ */
+void
+x509_verify_cert_info_populate(X509 *cert)
+{
+       /*
+        * Parse and save the cert times, or remember that they
+        * are unacceptable/unparsable.
+        */
+       cert->not_before = x509_verify_asn1_time_to_time_t(X509_get_notBefore(cert), 0);
+       cert->not_after = x509_verify_asn1_time_to_time_t(X509_get_notAfter(cert), 1);
+}
 
 struct x509_verify_chain *
 x509_verify_chain_new(void)
@@ -194,6 +245,7 @@ x509_verify_cert_cache_extensions(X509 *cert) {
        }
        if (cert->ex_flags & EXFLAG_INVALID)
                return 0;
+
        return (cert->ex_flags & EXFLAG_SET);
 }
 
@@ -455,22 +507,15 @@ x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent,
 }
 
 static int
-x509_verify_parent_signature(X509 *parent, X509 *child,
-    unsigned char *child_md, int *error)
+x509_verify_parent_signature(X509 *parent, X509 *child, int *error)
 {
-       unsigned char parent_md[EVP_MAX_MD_SIZE] = { 0 };
        EVP_PKEY *pkey;
        int cached;
        int ret = 0;
 
        /* Use cached value if we have it */
-       if (child_md != NULL) {
-               if (!X509_digest(parent, X509_VERIFY_CERT_HASH, parent_md,
-                   NULL))
-                       return 0;
-               if ((cached = x509_issuer_cache_find(parent_md, child_md)) >= 0)
-                       return cached;
-       }
+       if ((cached = x509_issuer_cache_find(parent->hash, child->hash)) >= 0)
+               return cached;
 
        /* Check signature. Did parent sign child? */
        if ((pkey = X509_get_pubkey(parent)) == NULL) {
@@ -483,8 +528,7 @@ x509_verify_parent_signature(X509 *parent, X509 *child,
                ret = 1;
 
        /* Add result to cache */
-       if (child_md != NULL)
-               x509_issuer_cache_add(parent_md, child_md, ret);
+       x509_issuer_cache_add(parent->hash, child->hash, ret);
 
        EVP_PKEY_free(pkey);
 
@@ -493,8 +537,8 @@ x509_verify_parent_signature(X509 *parent, X509 *child,
 
 static int
 x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
-    unsigned char *cert_md, int is_root_cert, X509 *candidate,
-    struct x509_verify_chain *current_chain, int full_chain)
+    int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain,
+    int full_chain)
 {
        int depth = sk_X509_num(current_chain->certs);
        struct x509_verify_chain *new_chain;
@@ -514,8 +558,7 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
                return 0;
        }
 
-       if (!x509_verify_parent_signature(candidate, cert, cert_md,
-           &ctx->error)) {
+       if (!x509_verify_parent_signature(candidate, cert, &ctx->error)) {
                if (!x509_verify_cert_error(ctx, candidate, depth,
                    ctx->error, 0))
                        return 0;
@@ -579,7 +622,6 @@ static void
 x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
     struct x509_verify_chain *current_chain, int full_chain)
 {
-       unsigned char cert_md[EVP_MAX_MD_SIZE] = { 0 };
        X509 *candidate;
        int i, depth, count, ret, is_root;
 
@@ -600,11 +642,6 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
                X509_V_ERR_CERT_CHAIN_TOO_LONG, 0))
                return;
 
-       if (!X509_digest(cert, X509_VERIFY_CERT_HASH, cert_md, NULL) &&
-           !x509_verify_cert_error(ctx, cert, depth,
-               X509_V_ERR_UNSPECIFIED, 0))
-               return;
-
        count = ctx->chains_count;
 
        ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
@@ -640,7 +677,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
                                is_root = !full_chain ||
                                    x509_verify_cert_self_signed(candidate);
                                x509_verify_consider_candidate(ctx, cert,
-                                   cert_md, is_root, candidate, current_chain,
+                                   is_root, candidate, current_chain,
                                    full_chain);
                        }
                        X509_free(candidate);
@@ -653,7 +690,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
                                is_root = !full_chain ||
                                    x509_verify_cert_self_signed(candidate);
                                x509_verify_consider_candidate(ctx, cert,
-                                   cert_md, is_root, candidate, current_chain,
+                                   is_root, candidate, current_chain,
                                    full_chain);
                        }
                }
@@ -665,7 +702,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
                        candidate = sk_X509_value(ctx->intermediates, i);
                        if (x509_verify_potential_parent(ctx, candidate, cert)) {
                                x509_verify_consider_candidate(ctx, cert,
-                                   cert_md, 0, candidate, current_chain,
+                                   0, candidate, current_chain,
                                    full_chain);
                        }
                }
@@ -748,47 +785,9 @@ x509_verify_set_check_time(struct x509_verify_ctx *ctx) {
        return 1;
 }
 
-int
-x509_verify_asn1_time_to_tm(const ASN1_TIME *atime, struct tm *tm, int notafter)
-{
-       int type;
-
-       type = ASN1_time_parse(atime->data, atime->length, tm, atime->type);
-       if (type == -1)
-               return 0;
-
-       /* RFC 5280 section 4.1.2.5 */
-       if (tm->tm_year < 150 && type != V_ASN1_UTCTIME)
-               return 0;
-       if (tm->tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME)
-               return 0;
-
-       if (notafter) {
-               /*
-                * If we are a completely broken operating system with a
-                * 32 bit time_t, and we have been told this is a notafter
-                * date, limit the date to a 32 bit representable value.
-                */
-               if (!ASN1_time_tm_clamp_notafter(tm))
-                       return 0;
-       }
-
-       /*
-        * Defensively fail if the time string is not representable as
-        * a time_t. A time_t must be sane if you care about times after
-        * Jan 19 2038.
-        */
-       if (timegm(tm) == -1)
-               return 0;
-
-       return 1;
-}
-
 static int
-x509_verify_cert_time(int is_notafter, const ASN1_TIME *cert_asn1,
-    time_t *cmp_time, int *error)
+x509_verify_cert_times(X509 *cert, time_t *cmp_time, int *error)
 {
-       struct tm cert_tm, when_tm;
        time_t when;
 
        if (cmp_time == NULL)
@@ -796,29 +795,21 @@ x509_verify_cert_time(int is_notafter, const ASN1_TIME *cert_asn1,
        else
                when = *cmp_time;
 
-       if (!x509_verify_asn1_time_to_tm(cert_asn1, &cert_tm,
-           is_notafter)) {
-               *error = is_notafter ?
-                   X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD :
-                   X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+       if (cert->not_before == -1) {
+               *error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
                return 0;
        }
-
-       if (gmtime_r(&when, &when_tm) == NULL) {
-               *error = X509_V_ERR_UNSPECIFIED;
+       if (when < cert->not_before) {
+               *error = X509_V_ERR_CERT_NOT_YET_VALID;
                return 0;
        }
-
-       if (is_notafter) {
-               if (ASN1_time_tm_cmp(&cert_tm, &when_tm) == -1) {
-                       *error = X509_V_ERR_CERT_HAS_EXPIRED;
-                       return 0;
-               }
-       } else  {
-               if (ASN1_time_tm_cmp(&cert_tm, &when_tm) == 1) {
-                       *error = X509_V_ERR_CERT_NOT_YET_VALID;
-                       return 0;
-               }
+       if (cert->not_after == -1) {
+               *error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+               return 0;
+       }
+       if (when > cert->not_after) {
+               *error = X509_V_ERR_CERT_HAS_EXPIRED;
+               return 0;
        }
 
        return 1;
@@ -924,15 +915,8 @@ x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert,
        }
 
        if (x509_verify_set_check_time(ctx)) {
-               if (!x509_verify_cert_time(0, X509_get_notBefore(cert),
-                   ctx->check_time, &ctx->error)) {
-                       if (!x509_verify_cert_error(ctx, cert, depth,
-                           ctx->error, 0))
-                               return 0;
-               }
-
-               if (!x509_verify_cert_time(1, X509_get_notAfter(cert),
-                   ctx->check_time, &ctx->error)) {
+               if (!x509_verify_cert_times(cert, ctx->check_time,
+                   &ctx->error)) {
                        if (!x509_verify_cert_error(ctx, cert, depth,
                            ctx->error, 0))
                                return 0;
index a097404..d8d2cb0 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509_verify.h,v 1.1 2020/09/13 15:06:17 beck Exp $ */
+/* $OpenBSD: x509_verify.h,v 1.2 2021/11/04 23:52:34 beck Exp $ */
 /*
  * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
  *
@@ -19,6 +19,7 @@
 
 #ifdef LIBRESSL_INTERNAL
 struct x509_verify_ctx;
+struct x509_verify_cert_info;
 typedef struct x509_verify_ctx X509_VERIFY_CTX;
 
 X509_VERIFY_CTX *x509_verify_ctx_new(STACK_OF(X509) *roots);
index 6644741..3b0d6df 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509_vfy.c,v 1.93 2021/11/01 20:53:08 tb Exp $ */
+/* $OpenBSD: x509_vfy.c,v 1.94 2021/11/04 23:52:34 beck Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -1843,6 +1843,18 @@ verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err)
        return ctx->verify_cb(0, ctx);
 }
 
+
+/* Mimic OpenSSL '0 for failure' ick */
+static int
+time_t_bogocmp(time_t a, time_t b)
+{
+       if (a == -1 || b == -1)
+               return 0;
+       if (a <= b)
+               return -1;
+       return 1;
+}
+
 /*
  * Check certificate validity times.
  *
@@ -1854,17 +1866,21 @@ verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err)
 int
 x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
 {
-       time_t *ptime;
+       time_t ptime;
        int i;
 
        if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
-               ptime = &ctx->param->check_time;
+               ptime = ctx->param->check_time;
        else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME)
                return 1;
        else
-               ptime = NULL;
+               ptime = time(NULL);
+
+       if (x->ex_flags & EXFLAG_SET)
+               i = time_t_bogocmp(x->not_before, ptime);
+       else
+               i = X509_cmp_time(X509_get_notBefore(x), &ptime);
 
-       i = X509_cmp_time(X509_get_notBefore(x), ptime);
        if (i >= 0 && depth < 0)
                return 0;
        if (i == 0 && !verify_cb_cert(ctx, x, depth,
@@ -1874,7 +1890,11 @@ x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
            X509_V_ERR_CERT_NOT_YET_VALID))
                return 0;
 
-       i = X509_cmp_time_internal(X509_get_notAfter(x), ptime, 1);
+       if (x->ex_flags & EXFLAG_SET)
+               i = time_t_bogocmp(x->not_after, ptime);
+       else
+               i = X509_cmp_time_internal(X509_get_notAfter(x), &ptime, 1);
+
        if (i <= 0 && depth < 0)
                return 0;
        if (i == 0 && !verify_cb_cert(ctx, x, depth,
@@ -1883,6 +1903,7 @@ x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
        if (i < 0 && !verify_cb_cert(ctx, x, depth,
            X509_V_ERR_CERT_HAS_EXPIRED))
                return 0;
+
        return 1;
 }
 
@@ -1994,30 +2015,23 @@ X509_cmp_current_time(const ASN1_TIME *ctm)
  * 0 on error.
  */
 static int
-X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time, int clamp_notafter)
+X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time, int is_notafter)
 {
-       time_t compare;
-       struct tm tm1, tm2;
-       int ret = 0;
+       time_t compare, cert_time;
 
        if (cmp_time == NULL)
                compare = time(NULL);
        else
                compare = *cmp_time;
 
-       memset(&tm1, 0, sizeof(tm1));
+       if ((cert_time = x509_verify_asn1_time_to_time_t(ctm, is_notafter)) ==
+           -1)
+               return 0; /* invalid time */
 
-       if (!x509_verify_asn1_time_to_tm(ctm, &tm1, clamp_notafter))
-               goto out; /* invalid time */
+       if (cert_time <= compare)
+               return -1; /* 0 is used for error, so map same to less than */
 
-       if (gmtime_r(&compare, &tm2) == NULL)
-               goto out;
-
-       ret = ASN1_time_tm_cmp(&tm1, &tm2);
-       if (ret == 0)
-               ret = -1; /* 0 is used for error, so map same to less than */
- out:
-       return (ret);
+       return 1;
 }
 
 int