[gnutls-devel] GnuTLS | GNUTLS 3.8.0 public API has broken ABI compatibility on 32-bit platforms with glibc >= 2.34 (#1466)

Read-only notification of GnuTLS library development activities gnutls-devel at lists.gnutls.org
Thu Mar 2 10:22:56 CET 2023



Daniel P_ Berrangé created an issue: https://gitlab.com/gnutls/gnutls/-/issues/1466



With the 3.8.0 release of GNUTLS, the public API has broken ABI compatibility on 32-bit platforms which have glibc >= 2.34 present.

The issue affects any GNUTLS API that uses the `time_t` type.  We detected this because it broken all the libvirt and QEMU unit tests which generate certificates, with errors about the certificate not being active yet.

A condensed snippet from the QEMU tests to reproduce the problem is as follows:

```
$ cat demo.c

#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>

# define PRIVATE_KEY \
    "-----BEGIN RSA PRIVATE KEY-----\n" \
    "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\n" \
    "-----END RSA PRIVATE KEY-----\n"

static gnutls_x509_privkey_t load_key(void)
{
    gnutls_x509_privkey_t key;
    const gnutls_datum_t data = { (unsigned char *)PRIVATE_KEY,
                                  strlen(PRIVATE_KEY) };
    assert(gnutls_x509_privkey_init(&key) >= 0);
    assert(gnutls_x509_privkey_import(key, &data,
                                      GNUTLS_X509_FMT_PEM) >= 0);
    return key;
}

int main(int argc, char **argv) {
    gnutls_x509_crt_t crt;
    int err;
    static char buffer[1024 * 1024];
    size_t size = sizeof(buffer);
    char serial[5] = { 1, 2, 3, 4, 0 };
    gnutls_datum_t der;
    time_t start = time(NULL);
    time_t expire = time(NULL) + (60 * 60 * 24);
    gnutls_x509_privkey_t privkey = load_key();

    assert(gnutls_x509_crt_init(&crt) >= 0);
    assert(gnutls_x509_crt_set_key(crt, privkey) >= 0);
    assert(gnutls_x509_crt_set_version(crt, 3) >= 0);
    assert(gnutls_x509_crt_set_serial(crt, serial, 5) >= 0);
    assert(gnutls_x509_crt_set_activation_time(crt, start) >= 0);
    assert(gnutls_x509_crt_set_expiration_time(crt, expire) >= 0);
    assert(gnutls_x509_crt_sign2(crt, crt, privkey,
                                 GNUTLS_DIG_SHA256, 0) >= 0);
    assert(gnutls_x509_crt_export(
               crt, GNUTLS_X509_FMT_PEM, buffer, &size) >= 0);

    assert(start == gnutls_x509_crt_get_activation_time(crt));
    printf("%s\n", buffer);

    return 0;
}
```

Compile this on a 32-bit host, (or 64-bit host passing -m32) and then query the certificate contents:

```
$ gcc  -g -lgnutls -m32 -o demo demo.c
$ ./demo  | certtool  -i | grep Not
		Not Before: Sat Sep 05 17:30:22 UTC 2703
		Not After: Sun Sep 06 17:30:22 UTC 2703
```

Notice that instead of having a validity/expiry date of today + 1 day, it has a date ~700 years into the future.

This did not happen with gnutls 3.7.8 / 3.7.9

I ran a git bisect in gnutls and narrowed it down to this change

```
commit 61fa36ca4ea84ca3bc42918690151eec8dfc1148
Author: Daiki Ueno <ueno at gnu.org>
Date:   Sat Jan 8 18:14:16 2022 +0100

    gnulib: update git submodule
    
    Signed-off-by: Daiki Ueno <ueno at gnu.org>
```

The problem arose because GNULIB has changed the 'largefile' module so that it probes for the C library exposing _TIME_BITS=64, and if available will set that define. This results in time_t changing from 32-bit in size to 64-bit when gnutls is built.

Meanwhile essentially no application that uses GNUTLS will have _TIME_BITS=64 set, and thus they will all be passing/receiving time with a 32-bit time_t.

This means that any application interacting with GNUTLS APIs that involve time_t will be broken on 32-bit hosts with glibc >= 2.34 (when _TIME_BITS=64 arrived).

GNULIB did provide a '--disable-year2038' flag for configure which can be used at build time to disable 64-bit time_t. Essentially everyone who builds GNUTLS today needs to be sure to pass --disable-year2038 to avoid the silent ABI change.

See also this thread https://sourceware.org/pipermail/libc-alpha/2023-March/146002.html

Both Gentoo and Fedora have hit this ABI incompatibility, and any other distro which still has 32-bit builds will do so too.

I'm not sure what the best course of action for GNUTLS is right now. IMHO, ideally GNULIB should not have forced 64-bit time_t on every application using 'largefile', it should have remained strictly opt-in, as GLibC had made it. I don't see a way for GNUTLS to get away from the 'largefile' change because 'largefile' is an important GNULIB module that every app needs. 

The best I can see is to prominently document the importance of setting '--disable-year2038' when building GNUTLS, unless GNULIB wants to revert their change to 'largefile' and make it opt-in.

-- 
Reply to this email directly or view it on GitLab: https://gitlab.com/gnutls/gnutls/-/issues/1466
You're receiving this email because of your account on gitlab.com.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.gnupg.org/pipermail/gnutls-devel/attachments/20230302/363f2498/attachment-0001.html>


More information about the Gnutls-devel mailing list