Open-Source Wikis

/

OpenSSL

/

Background

/

Migrating to OpenSSL 3.x

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; libcrypto is mostly a dispatcher and a set of common helpers.

That has three big consequences:

  1. FIPS is finally a separate, in-tree, validated module rather than a fork of OpenSSL.
  2. Library contexts (OSSL_LIB_CTX) make it possible for two parts of the same process to use independent sets of providers / algorithms / DRBG seeds.
  3. 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 legacy provider 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_PKEY plus EVP_PKEY_CTX plus OSSL_PARAM. See crypto/evp/p_lib.c and the evp page.

  • EVP_PKEY_CTX_ctrl in favour of EVP_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_config in favour of automatic init plus per-libctx config via openssl.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 should EVP_*_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 = 1

Plus an include directive: .include /etc/ssl/fipsmodule.cnf (the file generated by openssl fipsinstall).

Common upgrade gotchas

  • SSL_CTX_load_verify_locations returning 0: the path may be empty or contain only DER files; 3.x is stricter about validating that something usable was loaded. Use SSL_CTX_set_default_verify_paths plus SSL_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_ex for legacy compat.
  • OCSP OCSP_basic_verify flags: tightened defaults; you may need OCSP_NOCHECKS or to ensure the responder cert is in the chain.
  • EVP_PKEY_CTX_ctrl_str with custom keywords now has an OSSL_PARAM-translation path; old custom keywords may not be recognised. Use EVP_PKEY_CTX_set_params explicitly.
  • 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.

Migrating to OpenSSL 3.x – OpenSSL wiki | Factory