[PATCH] allow notAfter after 2038 with 32-bit time_t
RFC 5280 section 184.108.40.206 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
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.
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.
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index d8c09a12..c59bd258 100644
@@ -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))