RFC 5280 section 4.1.2.5 states: To indicate that a certificate has no well-defined expiration date, the notAfter SHOULD be assigned the GeneralizedTime value of 99991231235959Z.
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 <mack...@gmail.com> --- For those using the libressl-2.5.4.tar.gz distribution, an equivalent patch that updates the tarball files instead can be found here: https://gist.github.com/7d4d59bbae9e4d18444b86aa79d6f350 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); ---