This guide details the steps required to migrate from Mbed TLS version 2.x to Mbed TLS version 3.0 or greater. Unlike normal releases, Mbed TLS 3.0 breaks compatibility with previous versions, so users (and alt implementors) might need to change their own code in order to make it work with Mbed TLS 3.0.
Here‘s the list of breaking changes; each entry should help you answer these two questions: (1) am I affected? (2) if yes, what’s my migration path?
The changes are detailed below, and include:
config.h
was split into build_info.h
and mbedtls_config.h
.
#include <mbedtls/build_info.h>
. Don‘t include mbedtls/config.h
and don’t refer to MBEDTLS_CONFIG_FILE
.mbedtls_config.h
, or edit MBEDTLS_CONFIG_FILE
as before.include/mbedtls/version.h
, this has moved to include/mbedtls/build_info.h
. From C code, both headers now define the MBEDTLS_VERSION_xxx
macros.Also, if you have a custom configuration file:
check_config.h
or config_psa.h
anymore.MBEDTLS_CONFIG_H
anymore.A config file version symbol, MBEDTLS_CONFIG_VERSION
was introduced. Defining it to a particular value will ensure that Mbed TLS interprets the config file in a way that's compatible with the config file format used by the Mbed TLS release whose MBEDTLS_VERSION_NUMBER
has the same value. The only value supported by Mbed TLS 3.0.0 is 0x03000000
.
Direct access to fields of structures (struct
types) declared in public headers is no longer supported. In Mbed TLS 3, the layout of structures is not considered part of the stable API, and minor versions (3.1, 3.2, etc.) may add, remove, rename, reorder or change the type of structure fields.
There is a small number of exceptions where some fields are guaranteed to remain stable throughout the lifetime of Mbed TLS 3.x. These fields are explicitly documented as public. Please note that even if all the fields of a structure are public, future versions may add new fields. Also, as before, some public fields should be considered read-only, since modifying them may make the structure inconsistent; check the documentation in each case.
Attempting to access a private field directly will result in a compilation error.
If you were accessing structure fields directly, and these fields are not documented as public, you need to change your code. If an accessor (getter/setter) function exists, use that. Direct accessor functions are usually called mbedtls_<MODULE>_{get,set}_<FIELD>
or mbedtls_<MODULE>_<STRUCTURE>_{get,set}_<FIELD>
. Accessor functions that change the format may use different verbs, for example read
/write
for functions that import/export data from/to a text or byte string.
If no accessor function exists, please open an enhancement request against Mbed TLS and describe your use case. The Mbed TLS development team is aware that some useful accessor functions are missing in the 3.0 release, and we expect to add them to the first minor release(s) (3.1, etc.).
As a last resort, you can access the field foo
of a structure bar
by writing bar.MBEDTLS_PRIVATE(foo)
. Note that you do so at your own risk, since such code is likely to break in a future minor version of Mbed TLS.
The change affects users who use any of the following functions: mbedtls_timing_self_test()
, mbedtls_hardclock_poll()
, mbedtls_timing_hardclock()
and mbedtls_set_alarm()
.
If you were relying on these functions, you‘ll now need to change to using your platform’s corresponding functions directly.
The file include/mbedtls/net.h
was removed because its only function was to include mbedtls/net_sockets.h
which now should be included directly.
MBEDTLS_CHECK_PARAMS
optionThis change does not affect users who use the default configuration; it only affects users who enabled that option.
The option MBEDTLS_CHECK_PARAMS
(disabled by default) enabled certain kinds of “parameter validation”. It covered two kinds of validations:
The default reaction to a failed check was to call a function mbedtls_param_failed()
which the application had to provide. If this function returned, its caller returned an error MBEDTLS_ERR_xxx_BAD_INPUT_DATA
.
This feature was only used in some classic (non-PSA) cryptography modules. It was not used in X.509, TLS or in PSA crypto, and it was not implemented in all classic crypto modules.
This feature has been removed. The library no longer checks for NULL pointers; checks for enum-like arguments will be kept or re-introduced on a case-by-case basis, but their presence will no longer be dependent on a compile-time option.
Validation of enum-like values is somewhat useful, but not extremely important, because the parameters concerned are usually constants in applications.
For more information see issue #4313.
MBEDTLS_TEST_NULL_ENTROPY
configuration optionThis does not affect users who use the default mbedtls_config.h
, as this option was already off by default.
If you were using the MBEDTLS_TEST_NULL_ENTROPY
option and your platform doesn't have any entropy source, you should use MBEDTLS_ENTROPY_NV_SEED
and make sure your device is provisioned with a strong random seed. Alternatively, for testing purposes only, you can create and register a fake entropy function.
This doesn't affect people using the default configuration as it was already disabled by default.
This only affects users who called the HAVEGE modules directly (not recommended), or users who used it through the entropy module but had it as the only source of entropy. If you're in that case, please declare OS or hardware RNG interfaces with mbedtls_entropy_add_source()
and/or use an entropy seed file created securely during device provisioning. See https://tls.mbed.org/kb/how-to/add-entropy-sources-to-entropy-pool for more information.
This only affects people who've been using Mbed TLS since before version 2.0 and still relied on compat-1.3.h
in their code.
Please use the new names directly in your code; scripts/rename.pl
(from any of the 2.x releases — no longer included in 3.0) might help you do that.
Please also refer to the section High-level crypto for changes that could sit in either category.
This change affects all users who called a function accepting a f_rng
parameter with NULL
as the value of this argument; this is no longer supported.
The changed functions are: the X.509 CRT and CSR writing functions; the PK and RSA sign and decrypt functions; mbedtls_rsa_private()
; the functions in DHM and ECDH that compute the shared secret; the scalar multiplication functions in ECP.
You now need to pass a properly seeded, cryptographically secure RNG to all functions that accept a f_rng
parameter. It is of course still possible to pass NULL
as the context pointer p_rng
if your RNG function doesn't need a context.
Alternative implementations of a module (enabled with the MBEDTLS_module_ALT
configuration options) may have their own internal and are free to ignore the f_rng
argument but must allow users to pass one anyway.
This affects users of the following functions: mbedtls_ecp_check_pub_priv()
, mbedtls_pk_check_pair()
, mbedtls_pk_parse_key()
, and mbedtls_pk_parse_keyfile()
.
You now need to pass a properly seeded, cryptographically secure RNG when calling these functions. It is used for blinding, a countermeasure against side-channel attacks.
The function mbedtls_mpi_is_prime()
was removed. Please use mbedtls_mpi_is_prime_ext()
instead which additionally allows specifying the number of Miller-Rabin rounds.
The functions mbedtls_ctr_drbg_update()
and mbedtls_hmac_drbg_update()
were removed. They were superseded by mbedtls_ctr_drbg_update_ret()
and mbedtls_hmac_drbg_update_ret()
respectively.
The macros MBEDTLS_DHM_RFC5114_MODP_2048_P
, MBEDTLS_DHM_RFC5114_MODP_2048_G
, MBEDTLS_DHM_RFC3526_MODP_2048_P
, MBEDTLS_DHM_RFC3526_MODP_2048_G
, MBEDTLS_DHM_RFC3526_MODP_3072_P
, MBEDTLS_DHM_RFC3526_MODP_3072_G
, MBEDTLS_DHM_RFC3526_MODP_4096_P
and MBEDTLS_DHM_RFC3526_MODP_4096_G
were removed. The primes from RFC 5114 are deprecated because their derivation is not documented and therefore their usage constitutes a security risk; they are fully removed from the library. Please use parameters from RFC3526 (still in the library, only in binary form) or RFC 7919 (also available in the library) or other trusted sources instead.
Modules: MD5, SHA1, SHA256, SHA512, MD.
mbedtls_xxx_starts_ret()
, mbedtls_xxx_update_ret()
, mbedtls_xxx_finish_ret()
and mbedtls_xxx_ret()
were renamed to replace the corresponding functions without _ret
appended. Please call the name without _ret
appended and check the return value.mbedtls_md_init_ctx()
was removed; please use mbedtls_md_setup()
instead.mbedtls_xxx_process()
were removed. You normally don't need to call that from application code. However if you do (or if you want to provide your own version of that function), please use mbedtls_internal_xxx_process()
instead, and check the return value.MBEDTLS_ECP_FIXED_POINT_OPTIM
behaviorThe option MBEDTLS_ECP_FIXED_POINT_OPTIM
now increases code size and it does not increase peak RAM usage anymore.
If you are limited by code size, you can define MBEDTLS_ECP_FIXED_POINT_OPTIM
to 0
in your config file. The impact depends on the number and size of enabled curves. For example, for P-256 the difference is 1KB; see the documentation of this option for details.
MBEDTLS_SHA224_C
and MBEDTLS_SHA256_C
This does not affect users who use the default mbedtls_config.h
. MBEDTLS_SHA256_C was enabled by default. Now both MBEDTLS_SHA256_C and MBEDTLS_SHA224_C are enabled.
If you were using custom config file with MBEDTLS_SHA256_C enabled, then you will need to add #define MBEDTLS_SHA224_C
option to your config. Current version of the library does not support enabling MBEDTLS_SHA256_C without MBEDTLS_SHA224_C.
MBEDTLS_SHA512_NO_SHA384
with MBEDTLS_SHA384_C
This does not affect users who use the default mbedtls_config.h
. MBEDTLS_SHA512_NO_SHA384 was disabled by default, now MBEDTLS_SHA384_C is enabled by default.
If you were using a config file with both MBEDTLS_SHA512_C and MBEDTLS_SHA512_NO_SHA384, then just remove the MBEDTLS_SHA512_NO_SHA384. If you were using a config file with MBEDTLS_SHA512_C and without MBEDTLS_SHA512_NO_SHA384 and you need the SHA-384 algorithm, then add #define MBEDTLS_SHA384_C
to your config file.
The GCM module now supports arbitrary chunked input in the multipart interface. This changes the interface for applications using the GCM module directly for multipart operations. Applications using one-shot GCM or using GCM via the mbedtls_cipher_xxx
or psa_aead_xxx
interfaces do not require any changes.
mbedtls_gcm_starts()
now only sets the mode and the nonce (IV). Call the new function mbedtls_gcm_update_ad()
to pass the associated data.mbedtls_gcm_update()
now takes an extra parameter to indicate the actual output length. In Mbed TLS 2.x, applications had to pass inputs consisting of whole 16-byte blocks except for the last block (this limitation has been lifted). In this case:mbedtls_gcm_finish()
instead of returning it in the last call to mbedtls_gcm_update()
.mbedtls_gcm_finish()
now takes an extra output buffer for the last partial block. This is needed for alternative implementations that can only process a whole block at a time.The GCM multipart interface has changed as described in “GCM multipart interface: application changes”. The consequences for an alternative implementation of GCM (MBEDTLS_GCM_ALT
) are as follows:
mbedtls_gcm_starts()
now only sets the mode and the nonce (IV). The new function mbedtls_gcm_update_ad()
receives the associated data. It may be called multiple times.mbedtls_gcm_update()
now allows arbitrary-length inputs, takes an extra parameter to indicate the actual output length. Alternative implementations may choose between two modes:mbedtls_gcm_update()
or mbedtls_gcm_finish()
.mbedtls_gcm_finish()
now takes an extra output buffer for the last partial block if needed.MBEDTLS_ECP_NO_INTERNAL_RNG
was removedThis doesn't affect users of the default configuration; it only affects people who were explicitly setting this option.
This was a trade-off between code size and countermeasures; it is no longer relevant as the countermeasure is now always on at no cost in code size.
The output parameter of mbedtls_sha256_finish_ret()
, mbedtls_sha256_ret()
, mbedtls_sha512_finish_ret()
, mbedtls_sha512_ret()
now has a pointer type rather than array type. This makes no difference in terms of C semantics, but removes spurious warnings in some compilers when outputting a SHA-384 hash into a 48-byte buffer or a SHA-224 hash into a 28-byte buffer.
This makes no difference to a vast majority of applications. If your code takes a pointer to one of these functions, you may need to change the type of the pointer.
Alternative implementations of the SHA256 and SHA512 modules must adjust their functions' prototype accordingly.
MBEDTLS_ERR_xxx_FEATURE_UNSUPPORTED
from various crypto modules were removed; MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED
is now used instead.MBEDTLS_ERR_xxx_HW_ACCEL_FAILED
from various crypto modules were removed; MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED
is now used instead.This affects all users who use the RSA encryption, decryption, sign and verify APIs.
The RSA module no longer supports private-key operations with the public key or vice versa. As a consequence, RSA operation functions no longer have a mode parameter. If you were calling RSA operations with the normal mode (public key for verification or encryption, private key for signature or decryption), remove the MBEDTLS_MODE_PUBLIC
or MBEDTLS_MODE_PRIVATE
argument. If you were calling RSA operations with the wrong mode, which rarely makes sense from a security perspective, this is no longer supported.
The functions mbedtls_aes_encrypt()
and mbedtls_aes_decrypt()
were removed.
If you're simply using the AES module, you should be calling the higher-level functions mbedtls_aes_crypt_xxx()
.
If you're providing an alternative implementation using MBEDTLS_AES_ENCRYPT_ALT
or MBEDTLS_AES_DECRYPT_ALT
, you should be replacing the removed functions with mbedtls_internal_aes_encrypt()
and mbedtls_internal_aes_decrypt()
respectively.
Please also refer to the section Low-level crypto for changes that could sit in either category.
mbedtls_cipher_finish()
is mandatory for all multi-part operationsThis only affects people who use the cipher module to perform AEAD operations using the multi-part API.
Previously, the documentation didn't state explicitly if it was OK to call mbedtls_cipher_check_tag()
or mbedtls_cipher_write_tag()
directly after the last call to mbedtls_cipher_update()
— that is, without calling mbedtls_cipher_finish()
in-between. If you code was missing that call, please add it and be prepared to get as much as 15 bytes of output.
Currently the output is always 0 bytes, but it may be more when alternative implementations of the underlying primitives are in use, or with future versions of the library.
RSA verification functions also no longer take random generator arguments (this was only needed when using a private key). This affects all applications using the RSA verify functions.
This change affects users of the MD2, MD4, RC4, Blowfish and XTEA algorithms.
They are already niche or obsolete and most of them are weak or broken. For those reasons possible users should consider switching to modern and safe alternatives to be found in literature.
The functions mbedtls_cipher_auth_encrypt()
and mbedtls_cipher_auth_decrypt()
were removed. They were superseded by mbedtls_cipher_auth_encrypt_ext()
and mbedtls_cipher_auth_decrypt_ext()
respectively which additionally support key wrapping algorithms such as NIST_KW.
The functions mbedtls_ecdsa_write_signature_det()
and mbedtls_ecdsa_sign_det()
were removed. They were superseded by mbedtls_ecdsa_write_signature()
and mbedtls_ecdsa_sign_det_ext()
respectively.
The following functions now take an extra parameter indicating the size of the output buffer:
mbedtls_ecdsa_write_signature()
, mbedtls_ecdsa_write_signature_restartable()
mbedtls_pk_sign()
, mbedtls_pk_sign_restartable()
The requirements for the output buffer have not changed, but passing a buffer that is too small now reliably causes the functions to return an error, rather than overflowing the buffer.
mbedtls_*_ret()
cryptography functions whose deprecated variants have been removedThis change affects users who were using the mbedtls_*_ret()
cryptography functions.
Those functions were created based on now-deprecated functions according to a requirement that a function needs to return a value. This change brings back the original names of those functions. The renamed functions are:
name before this change | after the change |
---|---|
mbedtls_ctr_drbg_update_ret | mbedtls_ctr_drbg_update |
mbedtls_hmac_drbg_update_ret | mbedtls_hmac_drbg_update |
mbedtls_md5_starts_ret | mbedtls_md5_starts |
mbedtls_md5_update_ret | mbedtls_md5_update |
mbedtls_md5_finish_ret | mbedtls_md5_finish |
mbedtls_md5_ret | mbedtls_md5 |
mbedtls_ripemd160_starts_ret | mbedtls_ripemd160_starts |
mbedtls_ripemd160_update_ret | mbedtls_ripemd160_update |
mbedtls_ripemd160_finish_ret | mbedtls_ripemd160_finish |
mbedtls_ripemd160_ret | mbedtls_ripemd160 |
mbedtls_sha1_starts_ret | mbedtls_sha1_starts |
mbedtls_sha1_update_ret | mbedtls_sha1_update |
mbedtls_sha1_finish_ret | mbedtls_sha1_finish |
mbedtls_sha1_ret | mbedtls_sha1 |
mbedtls_sha256_starts_ret | mbedtls_sha256_starts |
mbedtls_sha256_update_ret | mbedtls_sha256_update |
mbedtls_sha256_finish_ret | mbedtls_sha256_finish |
mbedtls_sha256_ret | mbedtls_sha256 |
mbedtls_sha512_starts_ret | mbedtls_sha512_starts |
mbedtls_sha512_update_ret | mbedtls_sha512_update |
mbedtls_sha512_finish_ret | mbedtls_sha512_finish |
mbedtls_sha512_ret | mbedtls_sha512 |
To migrate to the this change the user can keep the *_ret
names in their code and include the compat_2.x.h
header file which holds macros with proper renaming or to rename those functions in their code according to the list from mentioned header file.
This affects users of the PK API as well as users of the low-level API in the RSA module. Users of the PSA API or of the ECDSA module are unaffected.
All the functions in the RSA module that accept a hashlen
parameter used to ignore it unless the md_alg
parameter was MBEDTLS_MD_NONE
, indicating raw data was signed. The hashlen
parameter is now always the size that is read from the hash
input buffer. This length must be equal to the output size of the hash algorithm used when signing a hash. (The requirements when signing raw data are unchanged.) This affects the following functions:
mbedtls_rsa_pkcs1_sign
, mbedtls_rsa_pkcs1_verify
mbedtls_rsa_rsassa_pkcs1_v15_sign
, mbedtls_rsa_rsassa_pkcs1_v15_verify
mbedtls_rsa_rsassa_pss_sign
, mbedtls_rsa_rsassa_pss_verify
mbedtls_rsa_rsassa_pss_sign_ext
, mbedtls_rsa_rsassa_pss_verify_ext
The signature functions in the PK module no longer accept 0 as the hash_len
parameter. The hash_len
parameter is now always the size that is read from the hash
input buffer. This affects the following functions:
mbedtls_pk_sign
, mbedtls_pk_verify
mbedtls_pk_sign_restartable
, mbedtls_pk_verify_restartable
mbedtls_pk_verify_ext
The migration path is to pass the correct value to those functions.
mbedtls_rsa_init()
This affects all users who use the RSA encryption, decryption, sign and verify APIs.
The function mbedtls_rsa_init()
no longer supports selecting the PKCS#1 v2.1 encoding and its hash. It just selects the PKCS#1 v1.5 encoding by default. If you were using the PKCS#1 v2.1 encoding you now need, subsequently to the call to mbedtls_rsa_init()
, to call mbedtls_rsa_set_padding()
to set it.
To choose the padding type when initializing a context, instead of
mbedtls_rsa_init(ctx, padding, hash_id);
use
mbedtls_rsa_init(ctx); mbedtls_rsa_set_padding(ctx, padding, hash_id);
To use PKCS#1 v1.5 padding, instead of
mbedtls_rsa_init(ctx, MBEDTLS_RSA_PKCS_V15, <ignored>);
just use
mbedtls_rsa_init(ctx);
Various functions in the PK and ASN.1 modules had a const
qualifier added to some of their parameters.
This normally doesn‘t affect your code, unless you use pointers to reference those functions. In this case, you’ll need to update the type of your pointers in order to match the new signature.
Some constants and types that were present in beta versions of the PSA Crypto API were removed from version 1.0 of specification. Please switch to the new names provided by the 1.0 specification instead.
This shouldn't affect users who took care not to include headers that were documented as internal, despite being in the public include directory.
If you‘re providing alt implementations of ECP or RSA, you’ll need to add our library
directory to your include path when building your alt implementations, and note that ecp_internal.h
and rsa_internal.h
have been renamed to ecp_internal_alt.h
and rsa_alt_helpers.h
respectively.
If you‘re a library user and used to rely on having access to a structure or function that’s now in a private header, please reach out on the mailing list and explain your need; we'll consider adding a new API in a future version.
The CCM interface has changed with the addition of support for multi-part operations. Five new API functions have been defined: mbedtls_ccm_starts()
, mbedtls_ccm_set_lengths()
, mbedtls_ccm_update_ad()
, mbedtls_ccm_update()
and mbedtls_ccm_finish()
. Alternative implementations of CCM (MBEDTLS_CCM_ALT
) have now to implement those additional five API functions.
This should not affect production use of the library, as the certificates and keys included there were never suitable for production use.
However it might affect you if you relied on them for testing purposes. In that case, please embed your own test certificates in your test code; now that certs.c
is out of the library there is no longer any stability guaranteed and it may change in incompatible ways at any time.
This affects applications that call the mbedtls_x509write_csr_set_extension
function.
The API is changed to include the parameter critical
which enables marking an extension included in a CSR as critical. To get the previous behavior pass 0.
This change does not affect users of the default configuration; it only affects users who enable this option.
The X.509 standard says that implementations must reject critical extensions that they don‘t recognize, and this is what Mbed TLS does by default. This option allowed to continue parsing those certificates but didn’t provide a convenient way to handle those extensions.
The migration path from that option is to use the mbedtls_x509_crt_parse_der_with_ext_cb()
function which is functionally equivalent to mbedtls_x509_crt_parse_der()
, and/or mbedtls_x509_crt_parse_der_nocopy()
but it calls the callback with every unsupported certificate extension and additionally the “certificate policies” extension if it contains any unsupported certificate policies.
MBEDTLS_X509_CHECK_*_KEY_USAGE
options from mbedtls_config.h
This change affects users who have chosen the configuration options to disable the library's verification of the keyUsage
and extendedKeyUsage
fields of x509 certificates.
The MBEDTLS_X509_CHECK_KEY_USAGE
and MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
configuration options are removed and the X509 code now behaves as if they were always enabled. It is consequently not possible anymore to disable at compile time the verification of the keyUsage
and extendedKeyUsage
fields of X509 certificates.
The verification of the keyUsage
and extendedKeyUsage
fields is important, disabling it can cause security issues and it is thus not recommended. If the verification is for some reason undesirable, it can still be disabled by means of the verification callback function passed to mbedtls_x509_crt_verify()
(see the documentation of this function for more information).
MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
optionThis change does not affect users who were using the default configuration, as this option was already disabled by default. Also, it does not affect users who are working with current V3 X.509 certificates.
Extensions were added in V3 of the X.509 specification, so pre-V3 certificates containing extensions were never compliant. Mbed TLS now rejects them with a parsing error in all configurations, as it did previously in the default configuration.
If you are working with the pre-V3 certificates you need to switch to the current ones.
This is described in the section Strengthen default algorithm selection for X.509 and TLS.
This doesn't affect people using the default configuration as it was already disabled by default.
If you used to rely on this module in order to store your private keys securely, please have a look at the key management facilities provided by the PSA crypto API. If you have a use case that's not covered yet by this API, please reach out on the mailing list.
This change affects users of the TLS 1.0, 1.1 and DTLS 1.0 protocols.
These versions have been deprecated by RFC 8996. Keeping them in the library creates opportunities for misconfiguration and possibly downgrade attacks. More generally, more code means a larger attack surface, even if the code is supposedly not used.
The migration path is to adopt the latest versions of the protocol.
As a consequence of removing TLS 1.0, support for CBC record splitting was also removed, as it was a work-around for a weakness in this particular version. There is no migration path since the feature is no longer relevant.
As a consequence of currently supporting only one version of (D)TLS (and in the future 1.3 which will have a different version negotiation mechanism), support for fallback SCSV (RFC 7507) was also removed. There is no migration path as it's no longer useful with TLS 1.2 and later.
As a consequence of currently supporting only one version of (D)TLS (and in the future 1.3 which will have a different concept of ciphersuites), support for configuring ciphersuites separately for each version via mbedtls_ssl_conf_ciphersuites_for_version()
was removed. Use mbedtls_ssl_conf_ciphersuites()
to configure ciphersuites to use with (D)TLS 1.2; in the future a different API will be added for (D)TLS 1.3.
This doesn't affect people using the default configuration as it was already disabled by default.
This only affects TLS users who explicitly enabled MBEDTLS_SSL_PROTO_SSL3
and relied on that version in order to communicate with peers that are not up to date. If one of your peers is in that case, please try contacting them and encouraging them to upgrade their software.
This doesn't affect people using the default configuration as it was already disabled by default.
This only affects TLS servers that have clients who send an SSLv2 ClientHello. These days clients are very unlikely to do that. If you have a client that does, please try contacting them and encouraging them to upgrade their software.
This affects users of truncated HMAC, that is, users who called mbedtls_ssl_conf_truncated_hmac( ..., MBEDTLS_SSL_TRUNC_HMAC_ENABLED)
, regardless of whether the standard version was used or compatibility version (MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT
).
The recommended migration path for people who want minimal overhead is to use a CCM-8 ciphersuite.
This doesn't affect people using the default configuration as it was already disabled by default.
This only affects TLS users who enabled MBEDTLS_ZLIB_SUPPORT
. This will not cause any failures however if you used to enable TLS record-level compression you may find that your bandwidth usage increases without compression. There's no general solution to this problem; application protocols might have their own compression mechanisms and are in a better position than the TLS stack to avoid variants of the CRIME and BREACH attacks.
This does not affect people who used the default mbedtls_config.h
and the default list of ciphersuites, as RC4-based ciphersuites were already not negotiated in that case.
Please switch to any of the modern, recommended ciphersuites (based on AES-GCM, AES-CCM or ChachaPoly for example) and if your peer doesn't support any, encourage them to upgrade their software.
This doesn't affect people using the default configuration as it was already disabled by default.
Please switch to any of the modern, recommended ciphersuites (based on AES-GCM, AES-CCM or ChachaPoly for example) and if your peer doesn't support any, encourage them to upgrade their software.
This doesn't affect people using the default configuration as it was already disabled by default.
This feature had been broken for a while so we doubt anyone still used it. However if you did, please reach out on the mailing list and let us know about your use case.
MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME
This doesn't affect people using the default configuration.
This option has not had any effect for a long time. Please use the lifetime
parameter of mbedtls_ssl_ticket_setup()
instead.
MBEDTLS_SSL_CID_PADDING_GRANULARITY
and MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY
optionsThis change affects users who modified the default mbedtls_config.h
padding granularity settings, i.e. enabled at least one of the options.
The mbedtls_config.h
options MBEDTLS_SSL_CID_PADDING_GRANULARITY
and MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY
were combined into one option because they used exactly the same padding mechanism and hence their respective padding granularities can be used in exactly the same way. This change simplifies the code maintenance.
The new single option MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY
can be used for both DTLS-CID and TLS 1.3.
The default preference order for curves in TLS now favors resource usage (performance and memory consumption) over size. The exact order is unspecified and may change, but generally you can expect 256-bit curves to be preferred over larger curves.
If you prefer a different order, call mbedtls_ssl_conf_curves()
when configuring a TLS connection.
This affects users of the SSL key export APIs:
mbedtls_ssl_conf_export_keys_cb() mbedtls_ssl_conf_export_keys_ext_cb()
Those APIs have been removed and replaced by the new API mbedtls_ssl_set_export_keys_cb()
. This API differs from the previous key export API in the following ways:
For users which do not rely on raw keys and IV, adjusting to the new callback type should be straightforward — see the example programs programs/ssl/ssl_client2
and programs/ssl/ssl_server2
for callbacks for NSSKeylog, EAP-TLS and DTLS-SRTP.
Users which require access to the raw keys used to secure application traffic may derive those by hand based on the master secret and the handshake transcript hashes which can be obtained from the raw data on the wire. Such users are also encouraged to reach out to the Mbed TLS team on the mailing list, to let the team know about their use case.
This affects users which use the MFL query APIs mbedtls_ssl_get_{input,output}_max_frag_len()
to infer upper bounds on the plaintext size of incoming and outgoing record.
Users should switch to mbedtls_ssl_get_max_{in,out}_record_payload()
instead, which also provides such upper bounds but takes more factors than just the MFL configuration into account.
This affects users which call the PSK configuration APIs mbedtlsl_ssl_conf_psk()
and mbedtls_ssl_conf_psk_opaque()
multiple times on the same SSL configuration.
In Mbed TLS 2.x, users would observe later calls overwriting the effect of earlier calls, with the prevailing PSK being the one that has been configured last. In Mbed TLS 3.0, calling mbedtls_ssl_conf_[opaque_]psk()
multiple times will return an error, leaving the first PSK intact.
To achieve equivalent functionality when migrating to Mbed TLS 3.0, users calling mbedtls_ssl_conf_[opaque_]psk()
multiple times should remove all but the last call, so that only one call to either mbedtls_ssl_conf_psk()
or mbedtls_ssl_conf_psk_opaque()
remains.
This does not affect users who use the default mbedtls_config.h
, as this option was already off by default.
If you were using a weak cipher, please switch to any of the modern, recommended ciphersuites (based on AES-GCM, AES-CCM or ChachaPoly for example) and if your peer doesn't support any, encourage them to upgrade their software.
If you were using a ciphersuite without encryption, you just have to enable MBEDTLS_CIPHER_NULL_CIPHER
now.
MBEDTLS_SSL_MAX_CONTENT_LEN
configuration optionThis affects users who use the MBEDTLS_SSL_MAX_CONTENT_LEN
option to set the maximum length of incoming and outgoing plaintext fragments, which can save memory by reducing the size of the TLS I/O buffers.
This option is replaced by the more fine-grained options MBEDTLS_SSL_IN_CONTENT_LEN
and MBEDTLS_SSL_OUT_CONTENT_LEN
that set the maximum incoming and outgoing plaintext fragment lengths, respectively.
mbedtls_ssl_get_session_pointer()
This affects two classes of users:
Users who manually inspect parts of the current session through direct structure field access.
Users of session resumption who query the current session via mbedtls_ssl_get_session_pointer()
prior to saving or exporting it via mbedtls_ssl_session_copy()
or mbedtls_ssl_session_save()
, respectively.
Migration paths:
Mbed TLS 3.0 does not offer a migration path for the use case 1: Like many other Mbed TLS structures, the structure of mbedtls_ssl_session
is no longer part of the public API in Mbed TLS 3.0, and direct structure field access is no longer supported. Please see the section on private structure fields for more details.
Users should replace calls to mbedtls_ssl_get_session_pointer()
by calls to mbedtls_ssl_get_session()
as demonstrated in the example program programs/ssl/ssl_client2.c
.
MBEDTLS_SSL_DTLS_BADMAC_LIMIT
optionThis change does not affect users who used the default mbedtls_config.h
, as the option MBEDTLS_SSL_DTLS_BADMAC_LIMIT
was already on by default.
This option was a trade-off between functionality and code size: it allowed users who didn't need that feature to avoid paying the cost in code size, by disabling it.
This option is no longer present, but its functionality is now always enabled.
The function mbedtls_ssl_conf_dh_param()
was removed. Please use mbedtls_ssl_conf_dh_param_bin()
or mbedtls_ssl_conf_dh_param_ctx()
instead.
The function mbedtls_ssl_get_max_frag_len()
was removed. Please use mbedtls_ssl_get_max_out_record_payload()
and mbedtls_ssl_get_max_in_record_payload()
instead.
MBEDTLS_SSL_RECORD_CHECKING
option and enable its action by defaultThis change does not affect users who use the default mbedtls_config.h
, as the option MBEDTLS_SSL_RECORD_CHECKING
was already on by default.
This option was added only to control compilation of one function, mbedtls_ssl_check_record()
, which is only useful in some specific cases, so it was made optional to allow users who don't need it to save some code space. However, the same effect can be achieved by using link-time garbage collection.
Users who changed the default setting of the option need to change the config/ build system to remove that change.
This affects users who use mbedtls_ssl_conf_session_cache()
to configure a custom session cache implementation different from the one Mbed TLS implements in library/ssl_cache.c
.
Those users will need to modify the API of their session cache implementation to that of a key-value store with keys being session IDs and values being instances of mbedtls_ssl_session
:
typedef int mbedtls_ssl_cache_get_t( void *data, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_session *session ); typedef int mbedtls_ssl_cache_set_t( void *data, unsigned char const *session_id, size_t session_id_len, const mbedtls_ssl_session *session );
Since the structure of mbedtls_ssl_session
is no longer public from 3.0 onwards, portable session cache implementations must not access fields of mbedtls_ssl_session
. See the corresponding migration guide. Users that find themselves unable to migrate their session cache functionality without accessing fields of mbedtls_ssl_session
should describe their use case on the Mbed TLS mailing list.
This affects users manually checking for the following error codes:
MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED
MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH
MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE
MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN
MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE
MBEDTLS_ERR_SSL_BAD_HS_XXX
Migration paths:
MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE
has been removed, and MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL
is returned instead if the user's own certificate is too large to fit into the output buffers.
Users should check for MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL
instead, and potentially compare the size of their own certificate against the configured size of the output buffer to understand if the error is due to an overly large certificate.
MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN
and MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE
have been replaced by MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE
.
All codes of the form MBEDTLS_ERR_SSL_BAD_HS_XXX
have been replaced by various alternatives, which give more information about the type of error raised.
Users should check for the newly introduced generic error codes
MBEDTLS_ERR_SSL_DECODE_ERROR
MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER
,MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE
MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION
MBEDTLS_ERR_SSL_BAD_CERTIFICATE
MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME
MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION
MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL
and the pre-existing generic error codes
MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE
MBEDTLS_ERR_SSL_INTERNAL_ERROR
instead.
mbedtls_ssl_{get,set}_session()
This affects users who call mbedtls_ssl_get_session()
or mbedtls_ssl_set_session()
multiple times on the same SSL context representing an established TLS 1.2 connection. Those users will now observe the second call to fail with MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE
.
Migration path:
mbedtls_ssl_get_session()
leads to multiple copies of the same session. This use of mbedtls_ssl_get_session()
is discouraged, and the following should be considered:mbedtls_ssl_set_session()
, export via mbedtls_ssl_get_session()
only once and load the same session into different contexts via mbedtls_ssl_set_session()
. Since mbedtls_ssl_set_session()
makes a copy of the session that's being loaded, this is functionally equivalent.mbedtls_ssl_session_save()
, export and serialize the session only once via mbedtls_ssl_get_session()
and mbedtls_ssl_session_save()
and make copies of the raw data instead.mbedtls_ssl_set_session()
multiple times in Mbed TLS 2.x is not useful since subsequent calls overwrite the effect of previous calls. Applications achieve equivalent functional behavior by issuing only the very last call to mbedtls_ssl_set_session()
.MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
configuration option into a runtime optionThis change affects users who were enabling MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
option in the mbedtls_config.h
This option has been removed and a new function with similar functionality has been introduced into the SSL API.
This new function mbedtls_ssl_conf_preference_order()
can be used to change the preferred order of ciphersuites on the server to those used on the client, e.g.: mbedtls_ssl_conf_preference_order(ssl_config, MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT)
has the same effect as enabling the removed option. The default state is to use the server order of suites.
The default X.509 verification profile (mbedtls_x509_crt_profile_default
) and the default curve and hash selection in TLS have changed. They are now aligned, except that the X.509 profile only lists curves that support signature verification.
Hashes and curves weaker than 255 bits (security strength less than 128 bits) are no longer accepted by default. The following hashes have been removed: SHA-1 (formerly only accepted for key exchanges but not for certificate signatures), SHA-224 (weaker hashes were already not accepted). The following curves have been removed: secp192r1, secp224r1, secp192k1, secp224k1.
The compile-time options MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
and MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
are no longer available.
The curve secp256k1 has also been removed from the default X.509 and TLS profiles. RFC 8422 deprecates it in TLS, and it is very rarely used, although it is not known to be weak at the time of writing.
If you still need to accept certificates signed with algorithms that have been removed from the default profile, call mbedtls_x509_crt_verify_with_profile
instead of mbedtls_x509_crt_verify
and pass a profile that allows the curves and hashes you want. For example, to allow SHA-224:
mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_default; my_profile.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 );
If you still need to allow hashes and curves in TLS that have been removed from the default configuration, call mbedtls_ssl_conf_sig_hashes()
and mbedtls_ssl_conf_curves()
with the desired lists.
This change does not affect users using default settings for 3DES in mbedtls_config.h
because the 3DES ciphersuites were disabled by that.
3DES has weaknesses/limitations and there are better alternatives, and more and more standard bodies are recommending against its use in TLS.
The migration path here is to chose from the alternatives recommended in the literature, such as AES.