OpenSSL Communities

Complexity of compile-time disableables makes it hard to contribute code to OpenSSL

TM Tomas Mraz Tue 25 Nov 2025 5:55PM Public Seen by 116

This was brought up by @Clemens Lang in https://github.com/openssl/openssl/pull/29192/files#r2550640630

I'm citing him here:

Are the no-dh and no-ec config options really still useful? They make writing tests so cumbersome. We don't have a no-pqc option, either, from what I can see. Maybe we should move off the compile-time configurability and more towards runtime configurability to improve both readability and easy of test writing?

IIRC the original patent concerns around no-ec are no longer a concern.

Quite a few people at the conference complained that it was hard to contribute (see, for example, the talk by the Python cryptography people), and this is one of the things where the contribution experience is just bad. Most of the other things I can test locally, but these special configurations always feel like a wild goose chase. Add that to the test system being an undocumented mess of copy/pasted code with huge files, nearly unreadable debug output in case tests fail, and a few local specialties that would be much better served by more standard tools (like the code style perl script, but at least that one's going to be replaced by clang-format soon, I hear), and it can quickly get frustrating to get the CI into a green state.

NT

Nicola Tuveri Tue 25 Nov 2025 7:20PM

@Peter Gutmann just a note that default upstream options and distro default options are not necessarily in sync. The optimized ecp and ecz implementations for example are on in most major distros for the mainstream hardware platforms, but they are not on by default in upstream OpenSSL.

Additionally some distros (used to?) apply custom linker scripts to “curate” the list of global symbols resulting in unfortunate ABI incompatibilities (I experienced this in Ubuntu in 1.1.1 times, and funnily enough the function was still declared in the public headers even though it was not available for linking).

The complexity problem of build time options is real when building testing harnesses to do dynamic analysis of internal OpenSSL code paths as not all possible combinations of build time options are testable by just looking at header defines. In the past I have had to maintain complex configure scripts to test with dedicated config tests what features were available and which ones weren’t in a particular build.

PG

Peter Gutmann Tue 25 Nov 2025 7:35PM

That sounds more like a test-case explosion problem though (which I have too) than a makes-code-contribution difficult... for the last option, would modifying `openssl version -a` to also display the config options fix that? It currently displays the compile options but not the build options.

Or add a new option to `openssl version` to display config options in machine-readable format.

CL

Clemens Lang Tue 25 Nov 2025 7:58PM

@Peter Gutmann The test case explosion problem is also what makes contribution harder. In the pull request that sparked this discussion, the one-line code fix was essentially done and finished immediately, and I needed 6 more iterations to get the test passing with the `no-ec` and `no-dh` options, skipped where it would fail (granted, that one caused by a genuine bug in the code on 32-bit systems), and matching the code formatting checker perl script.

It would have been significantly easier to contribute without the `no-ec` and `no-dh` options, since my test would not have needed as many iterations. That left me wondering, how many users really do still need `no-ec` and `no-dh`?

MB

Michael Baentsch Wed 26 Nov 2025 7:44AM

@Clemens Lang While I have fallen into these "not-set-by-default" (CI) build option "traps" myself, requiring iterating on my PRs, I have always seen these tests/build options as a benefit to my work, making me think how my code behaves under circumstances/configurations that may have a value to someone: OpenSSL is a system used under so many different circumstances, by so many people that a likely correct answer to your question above is "enough to support them". As a "PQ aficionado" I can also tell you that I wouldn't mind an option to build OpenSSL "no-ec no-rsa" (not sure when the PQ stuff moves from hype to reality, so can't tell you when this becomes necessary, but the need for disabling ec just might not only be in the past... :-)

CL

Clemens Lang Wed 26 Nov 2025 10:53AM

@Michael Baentsch I'm not convinced we need to disable them at compile time for this, though. A way to disable non-PQ algorithms at runtime (potentially with a mechanism that's closer to a system policy and not simple to override for applications) would in my eyes be a better approach to do this.

MB

Michael Baentsch Thu 27 Nov 2025 6:53AM

@Clemens Lang I beg to differ: I am convinced of this: If there were no way to compile-time disable features, it's a guarantee for a configuration error to cause major security incidents by triggering code paths that wouldn't have been there if they'd been compiled out at build time. Again, please consider the same "breadth of deployment" argument: OpenSSL is used in just too many places, administered by too many people with too many different (security) education backgrounds (or too little time at their hands to read all docs) that giving all of them a gun to shoot them in their feet (by setting a configuration option activating code that should not be activated) is a surefire way (pardon the pun) to have many very sore feet indeed.

PD

Paul Dale Thu 27 Nov 2025 8:59PM

Agreed, Hyrum's Law applies.

MR

Michael Richardson Tue 25 Nov 2025 8:02PM


Tomas Mraz (via OpenSSL Communities) wrote:

I'm citing him here:

Are the no-dh and no-ec config options really still useful? They

make writing tests so cumbersome. We don't have a no-pqc option,

Do no-dh and no-ec remove the DH and EC code from the default provider, or

does it remove all DH/EC APIs from OpenSSL? I can see good reasons to omit

things in many constrained systems that want to use some other provider for

all operations.

CL

Clemens Lang Tue 25 Nov 2025 8:09PM

@Michael Richardson They actually remove the EC APIs. Use `grep ':EC$' util/libcrypto.num` for a list of functions that will not be available when compiling with `no-ec`.

TM

Tomas Mraz Wed 26 Nov 2025 1:57PM

@Michael Richardson Yes, as Clemens wrote above. All the implementation of DH and EC (including EdDSA and X25519, X448 key exchanges) will be excluded from the build so neither the low level interfaces will be present nor the implementation of these algorithms in the default and fips providers.

PD

Paul Dale Tue 25 Nov 2025 8:49PM

There are a lot of items in the disablables list, some reduction seems like it would be worthwhile.

One could argue for the introduction of a no-rsa option. With the move to PQ physics experiments, the ability to remove RSA becomes useful.

We can do run-time removal of algorithms if we break the default provider into lots of smaller pieces. This was mooted as a possibility during the 3.0 development cycle and having support for doing so should meet the requirements of reducing size and removing unnecessary functionality. It will introduce other problems but nothing is free in life. Before anyone comments: I'm not suggesting the removal of the default provider, rather the addition of other providers.

MB

Michael Baentsch Wed 26 Nov 2025 7:33AM

@Paul Dale Splitting default provider into algorithm-specific providers (or at least into providers aligned with build options, e.g., an EC provider) that each can be en/disabled (potentially also at build time, certainly at run-time) seems like a very good proposal and very much in line with the original concept of providers: This serves both goals discussed above: Enable run-time activation of code/algorithms while also supporting build-time disablement of code optimizing for size (and maybe some lawyer-dependent legal compliance :)

TM

Tomas Mraz Wed 26 Nov 2025 1:59PM

@Paul Dale Hmm, except the default provider is built-in the libcrypto, so I assume at least in the shared build we would have to be first able to not have the default provider built-in and to really reduce the size of the shared libcrypto also the low-level interfaces to these algorithms would have to be removed. This sounds like a very significant project and change and it would certainly require a major version bump.

PD

Paul Dale Wed 26 Nov 2025 7:51PM

Isn't it fortunate that there is a major version change soon 🙂

MB

Michael Baentsch Thu 27 Nov 2025 7:01AM

@Tomas Mraz Completely agree, this wouldn't be a trivial thing but wouldn't it be sensible? I personally think it's not a good design practice that build switches change ABIs; changing functionality of APIs, yes - completely changing interfaces, doesn't seem desirable. Thanks to @Clemens Lang for pointing that out explicitly: It never registered with me before.

NT

Nicola Tuveri Thu 27 Nov 2025 7:17AM

@Michael Baentsch there is a counter argument that the applications impacted by these ABI changes are using old and deprecated APIs: looking at ancient code bases, most of the time, even if the function signature had a return value, the fact that in practice it couldn’t fail in the normal conditions meant they did not check at all return values.

For most of these applications a build time failure is way better than a run time failure that was not handled and tested.

I do think the argument of ABI breakage changing build time options like no-ex or no-dh is quite moot today: at some point the functions that are now deprecated can be dropped, those that are discouraged will be eventually deprecated and dropped. At that point the ABI breakage problem disappears, in a (painfully slow) process familiar to most developers.

Changing the behavior of an existing API is something that the project promises to never do, with way stronger guarantees than on ABI stability (which are mostly limited to core/provider for now). So the proposed change of making no-ec affect function behavior rather than remove the symbol is not possible either: at best we could add `EC_foo_bar_ex` alongside the deprecated `EC_foo_bar`. The new one could have behavior changes depending on the build time flag, but the old one cannot. So for existing applications this solves nothing: they were written against the API we cannot change and did not care yet to upgrade to the EVP API even if the EC functions have been deprecated and could go away soon.

In this context I believe it is better to wait the natural disappearance of the ABI-breaking-on-build-flags functions.

I am not against a review of existing build time flags, but the ABI issue is not really a motivating factor in this. All new provider-aware functions handle at runtime the failure of fetching specific algorithms already.

MB

Michael Baentsch Thu 27 Nov 2025 7:40AM

@Nicola Tuveri OK regarding ABI argument. Your last statement triggers the question, though, what effort already is in place to (eventually :) eliminate non-provider-aware functions? Are they all going to be at least deprecated in 4.0? Different discussion than this, surely, but one arguably worth having if we want to influence the speed of change in this area, no?

NT

Nicola Tuveri Thu 27 Nov 2025 9:19AM

@Michael Baentsch There are constant discussions :)
It's a chicken and egg problem:
- our users don't want us to deprecate functions because many compile with `-Wall` so deprecation warnings trigger build failures. (I usually answer that if they do not care about deprecations they could add `-Wno-deprecated` but I am usually downvoted on those discussions).
- for the reason above the project is weary of deprecating functions that are widely used, so instead we usually end up with adding some note in the documentation discouraging functions and recommending alternatives. (Also the reason above has been used sometime as an argument to add deprecations only in major releases)
- ideally at some point we are able to detect that families of "discouraged" functions have such low adoption that we are ok with the "deprecation" step. (My personal opinion is that without deprecations adoption will not dwindle especially for codebases designed to use aws-lc/boring/libre/openssl1.1.1/openssl3 interchangeably by using the non-provider-aware functions that are the common denominator across the forks)
- only after many years from deprecation, and in occasion of a planned major release, we can finally have a discussion about finally removing the long-deprecated functions.

The progress around removing the legacy ENGINE code and APIs is a good example of this: they have been deprecated since OpenSSL 3.0 (September 2021), and as a project we are still struggling to carve that out in time for 4.0 (April 2026).
And the ENGINE functions actually have the advantage of low adoption because they were carved out from all the forks since Heartbleed (2014!!!!) started all the forks!

I think if we want to make it possible to deprecate and remove legacy stuff more quickly than 12-years cycles, this platform should collect way more feedback in that direction to convince the project leadership to reevaluate the balance between support for legacy codebases and removal of legacy codepaths.

MB

Michael Baentsch Thu 27 Nov 2025 11:40AM

@Nicola Tuveri Very sensible again and completely agreed. That said, isn't a goal of these discussions (and the B|TACs) exactly to influence the project leadership? What about voting about concrete proposals (either to concretely deprecate certain options or more generically about a goal for a --quicker-- deprecation strategy)? Maybe the voting turns out that aws-ls/boring/etc compatibility is more important than deprecating stuff -- or not.

NT

Nicola Tuveri Thu 27 Nov 2025 11:54AM

@Michael Baentsch yes, absolutely!

For BAC/TAC to recommend changes though a representative needs feedback from their community that something needs to be discussed and changed!

Talking as representative of Academics, I can say that this matter (or tightly related ones) has been brought to me in private conversations, and I followed up with the invite to please post here on Loomio so we can gauge interest of other community members and properly discuss courses of action at the BAC/TAC.

Unfortunately so far I wasn’t persuasive enough to convince the academics members to participate more actively here, while other communities do have more engagement in the platform and seem definitely more interested in cross-fork-compatibility and legacy support than in “cleanup”.

Definitely a failure on my part in enticing academics to participate more, and hopefully with the new rounds of elections someone more effective than me can take this role.

But for now, beyond my strong interest and opinions, I can only bring anecdotal single digit numbers to support recommendations for change on the matters of deprecation, code cleanup, abi-compatibility, test complexity, splitting default provider in many separate providers, etc. so I am not really in a strong position to advocate for change in BAC/TAC other than raising awareness based on the little feedback I could gather face-to-face and my own experiences as an academic.

Item removed

RL

Richard Levitte (individual) Fri 28 Nov 2025 9:22AM

@tomas , but hmmm, the default provider algorithms are fetchable (or not) the same way as for any other provider. Probing for algorithms should be exactly the same regardless.

So apart from size, I don't quite understand how disablables affects applications (of course, under the conditions that they don't make assumptions base on macros, and do probe).

TM

Tomas Mraz Fri 28 Nov 2025 10:39AM

@Richard Levitte (individual) I am explicitly talking about size. And for other use-cases where size is not a problem but possible use of algorithms that must not be used is a problem, the default provider auto-activation would have to be disabled.

RL

Richard Levitte (individual) Fri 28 Nov 2025 3:42PM

@tomas, yup, ok.

DJL

Dimitri John Ledkov (Chainguard) Wed 26 Nov 2025 11:08PM

I really wish to have stable ABI irrespecive of compile time options - specifically imho no-dh compile time option should still provide the DH symbols that allow existing binaries exec and bind symbols (bind-now) and such symbols can be stubs that always return error. The thinking is that binaries can handle errors from those symbols, or for example the usage is optional / runtime dependent (for example if a given application happens at runtime to load only RSA keys and uses RSA KEM it might never actually call any of the EC symbols). Doing these stub symbols would help a lot, including doing a no-abi break transition of removing features.

For example if openssl 4 can be compiled wit stub-symbols for the removed engine API, it might be possible to make openssl 4 provider libcrypto.so.3 / libssl.so.3 ABI, despite the removal of working engine API. And similar.

NT

Nicola Tuveri Thu 27 Nov 2025 7:30AM

@Dimitri John Ledkov (Chainguard) I disagree.

The thinking is that binaries can handle errors from those symbols

If the applications were not written to handle the new failure case (I.e., function is a stub because of build time options), because since forever you either had or not had the symbol, but the function (if present) had a very specific set of failure conditions, an undetected/unexpected/ignored runtime failure is more dangerous (how many of us has seen the “if we reached here we can assume everything is fine” comments?) and costly (editing the codebase to handle the new failure path can force bigger refactors).

Additionally it hides away from the developers which parts of their codebase need attention: if you have a build time compilation error you get very clear diagnostics about something being wrong in a specific place (or more than one 😆). If you have stub functions, you have to scour changelogs and docs changes to discern which functions are affected, grep through all your codebase looking for those functions and make sure the new failure case is gracefully handled.

DJL

Dimitri John Ledkov (Chainguard) Wed 26 Nov 2025 11:10PM

About testing - i really dislike all the testing options, but most of them are quite easy to automatically gracefull handled algorithm not present. But it is too hard. At chainguard for some of our openssl builds - we run tests and ignore all failures, as we could not have been bothered to make all legacy interop tests to pass due to removed functionality.

So the testing complexity bugs is real, especially as it blocks removing insecure, legacy, deprecated functionality.

MB

Michael Baentsch Thu 27 Nov 2025 7:13AM

@Dimitri John Ledkov (Chainguard) I tend to agree: There's just too many options -- and you exemplify this when ignoring failures triggered by them. But ignoring all failures sounds like a pretty bad idea. So this really seems to call for an effort to streamline the options -- at the very least splitting them into "arcane" (build failure on some setting OK) and "sensible" (build failure on any setting inacceptable): Beyond documenting this (if not culling the arcane ones outright) this should lead to the arcane ones not being subject to CI testing any more: This would address the original concern of @Clemens Lang to some degree without losing the benefits of being able to do truly sensitive (and sensible) config changes.

CL

Clemens Lang Thu 27 Nov 2025 12:44PM

@Michael Baentsch Yeah, that outlines exactly the result I wanted as outcome from this discussion.

RL

Richard Levitte (individual) Thu 27 Nov 2025 9:43AM

This question is actually two question that can be treated separately:

  1. Building, where people have all sorts of reasons (reasonable or not, that's not actually interesting) to want to disable select parts of the library.
  2. Testing, where it's interesting to know what algorithms are available in runtime.

A middle ground is given with pluggable algorithms; in OpenSSL, that was meant to be provided by engines, now largely replaced by providers.

Using plugins should solve the application ABI issue, i.e. applications should not need to rely on algorithm-specific symbols being present at build time, but would have to depend on what algorithms can be fetched (in provider parlance).
This in turn would mean that disabling options like no-dh, no-ec and similar shouldn't affect the application facing ABI, but it would affect what's fetchable from OpenSSL's providers.

Testing is, like I said, separate. We have a lot of tests that depend on configuration options, but does it have to be that way? I'd say that no, it doesn't. Among others, test/evp_test.c is a prime example of this, as it will dynamically check if an algorithm it's about to run a test stanza on is actually available, and if not, that stanza is simply skipped.

So perhaps part of the answer is to stop using things like disabled("ec") in our test scripts, and replace that with something like, oh I dunno, available_signature("ecdsa-sha256"), available_keymgmt("ec"), something like that, possibly powered by some simple app that checks for availability given a set of providers.

RL

Richard Levitte (individual) Thu 27 Nov 2025 9:44AM

(incidently, and this is a tangential idea, I've wondered for a long time if the whole test suite couldn't be made into a separate project [read: repo], that would test things only given a path to the openssl app and libraries, along with a set of providers to use for those tests)

PD

Paul Dale Thu 27 Nov 2025 9:56AM

Detecting algorithm presence like this is a good idea. It will be a boon for cross version testing in addition to testing disable options.