On 17.03.2019 17:22, Simo Sorce wrote:
On Sun, 2019-03-17 at 12:56 +0300, Yuriy M. Kaminskiy wrote:
On 14.03.2019 00:31, Simo Sorce wrote:
On Thu, 2019-03-14 at 00:25 +0300, Yuriy M. Kaminskiy wrote:
On 12.03.2019 15:02, Yuriy M. Kaminskiy wrote: And it is embedded in struct chacha_poly1305_ctx and poly1305_aes_ctx, which looks like part of public (and used) low-level ABI.
(nettle-meta.h interface would be safe wrt struct size changes, but so far everything I've looked at - including gnutls - was not using it :-()
FWIW, I wouldn't feel blocked by an ABI break in Nettle.
Breaking ABI in the library that is used in another libraries is always problematic.
Scenario: $app links to libgnutls.so.1 and libnettle.so.1 (and libgnutls.so.1 linked against libnettle.so.1; then libnettle.so.2 installed and libgnutls.so.1 rebuilt against new nettle; what will happen with $app?
(Especially since nettle does not use versioned symbols)
(I was wrong here, nettle uses versioned symbols, so nothing terminally bad happens in this scenario: both libraries loaded, but $app uses @VER1 symbols, while libgnutls @VER2 symbols).
So, you either bump libgnutls soname too (and you must rebuild all apps to take advantage of it) [also it triggers same problem with libraries that uses libgnutls], or you add Conflict/Breaks in libnettle2 (and you must rebuild all libraries and apps to be able to even install libnettle2).
No, if app is built against nettle all you need to do is bump nettle's so name and rebuild gnutls, the app will have to be rebuilt against the new nettle only as gnutls completely masks nettle behind it's apis and offers a stable ABI even when nettle ABI changes.
(And both renders new libnettle unusable for stable-backports.)
Yes, backports may be an issue, but nettle broke the ABI previously, and it offers no ABI guarntee.
When you are forced to break ABI, it is good point to think: can it be avoided, and how can this be prevented in the future?
This is not possible with Nettle as it uses explicit structures exported to the caller, to have a stable ABI nettle would need to change how it deals with context structures by allocating them on the heap and making them opaque. I do not see this happening.
Actually, nettle provides (almost) everything needed already (except for umac): in nettle-meta.h.
User can obtain correct context structure size, allocate it with malloc or alloca, and use it safely with matching set of functions.
It's just that nettle *also* provides another, fragile, interface, and don't encourage or force library users to use the safe one.
(What's annoying, "fragile" interface is not even much more efficient; it is just a tiny bit more easy to use - `struct chacha_poly1305 ctx;` vs `void *pctx = alloca(nettle_chacha_poly1305.context_size);`).
(poly1305 is not only algo that may require altering context structure for optimized implementation [e.g. bitsliced or vectorized aes]).
E.g. openssl made all structures opaque, and I believe it is correct long-term solution.
Openssl is a higher level library. We can discuss a wrapper library around nettle that offers a stable API/ABI and could be used by GnuTLS perhaps.
Openssl provides both higher-level (libssl) and low-level (libcrypto) primitives. It is even easier for low-level primitives (you don't need accessors for e.g. internals of md5 context struct; it is much more complex for tls session struct).
(Well, I've thought about a way, although not very nice: keep old version internally, add separate {chacha,aes}_poly1305_encrypt_v2, #define $foo $foo_v2 in headers; you'll need to rebuild all directly dependent libraries and apps to take advantage of new implementation, but not necessarily whole system; also it is not 146% safe [lib$a built against old version, lib$b built against new version, lib$a allocates struct chacha20_poly13_ctx and passes pointer to lib$b; libb calls $foo_v2, BOOM], but I doubt anyone uses libnettle this way in practice).
Yes, as you described this method is broken, you would have to have explicit different APIs or introduce symbol versioning.
Symbol versioning won't help in this breakage scenario. At all.
lib$a allocate structure for use foo@VER1, passes it to lib$b, lib$b calls foo@VER2, BOOM.
Only way around this issue - use nettle-meta.h interface and pass matching struct nettle_{cipher,aead,...}. Then lib$b can call matching function set, regardless of which version of libnettle it was linked to.