openssl/openssl
Migrating to OpenSSL 3.x
OpenSSL 3.0 (Sep 2021) was the biggest API break since 0.9.x. Most applications that worked with 1.1.1 still build and run, but behind the scenes a lot has changed. This page summarises what to expect.
The big idea
Pre-3.0 OpenSSL had two pluggability points:
Engines for hardware-backed asymmetric and a handful of symmetric ops.
A static set of in-tree algorithms compiled into
libcrypto.3.0 reorganised crypto around providers (providers). Every algorithm now lives in a provider;
libcryptois mostly a dispatcher and a set of common helpers.
That has three big consequences:
- FIPS is finally a separate, in-tree, validated module rather than a fork of OpenSSL.
- Library contexts (
OSSL_LIB_CTX) make it possible for two parts of the same process to use independent sets of providers / algorithms / DRBG seeds. - Algorithm fetching (
EVP_*_fetch) replaces the macro shorthand (EVP_sha256()) and gives you property-based selection.
The migration guide upstream is doc/man7/migration_guide.pod and the related man pages — it is comprehensive and worth a thorough read before upgrading anything that calls into OpenSSL.
What "just works"
- TLS clients and servers using
SSL_*/SSL_CTX_*. - High-level CMS / PKCS#7 / PKCS#12 callers.
- Programs that load PEM with
PEM_read_bio_PrivateKey. - Most callers of
EVP_*(digest, cipher, sign, verify, derive, encrypt, decrypt). BIO-using code.- Most error-handling code (the codes still mean what they used to).
You may need to:
- Load the
legacyprovider explicitly if you use MD2/4, MDC2, RIPEMD-160, RC2/4/5, IDEA, single-DES, Blowfish, CAST5, SEED, or PBKDF1. - Fix calls that depended on Engines for crypto. Engines still load (
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_*, NULL)works) but the recommended path is providers.
What's deprecated
The deprecated APIs in 3.0 / 3.1 / 3.2 / 3.3 / 3.4 / 3.5 are listed in doc/man7/openssl_user_macros.pod. Compile with -DOPENSSL_API_COMPAT=30000 to make them errors. The big categories:
Per-algorithm structs and functions:
RSA *,DSA *,DH *,EC_KEY *,EVP_PKEY_assign_RSA,i2d_RSAPrivateKey,RSA_generate_key, etc. Replacement:EVP_PKEYplusEVP_PKEY_CTXplusOSSL_PARAM. Seecrypto/evp/p_lib.cand the evp page.EVP_PKEY_CTX_ctrlin favour ofEVP_PKEY_CTX_set_params. Why: the new path is provider-friendly. The legacy ctrl path goes through a 111 KB translator (crypto/evp/ctrl_params_translate.c) and supports the same operations but is closed to extension.Engines in favour of providers for crypto. (Engines remain for TLS hardware acceleration via async, etc.)
OPENSSL_configin favour of automatic init plus per-libctx config viaopenssl.cnf.MD2 / MD4 / MDC2 / RC2 / RC4 / RC5 / Blowfish / CAST5 / IDEA / SEED / RIPEMD-160 / Whirlpool: not removed, but moved to the legacy provider.
Macro shorthands (
EVP_sha256(),EVP_aes_256_gcm()): not deprecated, but discouraged because they implicitly use the default libctx and default property. New code shouldEVP_*_fetch(libctx, "name", "props")and free the result.
What's gone
- Some pre-3.0 engine API internals that were never declared public.
- Pre-1.0 export-grade ciphers were removed in earlier releases; the empty hooks were cleaned up in 3.0.
Property-based algorithm selection
The big new idea:
EVP_set_default_properties(libctx, "?fips=yes");
EVP_MD *md = EVP_MD_fetch(libctx, "SHA2-256", NULL); /* picks fips=yes if available */You can compose: provider=fips,fips=yes (FIPS-only), provider!=legacy (forbid legacy provider), provider=oqsprovider (prefer a third-party provider).
Library contexts
Code that wanted to mix FIPS and non-FIPS crypto in the same process used to require multiple-process shenanigans. In 3.x:
OSSL_LIB_CTX *fipsctx = OSSL_LIB_CTX_new();
OSSL_PROVIDER_load(fipsctx, "fips");
OSSL_PROVIDER_load(fipsctx, "base");
EVP_set_default_properties(fipsctx, "fips=yes");
OSSL_LIB_CTX *appctx = OSSL_LIB_CTX_new();
OSSL_PROVIDER_load(appctx, "default");
/* hash with FIPS */
EVP_MD *md = EVP_MD_fetch(fipsctx, "SHA2-256", NULL);
/* sign with the default */
EVP_SIGNATURE *sig = EVP_SIGNATURE_fetch(appctx, "RSA-PSS", NULL);The "default" libctx (NULL everywhere) still exists; new code should pass an explicit libctx.
Configuration changes
openssl.cnf gained a [providers] section:
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
default = default_sect
fips = fips_sect
[default_sect]
activate = 1
[fips_sect]
activate = 1Plus an include directive: .include /etc/ssl/fipsmodule.cnf (the file generated by openssl fipsinstall).
Common upgrade gotchas
SSL_CTX_load_verify_locationsreturning 0: the path may be empty or contain only DER files; 3.x is stricter about validating that something usable was loaded. UseSSL_CTX_set_default_verify_pathsplusSSL_CTX_load_verify_dir.- PKCS#12 files written with an old default: 3.0 increased PBKDF2 iterations and shifted to AES-256 by default. Old readers may fail to import. Use
PKCS12_create_exfor legacy compat. - OCSP
OCSP_basic_verifyflags: tightened defaults; you may needOCSP_NOCHECKSor to ensure the responder cert is in the chain. EVP_PKEY_CTX_ctrl_strwith custom keywords now has anOSSL_PARAM-translation path; old custom keywords may not be recognised. UseEVP_PKEY_CTX_set_paramsexplicitly.- TLS protocol minimum: 3.0 raised it to TLS 1.2 by default. Use
SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION)to explicitly accept older.
Multiple-version coexistence
libcrypto.so.3 and libcrypto.so.1.1 can both be installed on the same machine — the SONAMEs are different and they don't conflict. Linking and loading order matters in dlopen scenarios; the OpenSSL symbol versioning ensures they don't trample each other if you have to mix them at runtime.
More to read
doc/man7/migration_guide.pod— the canonical guide.doc/man7/ossl-guide-migration.pod— narrative version.doc/man7/openssl_user_macros.pod— the deprecation-control macro reference.- The 3.0, 3.1, 3.2, 3.3, 3.4, 3.5 release announcements at
https://openssl-library.org/news/openssl-3.X-notes/.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.