Add study for TLS/X.509 dependencies on crypto
This is an updated version of the study that was done a few years ago.
The script `syms` was used to list symbols form libmbedtls.a /
libmbedx509.a that are defined externally. It was run with config.py
full minus MBEDTLS_USE_PSA_CRYPTO minus
MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
diff --git a/docs/architecture/psa-migration/dependencies-tls.md b/docs/architecture/psa-migration/dependencies-tls.md
new file mode 100644
index 0000000..74f78d5
--- /dev/null
+++ b/docs/architecture/psa-migration/dependencies-tls.md
@@ -0,0 +1,563 @@
+Dependencies of the TLS library on the Crypto library
+=====================================================
+
+This document is part of the technical study on how to port Mbed TLS to PSA
+Crypto. It describes the dependencies of libmbedtls.a on libmbedcrypto.a.
+
+More precisely, it describes what functions from libmbedcrypto.a are called
+from libmbedtls.a - other forms of dependencies such as using static inline
+functions or types, accessing private struct members, etc., are not listed.
+
+It is based on Mbed TLS 3.0, excluding experimental support for TLS 1.3, and
+also excluding support for restartble ECP operations.
+
+Non-Crypto dependencies
+-----------------------
+
+The TLS library has a number of dependencies on libmbedcrypto.a that are not
+cryptographic, hence are unlikely to be covered by the PSA Crypto API.
+
+These involve the following modules:
+
+- threading
+- platform
+
+It also depends on the X.509 library, which is excluded from further analysis
+as the focus here is on dependencies on libmbedcrypto.a.
+
+Crypto dependencies (high-level)
+--------------------------------
+
+The TLS library depends on the following cryptographic modules:
+
+- cipher
+- dhm
+- ecdh
+- ecjpake
+- ecp
+- md
+- mpi
+- pk
+- sha256
+- sha512
+
+More specifically, calls are made to the following API functions:
+
+```
+mbedtls_cipher_auth_decrypt_ext
+mbedtls_cipher_auth_encrypt_ext
+mbedtls_cipher_crypt
+mbedtls_cipher_free
+mbedtls_cipher_info_from_type
+mbedtls_cipher_init
+mbedtls_cipher_set_padding_mode
+mbedtls_cipher_setkey
+mbedtls_cipher_setup
+
+mbedtls_dhm_calc_secret
+mbedtls_dhm_free
+mbedtls_dhm_get_bitlen
+mbedtls_dhm_get_len
+mbedtls_dhm_get_value
+mbedtls_dhm_init
+mbedtls_dhm_make_params
+mbedtls_dhm_make_public
+mbedtls_dhm_read_params
+mbedtls_dhm_read_public
+mbedtls_dhm_set_group
+
+mbedtls_ecdh_calc_secret
+mbedtls_ecdh_free
+mbedtls_ecdh_get_params
+mbedtls_ecdh_init
+mbedtls_ecdh_make_params
+mbedtls_ecdh_make_public
+mbedtls_ecdh_read_params
+mbedtls_ecdh_read_public
+mbedtls_ecdh_setup
+
+mbedtls_ecjpake_check
+mbedtls_ecjpake_derive_secret
+mbedtls_ecjpake_free
+mbedtls_ecjpake_init
+mbedtls_ecjpake_read_round_one
+mbedtls_ecjpake_read_round_two
+mbedtls_ecjpake_set_point_format
+mbedtls_ecjpake_setup
+mbedtls_ecjpake_write_round_one
+mbedtls_ecjpake_write_round_two
+
+mbedtls_ecp_curve_info_from_grp_id
+mbedtls_ecp_curve_info_from_tls_id
+
+mbedtls_md_clone
+mbedtls_md_finish
+mbedtls_md_free
+mbedtls_md_get_size
+mbedtls_md_get_type
+mbedtls_md_hmac_finish
+mbedtls_md_hmac_reset
+mbedtls_md_hmac_starts
+mbedtls_md_hmac_update
+mbedtls_md_info_from_type
+mbedtls_md_init
+mbedtls_md_setup
+mbedtls_md_starts
+mbedtls_md_update
+
+mbedtls_mpi_bitlen
+mbedtls_mpi_free
+mbedtls_mpi_read_binary
+
+mbedtls_pk_can_do
+mbedtls_pk_debug
+mbedtls_pk_decrypt
+mbedtls_pk_encrypt
+mbedtls_pk_get_bitlen
+mbedtls_pk_sign
+mbedtls_pk_sign_restartable
+mbedtls_pk_verify
+mbedtls_pk_verify_restartable
+
+mbedtls_sha256_clone
+mbedtls_sha256_finish
+mbedtls_sha256_free
+mbedtls_sha256_init
+mbedtls_sha256_starts
+mbedtls_sha256_update
+
+mbedtls_sha512_clone
+mbedtls_sha512_finish
+mbedtls_sha512_free
+mbedtls_sha512_init
+mbedtls_sha512_starts
+mbedtls_sha512_update
+```
+
+Note: the direct dependency on MPI functions is in order to manage DHM
+parameters, that are currently stored as a pair of MPIs in the
+`mbedtls_ssl_config` structure. (The public API uses byte arrays or a
+`mbedtls_dhm_context` structure.)
+
+Note: the direct dependency on ECP APIs is in order to access information;
+no crypto operation is done directly via this API, only via the PK and ECDH
+APIs.
+
+Note: the direct dependencies on the SHA-2 modules instead of using the
+MD layer is for convenience (and perhaps to save some memory as well) and can
+easily be replace by use of a more generic API.
+
+Key exchanges and other configuration options
+---------------------------------------------
+
+In the file-level analysis below, many things are only used if certain key
+exchanges or other configuration options are enabled. This section sums up
+those key exchanges and options.
+
+Key exchanges:
+
+- DHE-PSK
+- DHE-RSA
+- ECDH-ECDSA
+- ECDH-RSA
+- ECDHE-ECDSA
+- ECDHE-PSK
+- ECDHE-RSA
+- ECJPAKE
+- PSK
+- RSA
+- RSA-PSK
+
+Protocol:
+
+- `MBEDTLS_SSL_PROTO_TLS1_2`
+- `MBEDTLS_SSL_PROTO_DTLS`
+- `MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL` (excluded from this analysis)
+
+TLS sides:
+
+- `MBEDTLS_SSL_CLI_C`
+- `MBEDTLS_SSL_SRV_C`
+
+TLS support modules:
+
+- `MBEDTLS_SSL_CACHE_C`
+- `MBEDTLS_SSL_COOKIE_C`
+- `MBEDTLS_SSL_TICKET_C`
+
+Cipher modes:
+
+- `MBEDTLS_CIPHER_MODE_CBC`
+- `MBEDTLS_CIPHER_NULL_CIPHER`
+- `MBEDTLS_GCM_C`
+- `MBEDTLS_CCM_C`
+- `MBEDTLS_CHACHAPOLY_C`
+
+Hashes:
+
+- `MBEDTLS_MD5_C` (ciphersuites using HMAC-MD5)
+- `MBEDTLS_SHA1_C` (ciphersuites using HMAC-SHA1)
+- `MBEDTLS_SHA256_C`
+- `MBEDTLS_SHA512_C`
+
+Other options:
+
+- `MBEDTLS_X509_CRT_PARSE_C`
+- `MBEDTLS_SSL_SESSION_TICKETS`
+- `MBEDTLS_SSL_ENCRYPT_THEN_MAC`
+
+
+File-level analysis
+-------------------
+
+The TLS library consists of the following files (excluding TLS 1.3 which is
+currently experimental and changing rapidly):
+
+```
+library/debug.c
+library/net_sockets.c
+library/ssl_cache.c
+library/ssl_ciphersuites.c
+library/ssl_cli.c
+library/ssl_cookie.c
+library/ssl_msg.c
+library/ssl_srv.c
+library/ssl_ticket.c
+library/ssl_tls.c
+```
+
+The file `net_sockets.c` is excluded from further analysis as it's unrelated.
+
+**Note:** Calls to `f_rng` in the files below could also be replaced with
+direct calls to the global PSA RNG; however these calls are not included in
+the current analysis, since the PSA RNG can already be used by setting it
+explicitly.
+
+### `debug.c`
+
+- In `debug_print_pk()`
+ call `mbedtls_pk_debug()`
+ to print info (or "invalid PK context" on failure)
+ if `MBEDTLS_X509_CRT_PARSE_C` is enabled.
+
+- In `mbedtls_debug_print_mpi()`
+ call `mbedtls_mpi_print_mpi()`
+
+### `ssl_cache.c`
+
+**Note:** This module is only used server side.
+
+No call to any crypto API function from this file.
+
+_Note :_ in the future, work may be required in order to securely store
+session secrets in the cache, but it's outside the scope of this analysis.
+
+### `ssl_ciphersuites.c`
+
+No call to any crypto API function from this file.
+
+### `ssl_cookie.c`
+
+**Note:** this module is only used server-side, only for DTLS.
+
+- In `mbedtls_ssl_cookie_init()` / `mbedtls_ssl_cookie_free()`
+ call `mbedtls_md_init()` / `mbedtls_md_free()`
+
+- In `mbedtls_ssl_cookie_setup()`
+ call `mbedtls_md_setup()`, `mbedtls_md_info_from_type()` and `mbedtls_md_hmac_starts()`
+ to set up an HMAC key.
+
+- In `ssl_cookie_hmac()`
+ call `mbedtls_md_hmac_reset()`, `mbedtls_md_hmac_update()` and `mbedtls_md_hmac_finish()`
+
+### `ssl_ticket.c`
+
+**Note:** This module is only used server-side.
+
+- In `ssl_ticket_gen_key()`
+ call `mbedtls_cipher_setkey()` and `mbedtls_cipher_get_key_bitlen()`
+
+- In `mbedtls_ssl_ticket_setup()`
+ call `mbedtls_cipher_info_from_type()` and `mbedtls_cipher_setup()`
+
+- In `mbedtls_ssl_ticket_write()`
+ call `mbedtls_cipher_auth_encrypt_ext()`
+
+- In `mbedtls_ssl_ticket_parse()`
+ call `mbedtls_cipher_auth_decrypt_ext()`
+
+### `ssl_cli.c`
+
+**Note:** This module is only used client-side.
+
+- In `ssl_write_supported_elliptic_curves_ext()`
+ call `mbedtls_ecp_curve_list()` and `mbedtls_ecp_curve_info_from_grp_id()`
+ if ECDH, ECDSA or ECJPAKE is enabled
+
+- In `ssl_write_ecjpake_kkpp_ext()`
+ call `mbedtls_ecjpake_check()` and `mbedtls_ecjpake_write_round_one()`
+ if ECJPAKE is enabled
+
+- In `ssl_parse_supported_point_formats_ext()`
+ call `mbedtls_ecjpake_set_point_format()`
+ if ECJPAKE is enabled.
+
+- In `ssl_validate_ciphersuite()`
+ call `mbedtls_ecjpake_check()`
+ if ECJPAKE is enabled.
+
+- In `ssl_parse_ecjpake_kkpp()`
+ call `mbedtls_ecjpake_read_round_one()`
+ if ECJPAKE is enabled.
+
+- In `ssl_parse_server_dh_params()`
+ call `mbedtls_dhm_read_params()` and `mbedtls_dhm_get_bitlen()`
+ if DHE-RSA or DHE-PSK key echange is enabled.
+
+- In `ssl_check_server_ecdh_params()`
+ call `mbedtls_ecp_curve_info_from_grp_id()`
+ if ECDHE-RSA, ECDHE-ECDSA, ECDHE-PSK, ECDH-RSA or ECDH-ECDSA key exchange is enabled.
+
+- In `ssl_parse_server_ecdh_params()`
+ call `mbedtls_ecdh_read_params()`
+ if ECDHE-RSA, ECDHE-ECDSA or ECDHE-PSK is enabled.
+
+- In `ssl_write_encrypted_pms()`
+ call `mbedtls_pk_can_do()` and `mbedtls_pk_encrypt()` on peer's public key
+ if RSA or RSA-PSK key exchange enabled.
+
+- In `ssl_get_ecdh_params_from_cert()`
+ call `mbedtls_pk_can_do()` and `mbedtls_pk_ec()` and `mbedtls_ecdh_get_params()`
+ if ECDH-RSA or ECDH-ECDSA key exchange is enabled
+ to import public key of peer's cert to ECDH context.
+
+- In `ssl_parse_server_key_exchange()`
+ call `mbedtls_ecjpake_read_round_two()`
+ if ECJPAKE is enabled.
+
+- In `ssl_parse_server_key_exchange()`
+ call `mbedtls_pk_can_do()` and `mbedtls_pk_verify_restartable()`
+ if DHE-RSA, ECDHE-RSA or ECDHE-ECDSA is enabled.
+ (Note: the hash is computed by `mbedtls_ssl_get_key_exchange_md_tls1_2()`.)
+
+- In `ssl_write_client_key_exchange()`
+ call `mbedtls_dhm_make_public()`, `mbedtls_dhm_get_len()` and `mbedtls_dhm_calc_secret()`
+ if DHE-RSA key exchange is enabled.
+
+- In `ssl_write_client_key_exchange()`
+ call `mbedtls_ecdh_make_public()` and `mbedtls_ecdh_calc_secret()`
+ if ECDHE-RSA, ECDHE-ECDSA, ECDH-RSA or ECDH-ECDSA is enabled.
+
+- In `ssl_write_client_key_exchange()`
+ call `mbedtls_dhm_make_public()` and `mbedtls_dhm_get_len()`
+ if DHE-PSK is enabled.
+
+- In `ssl_write_client_key_exchange()`
+ call `mbedtls_ecdh_make_public()`
+ if ECDHE-PSK is enabled.
+
+- In `ssl_write_client_key_exchange()`
+ call `mbedtls_ecjpake_write_round_two()` and `mbedtls_ecjpake_derive_secret()`
+ if ECJPAKE is enabled.
+
+- In `ssl_write_certificate_verify()`
+ call `mbedtls_pk_can_do()` and `mbedtls_pk_sign_restartable()`
+ if RSA, DHE-RSA, ECDH-RSA, ECDHE-RSA, ECDH-ECDSA or ECDHE-ECDSA is enabled.
+ (Note: the hash is computed by `calc_verify()`.)
+
+### `ssl_srv.c`
+
+**Note:** This module is only used server-side.
+
+- In `ssl_parse_supported_elliptic_curves()`
+ call `mbedtls_ecp_curve_info_from_tls_id()`
+ if ECDH, ECDSA or ECJPAKE is enabled.
+
+- In `ssl_parse_supported_point_formats()`
+ call `mbedtls_ecjpake_set_point_format()`
+ if ECJPAKE is enabled.
+
+- In `ssl_parse_ecjpake_kkpp()`
+ call `mbedtls_ecjpake_check()` and `mbedtls_ecjpake_read_round_one()`
+ if ECJPAKE is enabled.
+
+- In `ssl_check_key_curve()` to get group ID
+ call `mbedtls_pk_ec()`
+ if certificates and ECDSA are enabled.
+
+- In `ssl_pick_cert()`
+ call `mbedtls_pk_can_do()`
+ if certificates are enabled.
+
+- In `ssl_write_encrypt_then_mac_ext()`
+ call `mbedtls_cipher_info_from_type()` on ciphersuite info
+ if EtM is enabled
+
+- In `ssl_write_ecjpake_kkpp_ext()`
+ call `mbedtls_ecjpake_write_round_one()`
+ if ECJPAKE is enabled.
+
+- In `ssl_get_ecdh_params_from_cert()`
+ call `mbedtls_pk_can_do()`, `mbedtls_pk_ec()` and `mbedtls_ecdh_get_params()`
+ if ECDH-RSA or ECDH-ECDSA is enabled,
+ in order to import own private key to ecdh context.
+
+- In `ssl_prepare_server_key_exchange()`
+ call `mbedtls_ecjpake_write_round_two()`
+ if ECJPAKE is enabled.
+
+- In `ssl_prepare_server_key_exchange()`
+ call `mbedtls_dhm_set_group()`, `mbedtls_dhm_make_params()` and `mbedtls_dhm_get_len()`
+ if DHE-RSA or DHE-PSK key exchange is enabled.
+
+- In `ssl_prepare_server_key_exchange()`
+ call `mbedtls_ecdh_setup()` and `mbedtls_ecdh_make_params()`
+ if ECDHE-RSA, ECDHE-ECDSA or ECDHE-PSK is enabled.
+
+- In `ssl_prepare_server_key_exchange()`
+ call `mbedtls_pk_sign()` from `ssl_prepare_server_key_exchange()`
+ if DHE-RSA, ECDHE-RSA or ECDHE-ECDSA is enabled.
+
+- In `ssl_parse_client_dh_public()`
+ call `mbedtls_dhm_read_public()`
+ if DHE-RSA or DHE-PSK is enabled.
+
+- In `ssl_decrypt_encrypted_pms()`
+ call `mbedtls_pk_get_len()`, `mbedtls_pk_can_do()` and `mbedtls_pk_decrypt()`
+ if RSA or RSA-PSK key exchange is enabled.
+
+- In `ssl_parse_client_key_exchange()`
+ call `mbedtls_dhm_calc_secret()`
+ if DHE-RSA enabled.
+ (Note: `ssl_parse_client_dh_public()` called first.)
+
+- In `ssl_parse_client_key_exchange()`
+ call `mbedtls_ecdh_read_public()` and `mbedtls_ecdh_calc_secret()`
+ if ECDHE-RSA, ECDHE-ECDSA, ECDH-RSA or ECDH-ECDSA enabled.
+
+- In `ssl_parse_client_key_exchange()`
+ call `mbedtls_ecdh_read_public()`
+ if ECDHE-PSK enabled.
+ (Note: calling `mbedtls_ssl_psk_derive_premaster()` afterwards.)
+
+- In `ssl_parse_client_key_exchange()`
+ call `mbedtls_ecjpake_read_round_two()` and `mbedtls_ecjpake_derive_secret()`
+ if ECJPAKE enabled.
+
+- In `ssl_parse_certificate_verify()`
+ call `mbedtls_pk_can_do()` and `mbedtls_pk_verify()`
+ if RSA, DHE-RSA, ECDH-RSA, ECDHE-RSA, ECDH-ECDSA or ECDHE-ECDSA enabled.
+
+### `ssl_tls.c`
+
+**Note:** This module is used both server-side and client-side.
+
+- In `tls_prf_generic()`
+ call `mbedtls_md_init()`, `mbedtls_md_info_from_type()`, `mbedtls_md_get_size()`, `mbedtls_md_setup()`, `mbedtls_md_hmac_starts()`, `mbedtls_md_hmac_update()`, `mbedtls_md_hmac_finish()`, `mbedtls_md_hmac_reset()` and `mbedtls_md_free()`
+
+- In `mbedtls_ssl_derive_keys()`
+ call `mbedtls_cipher_info_from_type()`, `mbedtls_cipher_setup_psa()` or `mbedtls_cipher_setup()`, `mbedtls_cipher_setkey()`, and `mbedtls_cipher_set_padding_mode()`
+
+- In `mbedtls_ssl_derive_keys()`.
+ call `mbedtls_md_info_from_type()`, `mbedtls_md_setup()`, `mbedtls_md_get_size()` and `mbedtls_md_hmac_starts()`
+ Note: should be only if CBC/NULL ciphersuites enabled, but is currently unconditional.
+
+- In `ssl_calc_verify_tls_sha256()`
+ call `mbedtls_sha256_init()` `mbedtls_sha256_clone()` `mbedtls_sha256_finish()` `mbedtls_sha256_free()`
+ if SHA256 is enabled.
+
+- In `ssl_calc_verify_tls_sha384()`
+ call `mbedtls_sha512_init()` `mbedtls_sha512_clone()` `mbedtls_sha512_finish()` `mbedtls_sha512_free()`
+ if SHA512 is enabled.
+
+- In `mbedtls_ssl_psk_derive_premaster()`
+ call `mbedtls_dhm_calc_secret()`
+ if DHE-PSK is enabled.
+
+- In `mbedtls_ssl_psk_derive_premaster()`
+ call `mbedtls_ecdh_calc_secret()`
+ if ECDHE-PSK is enabled.
+
+- In `ssl_encrypt_buf()`
+ call `mbedtls_cipher_get_cipher_mode()` `mbedtls_md_hmac_update()` `mbedtls_md_hmac_finish()` `mbedtls_md_hmac_reset()` `mbedtls_cipher_crypt()`
+ if CBC or NULL is enabled.
+
+- In `ssl_encrypt_buf()`
+ call `mbedtls_cipher_get_cipher_mode()`, `mbedtls_cipher_auth_encrypt()`
+ if GCM, CCM or CHACHAPOLY is enabled.
+
+- In `ssl_decrypt_buf()`
+ call `mbedtls_cipher_get_cipher_mode()` `mbedtls_md_hmac_update()` `mbedtls_md_hmac_finish()` `mbedtls_md_hmac_reset()` `mbedtls_cipher_crypt()`
+ if CBC and Encrypt-then-Mac
+are enabled.
+
+- In `mbedtls_ssl_cf_hmac()`
+ call `mbedtls_md_clone()`
+ if CBC or NULL is enabled.
+
+- In `ssl_decrypt_buf()`
+ call `mbedtls_cipher_get_cipher_mode()`, `mbedtls_cipher_auth_decrypt()`
+ if GCM, CCM or CHACHAPOLY is enabled.
+
+- In `mbedtls_ssl_parse_certificate()`
+ call `mbedtls_pk_can_do()` and `mbedtls_pk_ec()`
+ to get and check group ID.
+
+- In `mbedtls_ssl_reset_checksum()`.
+ call `mbedtls_sha256_starts()` `mbedtls_sha512_starts()`
+
+- In `ssl_update_checksum_start()`.
+ call `mbedtls_sha256_update()` `mbedtls_sha512_update()`
+
+- In `ssl_update_checksum_sha256()`
+ call `mbedtls_sha256_update()`
+ if SHA256 is enabled.
+
+- In `ssl_update_checksum_sha512()`
+ call `mbedtls_sha512_update()`
+ if SHA512 is enabled.
+
+- In `ssl_calc_finished_tls_sha256()`
+ call `mbedtls_sha256_init()` `mbedtls_sha256_clone()` `mbedtls_sha256_finish()` `mbedtls_sha256_free()`
+ if SHA256 is enabled.
+
+- In `ssl_calc_finished_tls_sha512()`
+ call `mbedtls_sha512_init()` `mbedtls_sha512_clone()` `mbedtls_sha512_finish()` `mbedtls_sha512_free()`
+ if SHA512 is enabled.
+
+- In `ssl_handshake_params_init()`.
+ call `mbedtls_sha256_init()` `mbedtls_sha256_starts()` `mbedtls_sha512_init()` `mbedtls_sha512_starts()` `mbedtls_dhm_init()` `mbedtls_ecdh_init()` `mbedtls_ecjpake_init()`
+
+- In `ssl_transform_init()`.
+ call `mbedtls_cipher_init()` `mbedtls_md_init()`
+
+- In `mbedtls_ssl_set_hs_ecjpake_password()`
+ call `mbedtls_ecjpake_setup()`
+ if ECJPAKE is enabled.
+
+- In `mbedtls_ssl_conf_dh_param_bin()`
+ call `mbedtls_mpi_read_binary()` and `mbedtls_mpi_free()`
+ if DHM and SRV are enabled.
+
+- In `mbedtls_ssl_conf_dh_param_ctx()`
+ call `mbedtls_dhm_get_value()` and `mbedtls_mpi_free()`
+ if DHM and SRV are enabled.
+
+- In `mbedtls_ssl_get_record_expansion()`.
+ call `mbedtls_cipher_get_cipher_mode()` and `mbedtls_cipher_get_block_size()`
+
+- In `mbedtls_ssl_transform_free()`.
+ call `mbedtls_cipher_free()` and `mbedtls_md_free()`
+
+- In `mbedtls_ssl_handshake_free()`.
+ call `mbedtls_sha256_free()` `mbedtls_sha512_free()` `mbedtls_dhm_free()` `mbedtls_ecdh_free()` `mbedtls_ecjpake_free()`
+
+- In `mbedtls_ssl_config_free()`
+ call `mbedtls_mpi_free()`
+ if DHM is enabled.
+
+- In `mbedtls_ssl_sig_from_pk()`.
+ call `mbedtls_pk_can_do()`
+
+- In `mbedtls_ssl_get_key_exchange_md_tls1_2()`
+ call `mbedtls_md_info_from_type()` `mbedtls_md_get_size()` `mbedtls_md_init()` `mbedtls_md_setup()` `mbedtls_md_starts()` `mbedtls_md_update()` `mbedtls_md_update()` `mbedtls_md_finish()` `mbedtls_md_free()`
diff --git a/docs/architecture/psa-migration/dependencies-x509.md b/docs/architecture/psa-migration/dependencies-x509.md
new file mode 100644
index 0000000..dfbff83
--- /dev/null
+++ b/docs/architecture/psa-migration/dependencies-x509.md
@@ -0,0 +1,206 @@
+Dependencies of the X.509 library on the Crypto library
+=======================================================
+
+This document is part of the technical study on how to port Mbed TLS to PSA
+Crypto. It describes the dependencies of libmbedx509.a on libmbedcrypto.a.
+
+More precisely, it describes what functions from libmbedcrypto.a are called
+from libmbedx509.a - other forms of dependencies such as using static inline
+functions or types, accessing private struct members, etc., are not listed.
+
+It is based on Mbed TLS 3.0, excluding support for restartble ECP operations.
+
+Non-Crypto dependencies
+-----------------------
+
+The X.509 library has a number of dependencies on libmbedcrypto.a that are not
+cryptographic, hence are unlikely to be covered by the PSA Crypto API.
+
+These involve the following modules:
+
+- asn1
+- oid
+- pem
+- platform
+- threading
+
+Crypto dependencies (high-level)
+--------------------------------
+
+The X.509 library depends on the following cryptographic modules:
+
+- pk
+- md
+- mpi
+- sha1
+
+More specifically, calls are made to the following API functions:
+
+```
+mbedtls_pk_can_do
+mbedtls_pk_free
+mbedtls_pk_get_bitlen
+mbedtls_pk_get_name
+mbedtls_pk_get_type
+mbedtls_pk_load_file
+mbedtls_pk_parse_subpubkey
+mbedtls_pk_sign
+mbedtls_pk_verify_ext
+mbedtls_pk_write_pubkey
+mbedtls_pk_write_pubkey_der
+
+mbedtls_md
+mbedtls_md_get_name
+mbedtls_md_get_size
+mbedtls_md_info_from_type
+
+mbedtls_mpi_copy
+mbedtls_mpi_free
+mbedtls_mpi_init
+
+mbedtls_sha1
+```
+
+Note: the dependency on MPI is because the certificate's serial number is
+stored as an MPI in `struct mbedtls_x509write_cert` - the MPI is used purely
+as a container for bytes. The depencency is embedded in the public API as
+`mbedtls_x509write_crt_set_serial` take an argument of type `mbedtls_mpi *`.
+
+Note: the direct dependency on SHA1 is in `x509write_crt.c` and makes sense
+because it's the only hash that can be used to compute key identifiers for the
+Subject Key Identifier and Authority Key Identifier extensions. Replacing that
+with an algorithm-agnistic API would or course be easy.
+
+File by file analysis
+---------------------
+
+The X.509 library consists of the following C files and associated headers:
+```
+x509.c
+x509_create.c
+x509_crl.c
+x509_crt.c
+x509_csr.c
+x509write_crt.c
+x509write_csr.c
+```
+
+### `x509.c`
+
+- In `mbedtls_x509_sig_alg_gets()`
+ call `mbedtls_md_info_from_type()` and `mbedtls_md_get_name()`
+ to print out information
+
+### `x509_crl.c`
+
+- In `mbedtls_x509_crl_parse_file()`
+ call `mbedtls_pk_load_file()`
+ to load files if `MBEDTLS_FS_IO` defined
+
+### `x509_crt.c`
+
+**Note:** All calls to PK APIs in this file use public (not private) keys.
+
+- In `x509_profile_check_key()`
+ call `mbedtls_pk_get_type()` and `mbedtls_pk_get_bitlen()`
+
+- In `x509_profile_check_key()`
+ call `mbedtls_pk_ec()`
+ to get the group id
+
+- In `x509_crt_parse_der_core()`
+ call `mbedtls_pk_parse_subpubkey()`
+
+- In `mbedtls_x509_crt_parse_file()`
+ call `mbedtls_pk_load_file()`
+ to load files if `MBEDTLS_FS_IO` defined
+
+- In `mbedtls_x509_crt_info()`
+ call `mbedtls_pk_get_name()` and `mbedtls_pk_get_bitlen()`
+ to print out information
+
+- In `x509_crt_verifycrl()`
+ call `mbedtls_md_info_from_type()`, `mbedtls_md()`, `mbedtls_pk_verify_ext()` and `mbedtls_md_get_size()`
+ to verify CRL signature
+
+- In `x509_crt_check_signature()`
+ call `mbedtls_md_info_from_type()`, `mbedtls_md_get_size()`, `mbedtls_md()`, then `mbedtls_pk_can_do()` and `mbedtls_pk_verify_ext()`
+ to verify certificate signature
+
+- In `x509_crt_verify_restartable_ca_cb()`
+ call `mbedtls_pk_get_type()`
+ to check against profile
+
+- In `mbedtls_x509_crt_free()`
+ call `mbedtls_pk_free()`
+
+### `x509_csr.c`
+
+**Note:** All calls to PK APIs in this file use public (not private) keys.
+
+- In `mbedtls_x509_csr_parse_der()`
+ call `mbedtls_pk_parse_subpubkey()`
+
+- In `mbedtls_x509_csr_parse_file()`
+ call `mbedtls_pk_load_file()`
+ to load files if `MBEDTLS_FS_IO` defined
+
+- In `mbedtls_x509_csr_info()`
+ call `mbedtls_pk_get_name()` and `mbedtls_pk_get_bitlen()`
+ to print out information
+
+- In `mbedtls_x509_csr_free()`
+ call `mbedtls_pk_free()`
+
+### `x509_create.c`
+
+No call to crypto functions - mostly ASN.1 writing and data conversion.
+
+### `x509write_crt.c`
+
+**Note:** Calls to PK APIs in this file are both on public and private keys.
+
+- In `mbedtls_x509write_crt_init()`, resp. `mbedtls_x509write_crt_free()`
+ call `mbedtls_mpi_init()`, resp. `mbedtls_mpi_free()`
+ to manage the serial number
+
+- In `mbedtls_x509write_crt_set_serial()`
+ call `mbedtls_mpi_copy()`
+
+- In `mbedtls_x509write_crt_set_subject_key_identifier()` and `mbedtls_x509write_crt_set_authority_key_identifier()`
+ call `mbedtls_pk_write_pubkey()` and `mbedtls_sha1_ret()`
+
+- In `mbedtls_x509write_crt_der()`
+ call `mbedtls_pk_can_do()`
+ on a private key (issuer)
+ to write out correct signature algorithm
+
+- In `mbedtls_x509write_crt_der()`
+ call `mbedtls_pk_write_pubkey_der()`
+ on a public key (subject)
+
+- In `mbedtls_x509write_crt_der()`
+ call `mbedtls_md_info_from_type()` and `mbedtls_md()`
+ to prepare for signing
+
+- In `mbedtls_x509write_crt_der()`
+ call `mbedtls_pk_sign()`
+ on a private key (issuer)
+ to sign certificate being issued
+
+### `x509write_csr.c`
+
+**Note:** All calls for PK APIs in this file are on private (not public) keys
+
+- In `mbedtls_x509write_csr_der()`
+ call `mbedtls_pk_write_pubkey_der()`
+
+- In `mbedtls_x509write_csr_der()`
+ call `mbedtls_md_info_from_type()` and `mbedtls_md()`
+
+- In `mbedtls_x509write_csr_der()`
+ call `mbedtls_pk_sign()`
+
+- Call `mbedtls_pk_can_do()`
+ on a private key (writer's)
+ to write out correct signature algorithm
diff --git a/docs/architecture/psa-migration/syms.sh b/docs/architecture/psa-migration/syms.sh
new file mode 100755
index 0000000..5c34b28
--- /dev/null
+++ b/docs/architecture/psa-migration/syms.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+#
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Purpose
+#
+# Show symbols in the X.509 and TLS libraries that are defined in another
+# libmbedtlsXXX.a library. This is usually done to list Crypto dependencies.
+#
+# Usage:
+# - build the library with debug symbols and the config you're interested in
+# (default, full minus MBEDTLS_USE_PSA_CRYPTO, full, etc.)
+# - run this script with the name of your config as the only argument
+
+set -eu
+
+# list mbedtls_ symbols of a given type in a static library
+syms() {
+ TYPE="$1"
+ FILE="$2"
+
+ nm "$FILE" | sed -n "s/[0-9a-f ]*${TYPE} \(mbedtls_.*\)/\1/p" | sort -u
+}
+
+# create listings for the given library
+list() {
+ NAME="$1"
+ FILE="library/libmbed${NAME}.a"
+ PREF="${CONFIG}-$NAME"
+
+ syms '[TRrD]' $FILE > ${PREF}-defined
+ syms U $FILE > ${PREF}-unresolved
+
+ diff ${PREF}-defined ${PREF}-unresolved \
+ | sed -n 's/^> //p' > ${PREF}-external
+ sed 's/mbedtls_\([^_]*\).*/\1/' ${PREF}-external \
+ | uniq -c | sort -rn > ${PREF}-modules
+
+ rm ${PREF}-defined ${PREF}-unresolved
+}
+
+CONFIG="${1:-unknown}"
+
+list x509
+list tls