On Jul 5, 2017, at 22:30, Bob Beck wrote:
On Thu, May 18, 2017 at 7:31 AM, Kyle J. McKay <mack...@gmail.com> wrote:
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.


True enough.


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.

Correct

So, I'll ask - what is the platform you are using that needs this? OpenBSD does not, nor do most modern unix systems - So what platform are we doing this for?

I make a Git OS X installer for older (and current) Mac OS X (mackyle.github.io/git-osx-installer). I will, in the near future, be providing a LibreSSL installer too and it can be used to redirect the Git OS X Installer Git from the native SecureTransport to using LibreSSL instead (prior to OS X 10.8 only TLS 1.0 is available via SecureTransport). The installer must support 32-bit PPC and 32-bit Intel in order to be compatible with older machines. Those have a 32- bit time_t. I also see that my Raspberry Pi (it's not a "3") running Raspbian has a 32-bit time_t, so LibreSSL portable out-of-the-box would not work properly on it either (even on an RPi 3 I don't think 64-bit Raspbbian builds are officially supported yet).

I'm not asking it to be nasty, but to put it in a slightly different context "OMG, windows 98 does not support this, but if you add this code I can support windows 98". You and I both know what your answer would probably be for the person with Windows 98, which is "Here's a nickel kid, get a modern operating system".

Yes, well, I could also just build OpenSSL and use that instead, but I'd much rather use LibreSSL. Initially I thought I was just going to have to use OpenSSL, but then I poked around and worked out the patch. So I'm willing to maintain that patch separately for the LibreSSL installer since it's really such a tiny change. I'm just not comfortable shipping a 32-bit installer for LibreSSL that can't connect to current web sites, so I need to include the patch if I use LibreSSL rather than OpenSSL.

We ripped out support for a lot of moribund platforms for a reason. What platform are you using with 32 bit time where this is an issue? I'm not saying no, I'm saying "convince me this matters for anything relevant please", and I am open to being convinced.

It's really a portable-only change. The way the patch is written the compiler will omit the changes unless sizeof(time_t) == 4, but that does still leave that test in there making the code a bit less elegant.

Do you have some other suggestion for how I can ship a version of LibreSSL for older Mac OS X systems that works with those certificates?

Some folks are deliberately hanging on to their PPC Macs because they have legacy hardware/software that they need to use. Or they just can't afford to plunk down 1K+ for a new system, they'd rather use that money to eat. Those systems cannot be upgraded past Mac OS X 10.5. Even some Intel Macs with older graphic cards can't be upgraded past 10.7 (thank you very much Cupertino). Macs are not quite as cheap to replace as wintel so the kid will need more than a nickel. ;)

And the $5 Pi isn't 64-bit either.

My arguments are:

1) The compiler should produce exactly the same code before and after patch for 64-bit time_t systems 2) 32-bit systems are going to be around for many years still; 32-bit ARM platforms are everywhere 3) 32-bit systems typically have 32-bit time_t values (I'm not aware of anything in the standard preventing use of a 64-bit time_t on a 32- bit system but that doesn't seem to be happening, at least not yet) 4) 32-bit time_t has potentially still got over 20 years of life left in it 5) There are already pre-trusted root certificates with post 2038-01-19 expiration dates (I've seen 2041 for example), the number of these will continue to increase 6) The alternatives to LibreSSL are (a) OpenSSL [0.9.8zh, that's a joke, right? "zh"!] (b) BoringSSL [will get you caught up in goo*le specific stuff sooner or later] (c) GnuTLS [but it's GPL 3 and used to have horrible benchmarks in comparison to OpenSSL, but perhaps that's been addressed]. I'm sure there are more but those are obvious choices. If you need to stay away from GPL 3 (for whatever reason) then the only reasonable choice left for 32-bit time_t systems will be OpenSSL. I admit there hasn't been a 1.0.2zh [yet] but it's already at 1.0.2l. Then there's the OpenSSL 1.1.0 API changes. If folks adopt OpenSSL to get 32-bit time_t support they will likely be gone for good unless LibreSSL picks up the same API changes allowing them to migrate back after they no longer need 32-bit time_t support.

This is all, of course, a LibreSSL-portable argument and doesn't apply to the non-portable version, but there really aren't two versions of the core LibreSSL files, are there?

The LibreSSL installer I'm creating will have 3 patches and a kludge in it:

1) added OIDs for EV certificates -- this change has already been picked up and committed, so this is really actually a backport now since there hasn't yet been a LibreSSL portable release with it
2) the patch below
3) a netcat patch to provide "-T tlscompat" (to go with the pre- existing "-T tlsall" option) 4) a compile kludge to redirect all "poll(...)" function calls to a "pollcompat(...)" wrapper function that emulates poll() properly on Mac OS X

(1) will shortly become unnecessary, (4) I'll always be stuck with. I'm not exactly sure what the current status of (3) is. (2) I must have for the reasons above. So it's not that big a deal to always be stuck with (2) in addition to the others. They're all tiny changes except for (4) which just does something with compiler options and a tiny static library that provides the wrapper implementation but doesn't actually change any LibreSSL code at all.

Cheers,

Kyle


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);

---



Reply via email to