Skip to content

LibreSSL is misidentified as OpenSSL 0.9.0, disabling functionality LibreSSL supports #9

Description

@SeanTAllen

LibreSSL users currently build with -Dopenssl_0.9.0, which forces LibreSSL through a code path designed for ancient OpenSSL. This silently disables functionality that LibreSSL actually supports (ALPN, modern init, modern EVP API) and runs unnecessary legacy code (the CRYPTO_set_locking_callback threading ceremony, which is a no-op in LibreSSL).

LibreSSL's actual API compatibility

LibreSSL's API is a hybrid — mostly OpenSSL 1.1.x compatible, with a few 0.9.x/1.0.x holdovers. It does not fit cleanly into any of the three existing ifdef paths (openssl_0.9.0, openssl_1.1.x, openssl_3.0.x).

Functions LibreSSL has (1.1.x compatible)

Function Status
TLS_method() Available (since LibreSSL 2.2.2)
OPENSSL_init_ssl() Available (with pthread_once semantics)
EVP_MD_CTX_new() / EVP_MD_CTX_free() Available (old names also still work)
SSL_CTX_set_alpn_select_cb() Available
SSL_CTX_set_alpn_protos() Available
SSL_get0_alpn_selected() Available

Functions LibreSSL does NOT have

Function LibreSSL alternative Notes
OPENSSL_sk_pop() / OPENSSL_sk_free() sk_pop() / sk_free() Old naming convention only
SSL_get1_peer_certificate() SSL_get_peer_certificate() 3.0.x rename not adopted
SSL_has_pending() Not available SSL_pending() exists but SSL_has_pending() (added in OpenSSL 1.1.0) is not
SSL_CTX_set_options() as function Macro calling SSL_CTX_ctrl() OpenSSL 1.1.x made this a real function; LibreSSL kept the macro

Threading

CRYPTO_set_locking_callback() exists in LibreSSL for API compatibility but is a no-op. LibreSSL handles threading internally using pthread mutexes. The current 0.9.0 code path calls @ponyint_ssl_multithreading and @CRYPTO_set_locking_callback unnecessarily.

Impact of the current misidentification

Because LibreSSL is forced through the openssl_0.9.0 path:

  1. ALPN is disabled — the 0.9.0 path returns false from alpn_set_resolver() and alpn_set_client_protocols(), even though LibreSSL fully supports ALPN.
  2. Legacy init ceremony runsSSL_library_init(), SSL_load_error_strings(), CRYPTO_num_locks(), @ponyint_ssl_multithreading(), and CRYPTO_set_locking_callback() all run. LibreSSL doesn't need any of this; OPENSSL_init_ssl() works fine.
  3. Legacy API names usedSSLv23_method(), EVP_MD_CTX_create()/EVP_MD_CTX_destroy(), SSL_CTX_ctrl() for options. LibreSSL supports the modern equivalents.
  4. SSL_has_pending() not called — this one is actually correct since LibreSSL doesn't have it, but for the wrong reason (the 0.9.0 path skips it because 0.9.0 doesn't have it, not because LibreSSL doesn't).

Proposed fix

Add a new define (-Dlibressl or similar) that gives LibreSSL its own code path. This path should be based on the openssl_1.1.x path with targeted overrides for the four differences:

  1. Use sk_pop()/sk_free() instead of OPENSSL_sk_pop()/OPENSSL_sk_free()
  2. Use SSL_get_peer_certificate() instead of SSL_get1_peer_certificate()
  3. Handle SSL_CTX_set_options() being a macro (this may already work transparently)
  4. Skip SSL_has_pending() (use the SSL_pending() fallback)

Once LibreSSL has its own path, the actual OpenSSL 0.9.0 code path can be removed — OpenSSL 0.9.x has been EOL since 2015.

Downstream projects that have Makefiles with ssl= options (e.g., lori) will need to add the new define as a build option so users can build against LibreSSL properly.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions