# Migrating from Mbed TLS 2.x to Mbed TLS 3.0

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:

- Removal of many insecure or obsolete features
- Tidying up of configuration options (including removing some less useful options).
- Changing function signatures, e.g. adding return codes, adding extra parameters, or making some arguments const.
- Removal of functions previously marked as deprecated.


## General changes

### Introduce a level of indirection and versioning in the config files

`config.h` was split into `build_info.h` and `mbedtls_config.h`.

* In code, use `#include <mbedtls/build_info.h>`. Don't include `mbedtls/config.h` and don't refer to `MBEDTLS_CONFIG_FILE`.
* In build tools, edit `mbedtls_config.h`, or edit `MBEDTLS_CONFIG_FILE` as before.
* If you had a tool that parsed the library version from `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:

* Don't include `check_config.h` or `config_psa.h` anymore.
* Don't define `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`.

### Most structure fields are now private

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](https://github.com/ARMmbed/mbedtls/issues/new?template=feature_request.md) 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.

### Move part of timing module out of the library

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.

### Deprecated net.h file was removed

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.

### Remove `MBEDTLS_CHECK_PARAMS` option

This 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:

- In some functions that require a valid pointer, “parameter validation” checks
that the pointer is non-null. With the feature disabled, a null pointer is not
treated differently from any other invalid pointer, and typically leads to a
runtime crash. 90% of the uses of the feature are of this kind.
- In some functions that take an enum-like argument, “parameter validation”
checks that the value is a valid one. With the feature disabled, an invalid
value causes a silent default to one of the valid values.

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.

### Remove the `MBEDTLS_TEST_NULL_ENTROPY` configuration option

This 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.

### Remove the HAVEGE module

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.

### Remove helpers for the transition from Mbed TLS 1.3 to Mbed TLS 2.0

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.


## Low-level crypto

Please also refer to the section [High-level crypto](#high-level-crypto) for
changes that could sit in either category.

### Deprecated functions were removed from bignum

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.

### Deprecated functions were removed from DRBGs

The functions `mbedtls_ctr_drbg_update_ret()` and `mbedtls_hmac_drbg_update_ret()`
were renamed to replace the corresponding functions without `_ret` appended. Please call
the name without `_ret` appended and check the return value.

### Deprecated hex-encoded primes were removed from DHM

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.

### Deprecated functions were removed from hashing modules

Modules: MD5, SHA1, SHA256, SHA512, MD.

- The functions `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.
- The function `mbedtls_md_init_ctx()` was removed; please use
  `mbedtls_md_setup()` instead.
- The functions `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.

### Change `MBEDTLS_ECP_FIXED_POINT_OPTIM` behavior

The 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.

### Separated `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`.

### Replaced `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.

### GCM multipart interface: application changes

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:
    * As long as the input remains block-aligned, the output length is exactly the input length, as before.
    * If the length of the last input is not a multiple of 16, alternative implementations may return the last partial block in the call to `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.

### GCM interface changes: impact for alternative implementations

The GCM multipart interface has changed as described in [“GCM multipart interface: application changes”](#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:
    * Always return the partial output immediately, even if it does not consist of a whole number of blocks.
    * Buffer the data for the last partial block, to be returned in the next call to `mbedtls_gcm_update()` or `mbedtls_gcm_finish()`.
* `mbedtls_gcm_finish()` now takes an extra output buffer for the last partial block if needed.

### The configuration option `MBEDTLS_ECP_NO_INTERNAL_RNG` was removed

This 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.

### SHA-512 and SHA-256 output type change

The output parameter of `mbedtls_sha256_finish()`, `mbedtls_sha256()`, `mbedtls_sha512_finish()`, `mbedtls_sha512()` 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.

### Deprecated error codes for hardware failures were removed

- The macros `MBEDTLS_ERR_xxx_FEATURE_UNSUPPORTED` from various crypto modules
  were removed; `MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED` is now used
  instead.
- The macros `MBEDTLS_ERR_xxx_HW_ACCEL_FAILED` from various crypto modules
  were removed; `MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED` is now used instead.

### Remove the mode parameter from RSA functions

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.

### Deprecated functions were removed from AES

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.

### Deprecated functions were removed from ECDSA

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.

### Rename `mbedtls_*_ret()` cryptography functions whose deprecated variants have been removed

This 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.

### Remove the RNG parameter from RSA verify functions

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.

### Remove the padding parameters from `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

```C
    mbedtls_rsa_init(ctx, padding, hash_id);
```

use

```C
    mbedtls_rsa_init(ctx);
    mbedtls_rsa_set_padding(ctx, padding, hash_id);
```

To use PKCS#1 v1.5 padding, instead of

```C
    mbedtls_rsa_init(ctx, MBEDTLS_RSA_PKCS_V15, <ignored>);
```

just use

```C
    mbedtls_rsa_init(ctx);
```


## High-level crypto

Please also refer to the section [Low-level crypto](#low-level-crypto) for
changes that could sit in either category.

### Calling `mbedtls_cipher_finish()` is mandatory for all multi-part operations

This 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.

### Remove MD2, MD4, RC4, Blowfish and XTEA algorithms

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.

### Deprecated functions were removed from cipher

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.

### Extra parameter for the output buffer size

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.

### Signature functions now require the hash length to match the expected value

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.

### Some function parameters were made const

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.

### The RNG parameter is now mandatory for all functions that accept one

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.

### Some functions gained an RNG parameter

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.


## PSA

### Deprecated names for PSA constants and types were removed

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.


## Changes that only affect alternative implementations

### Internal / alt-focused headers were moved to a private location

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.

### CCM interface changes: impact for alternative implementations

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.


## X.509

### Remove the certs module from the library

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.

### Change the API to allow adding critical extensions to CSRs

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.

### Remove the config option `MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION`

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.

### Remove `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).

### Remove the `MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3` option

This 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.

### Strengthen default algorithm selection for X.509

This is described in the section [Strengthen default algorithm selection for X.509 and TLS](#strengthen-default-algorithm-selection-for-x.509-and-tls).

### Remove wrapper for libpkcs11-helper

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.


## SSL

### Remove support for TLS 1.0, 1.1 and DTLS 1.0

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.

### Remove support for SSL 3.0

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.

### Remove support for parsing SSLv2 ClientHello

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.

### Remove support for truncated HMAC

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.

### Remove support for TLS record-level compression

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.

### Remove support for TLS RC4-based ciphersuites

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.

### Remove support for TLS single-DES ciphersuites

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.

### Remove support for TLS record-level hardware acceleration

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.

### Remove config option `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.

### Combine the `MBEDTLS_SSL_CID_PADDING_GRANULARITY` and `MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY` options

This 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.

### TLS now favors faster curves over larger curves

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.

### SSL key export interface change

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:

- It is no longer bound to an SSL configuration, but to an
  SSL context. This allows users to more easily identify the
  connection an exported key belongs to.
- It no longer exports raw keys and IV.
- A secret type parameter has been added to identify which key
  is being exported. For TLS 1.2, only the master secret is
  exported, but upcoming TLS 1.3 support will add other kinds of keys.
- The callback now specifies a void return type, rather than
  returning an error code. It is the responsibility of the application
  to handle failures in the key export callback, for example by
  shutting down the TLS connection.

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.

### Remove MaximumFragmentLength (MFL) query API

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.

### Relaxed semantics for PSK configuration

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.

### Remove the configuration to enable weak ciphersuites in SSL / TLS

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.

### Remove the `MBEDTLS_SSL_MAX_CONTENT_LEN` configuration option

This 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.

### Remove the SSL API `mbedtls_ssl_get_session_pointer()`

This affects two classes of users:

1. Users who manually inspect parts of the current session through
   direct structure field access.

2. 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:

1. 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](#most-structure-fields-are-now-private) for more details.

2. 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`.

### Remove `MBEDTLS_SSL_DTLS_BADMAC_LIMIT` option

This 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.

### Deprecated functions were removed from SSL

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.

### Remove `MBEDTLS_SSL_RECORD_CHECKING` option and enable its action by default

This 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.

### Session Cache API 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`:

```C
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.

### Changes in the SSL error code space

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.

### Modified semantics of `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:
- Exporting the same TLS 1.2 connection multiple times via
  `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:
  * If the various session copies are later loaded into
    fresh SSL contexts via `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.
  * If the various session copies are later serialized
    via `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.
- Calling `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()`.

### Turn `MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE` configuration option into a runtime option

This 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.

### Strengthen default algorithm selection for X.509 and TLS

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](https://datatracker.ietf.org/doc/html/rfc8422#section-5.1.1) 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:
```C
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.

### Remove 3DES ciphersuites

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.
