[PATCH] allow notAfter after 2038 with 32-bit time_t

Previous Topic Next Topic
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
Report Content as Inappropriate

[PATCH] allow notAfter after 2038 with 32-bit time_t

Kyle J. McKay
RFC 5280 section states:

    To indicate that a certificate has no well-defined expiration date,
    the notAfter SHOULD be assigned the GeneralizedTime value of

Unfortunately, if sizeof(time_t) == 4, 9999-12-31T23:59:59Z cannot be
represented as a time_t value causing valid certificates to be rejected
just because the notAfter value is after 2038-01-19T03:14:07Z.

Fix this problem by disabling the restriction in the X509_cmp_time function
and "wrap" far in the future notAfter values to 2038-01-19T03:14:07Z in the
tls_get_peer_cert_times function.

With both of these changes certificates with "no well-defined expiration
date" as specified by RFC 5280 are again accepted on platforms where the
sizeof(time_t) == 4.

In general, there's no reason that a notAfter value should not be wrapped
to 2038-01-19T03:14:07Z on a system with a 32-bit time_t.  The system itself
can never have a time after 2038-01-19T03:14:07Z because of the size of the
time_t type and so wrapping a notAfter date that is after 2038-01-19T03:14:07Z
to 2038-01-19T03:14:07Z can never result in any additional certificates being
accepted on such a system.

Signed-off-by: Kyle J. McKay <[hidden email]>

For those using the libressl-2.5.4.tar.gz distribution, an equivalent
patch that updates the tarball files instead can be found here:


Without this patch (or an equivalent), libressl-portable is not a viable
alternative to OpenSSL on systems with a 32-bit time_t.

It rejects valid TLS connections to any site that contains a notAfter date
after 2038-01-19T03:14:07Z in any certificate in the chain.

Besides the special case date mentioned above, there are many root certificates
already in use today that have notAfter dates beyond 2038-01-19.

These patches have been tested with libressl-portable 2.5.4 on a system with
a 32-bit time_t.  With both of these patches the "nc -c" command successfully
connects to sites with certificates that include notAfter dates after 2038-01-19.

If either patch is omitted, "nc -c" fails to connect.

 src/lib/libcrypto/x509/x509_vfy.c | 3 ++-
 src/lib/libtls/tls_conninfo.c     | 8 ++++++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index d8c09a12..c59bd258 100644
--- a/src/lib/libcrypto/x509/x509_vfy.c
+++ b/src/lib/libcrypto/x509/x509_vfy.c
@@ -1882,7 +1882,8 @@ X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
  * a time_t. A time_t must be sane if you care about times after
  * Jan 19 2038.
- if ((time1 = timegm(&tm1)) == -1)
+ if (((time1 = timegm(&tm1)) == -1) &&
+    ((sizeof(time_t) != 4) || tm1.tm_year < 138))
  goto out;
  if (gmtime_r(&time2, &tm2) == NULL)
diff --git a/src/lib/libtls/tls_conninfo.c b/src/lib/libtls/tls_conninfo.c
index 5cdd0f77..a59b4ba2 100644
--- a/src/lib/libtls/tls_conninfo.c
+++ b/src/lib/libtls/tls_conninfo.c
@@ -142,8 +142,12 @@ tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore,
  goto err;
  if ((*notbefore = timegm(&before_tm)) == -1)
  goto err;
- if ((*notafter = timegm(&after_tm)) == -1)
- goto err;
+ if ((*notafter = timegm(&after_tm)) == -1) {
+ if (sizeof(time_t) == 4 && after_tm.tm_year >= 138)
+ *notafter = 2147483647;
+ else
+ goto err;
+ }
  return (0);