blob: 184dcef4e5f5fb30e9b0f251e407c9ef38420356 [file] [log] [blame] [view]
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001# Transitioning to the PSA API
2
3> I have code written for `mbedtls_` cryptography APIs. How do I migrate to `psa_` APIs?
4
5## Introduction
6
7Mbed TLS is gradually moving from legacy `mbedtls_xxx` APIs to newer `psa_xxx` APIs for cryptography. Note that this only concerns cryptography APIs, not X.509 or SSL/TLS APIs.
8
9This guide is intended to help migrate existing applications that use Mbed TLS for cryptography. It aims to cover common use cases, but cannot cover all possible scenarios.
10
11### Suggested reading
12
13This document is long, but you probably don't need to read all of it. You should start with the following sections:
14
151. [Where can I find documentation?](#where-can-i-find-documentation)
162. [General considerations](#general-considerations)
17
18Then use the [summary of API modules](#summary-of-api-modules), the table of contents or a text search to locate the sections that interest you, based on what legacy interfaces your code is currently using.
19
20### Where can I find documentation?
21
22**Tutorial**: See the [getting started guide](https://mbed-tls.readthedocs.io/en/latest/getting_started/psa/).
23
24**Reference**: The [PSA Crypto API specification](https://arm-software.github.io/psa-api/crypto/) is available online. Mbed TLS implements a large subset of the specification which is documented in the [`psa/crypto*.h` headers](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto_8h/).
25
26### Additional resources
27
28* [Mbed TLS open issues](https://github.com/Mbed-TLS/mbedtls/issues)
29* [PSA API open issues](https://github.com/ARM-software/psa-api/issues) (not just cryptography APIs)
30* [Mbed TLS mailing list](https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org/)
31
32### Why change the API?
33
34* Mbed TLS APIs are traditionally very transparent: the caller can access internal fields of operations. This is less true in the 3.x major version than before, but still the case to some extent. This offers applications some flexibility, but it removes flexibility from the implementation. For example, it is hard to support hardware acceleration, because the API constrains how the data must be represented. PSA APIs were designed to be more opaque, giving more freedom to the implementation.
35* Mbed TLS legacy APIs require key material to be present in the application memory. The PSA Crypto API natively supports operations on keys stored in an external [location](https://arm-software.github.io/psa-api/crypto/1.1/api/keys/lifetimes.html#c.psa_key_location_t) (secure enclave, secure element, HSM, etc.).
Gilles Peskinedfe67072023-11-29 21:12:39 +010036* PSA APIs have [consistent conventions](https://arm-software.github.io/psa-api/crypto/1.1/overview/conventions.html#parameter-conventions) which many legacy APIs in Mbed TLS do not follow. For example, many legacy cryptography functions require the caller to know how large an output buffer needs to be based on the selected algorithm, whereas in the PSA API, all buffer arguments have a well-defined size and those sizes are checked.
37* Mbed TLS legacy APIs require passing around a random generator argument where needed. This has historically been problematic with functions that were created without an RNG argument but later needed one as part of a security countermeasure. The PSA crypto subsystem maintains a global random generator, resolving this problem.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020038
39### Migration timeline
40
41* Mbed TLS 2.15.0 (Nov 2018): first release with a draft implementation of the PSA API.
42* Mbed TLS 2.18.0 (Jun 2019): The PSA API is available in the default build.
43* Mbed TLS 3.1.0 (Dec 2021): TLS 1.3 support is the first major feature that requires the PSA API.
44* Mbed TLS 4.0.0 (2024?): X.509 and TLS require the PSA API. Removal of some legacy crypto APIs.
45* Mbed TLS 5.0.0 (??): Removal of the remaining non-PSA crypto APIs.
46
47## General considerations
48
49### Configuration of the PSA subsystem
50
Gilles Peskinedfe67072023-11-29 21:12:39 +010051To make the PSA API available, make sure that the configuration option [`MBEDTLS_PSA_CRYPTO_C`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/mbedtls__config_8h/#c.MBEDTLS_PSA_CRYPTO_C) is enabled. (It is enabled in the default configuration.)
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020052
Gilles Peskine677285a2023-11-28 16:45:50 +010053You should probably enable [`MBEDTLS_USE_PSA_CRYPTO`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/mbedtls__config_8h/#mbedtls__config_8h_1a70fd7b97d5f11170546583f2095942a6) as well (it is disabled by default). This option causes the PK, X.509 and TLS modules to use PSA crypto under the hood. Some functions that facilitate the transition (for example, to convert between metadata encodings or between key representations) are only available when `MBEDTLS_USE_PSA_CRYPTO` is enabled.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020054
Gilles Peskine1097d4e2023-11-30 21:18:10 +010055By default, the PSA crypto API offers a similar set of cryptographic mechanisms as those offered by the legacy API (configured by `MBEDTLS_XXX` macros). The PSA crypto API also has its own configuration mechanism; see “[Cryptographic mechanism availability](#cryptographic-mechanism-availability)”.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020056
57### Header files
58
59Applications only need to include a single header file:
60```
61#include <psa/crypto.h>
62```
63
64### General application layout
65
66Before any cryptographic operation, call [`psa_crypto_init`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__initialization/#group__initialization_1ga2de150803fc2f7dc6101d5af7e921dd9) and check that it succeeds. (A failure indicates an abnormal system state from which most applications cannot recover.)
67
68If you wish to free all resources associated with PSA cryptography, call [`mbedtls_psa_crypto_free`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__extra_8h/#_CPPv423mbedtls_psa_crypto_freev).
69
Gilles Peskinedfe67072023-11-29 21:12:39 +010070The PSA subsystem has an internal random generator. As a consequence, you do not need to instantiate one manually (no need to create an `mbedtls_entropy_context` and an `mbedtls_xxx_drbg_context`).
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020071
72### Error codes
73
Gilles Peskinedfe67072023-11-29 21:12:39 +010074Mbed TLS functions return a status of type `int`: 0 for success (or occasionally a positive value which is the output length), or a negative value `MBEDTLS_ERR_xxx` indicating an error.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020075
76PSA functions return a status of type [`psa_status_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__error/#group__error_1ga05676e70ba5c6a7565aff3c36677c1f9): `PSA_SUCCESS == 0` for success, or a negative value [`PSA_ERROR_xxx`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__error/) indicating an error.
77
78## Summary of API modules
79
80| Header | Function prefix | PSA equivalent |
81| ------ | --------------- | -------------- |
82| `aes.h` | `mbedtls_aes_` | [Symmetric encryption](#symmetric-encryption) |
83| `aria.h` | `mbedtls_aria_` | [Symmetric encryption](#symmetric-encryption) |
Gilles Peskinedbcfc7d2023-11-30 21:04:06 +010084| `asn1.h` | `mbedtls_asn1_` | No change ([PK support interface](#pk-format-support-interfaces)) |
Gilles Peskine2fffc452023-12-04 22:22:07 +010085| `asn1write.h` | `mbedtls_asn1_write_` | No change ([PK support interface](#pk-format-support-interfaces)) |
Gilles Peskinedbcfc7d2023-11-30 21:04:06 +010086| `base64.h` | `mbedtls_base64_` | No change ([PK support interface](#pk-format-support-interfaces)) |
Gilles Peskine3ea22dc2023-11-30 21:07:24 +010087| `bignum.h` | `mbedtls_mpi_` | None (no low-level arithmetic) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020088| `build_info.h` | `MBEDTLS_` | No change (not a crypto API) |
89| `camellia.h` | `mbedtls_camellia_` | [Symmetric encryption](#symmetric-encryption) |
90| `ccm.h` | `mbedtls_ccm_` | [Symmetric encryption](#symmetric-encryption), [Authenticated cipher operations](#authenticated-cipher-operations) |
91| `chacha20.h` | `mbedtls_chacha20_` | [Symmetric encryption](#symmetric-encryption) |
Gilles Peskine3ea22dc2023-11-30 21:07:24 +010092| `chachapoly.h` | `mbedtls_chachapoly_` | [Symmetric encryption](#symmetric-encryption), [Authenticated cipher operations](#authenticated-cipher-operations) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020093| `check_config.h` | N/A | No public APIs (internal support header) |
94| `cipher.h` | `mbedtls_cipher_` | [Symmetric encryption](#symmetric-encryption) |
Gilles Peskine3ea22dc2023-11-30 21:07:24 +010095| `cmac.h` | `mbedtls_cipher_cmac_` | [Hashes and MAC](#hashes-and-mac), [MAC calculation](#mac-calculation) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020096| `compat-2.x.h` | various | None (transitional APIs) |
97| `config_psa.h` | N/A | No public APIs (internal support header) |
Gilles Peskine3ea22dc2023-11-30 21:07:24 +010098| `constant_time.h` | `mbedtls_ct_` | [Constant-time functions](#constant-time-functions) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +020099| `ctr_drbg.h` | `mbedtls_ctr_drbg_` | [Random generation interface](#random-generation-interface), [Deterministic pseudorandom generation](#deterministic-pseudorandom-generation) |
100| `debug.h` | `mbedtls_debug_` | No change (not a crypto API) |
101| `des.h` | `mbedtls_des_` | [Symmetric encryption](#symmetric-encryption) |
102| `dhm.h` | `mbedtls_dhm_` | [Asymmetric cryptography](#asymmetric-cryptography) |
103| `ecdh.h` | `mbedtls_ecdh_` | [Asymmetric cryptography](#asymmetric-cryptography) |
104| `ecdsa.h` | `mbedtls_ecdsa_` | [Asymmetric cryptography](#asymmetric-cryptography) |
105| `ecjpake.h` | `mbedtls_ecjpake_` | [EC-JPAKE](#ec-jpake) |
106| `ecp.h` | `mbedtls_ecp_` | [Asymmetric cryptography](#asymmetric-cryptography) |
107| `entropy.h` | `mbedtls_entropy_` | [Random generation interface](#random-generation-interface), [Entropy sources](#entropy-sources) |
Gilles Peskine3ea22dc2023-11-30 21:07:24 +0100108| `error.h` | `mbedtls_*err*` | [Error messages](#error-messages) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200109| `gcm.h` | `mbedtls_gcm_` | [Symmetric encryption](#symmetric-encryption), [Authenticated cipher operations](#authenticated-cipher-operations) |
110| `hkdf.h` | `mbedtls_hkdf_` | [HKDF](#hkdf) |
111| `hmac_drbg.h` | `mbedtls_hmac_drbg_` | [Random generation interface](#random-generation-interface), [Deterministic pseudorandom generation](#deterministic-pseudorandom-generation) |
Gilles Peskinedbcfc7d2023-11-30 21:04:06 +0100112| `lms.h` | `mbedtls_lms_` | No change ([LMS signatures](#lms-signatures)) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200113| `mbedtls_config.h` | `MBEDTLS_` | [Compile-time configuration](#compile-time-configuration) |
114| `md.h` | `mbedtls_md_` | [Hashes and MAC](#hashes-and-mac) |
115| `md5.h` | `mbedtls_md5_` | [Hashes and MAC](#hashes-and-mac) |
116| `memory_buffer_alloc.h` | `mbedtls_memory_buffer_alloc_` | No change (not a crypto API) |
117| `net_sockets.h` | `mbedtls_net_` | No change (not a crypto API) |
Gilles Peskinedbcfc7d2023-11-30 21:04:06 +0100118| `nist_kw.h` | `mbedtls_nist_kw_` | Migration path not yet defined |
119| `oid.h` | `mbedtls_oid_` | No change ([PK support interface](#pk-format-support-interfaces)) |
120| `pem.h` | `mbedtls_pem_` | No change ([PK support interface](#pk-format-support-interfaces)) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200121| `pk.h` | `mbedtls_pk_` | [Asymmetric cryptography](#asymmetric-cryptography) |
122| `pkcs5.h` | `mbedtls_pkcs5_` | [PKCS#5 module](#pkcs5-module) |
123| `pkcs7.h` | `mbedtls_pkcs7_` | No change (not a crypto API) |
124| `pkcs12.h` | `mbedtls_pkcs12_` | [PKCS#12 module](#pkcs12-module) |
125| `platform.h` | `mbedtls_platform_` | No change (not a crypto API) |
Gilles Peskine3ea22dc2023-11-30 21:07:24 +0100126| `platform_time.h` | `mbedtls_*time*` | No change (not a crypto API) |
127| `platform_util.h` | `mbedtls_platform_` | No change (not a crypto API) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200128| `poly1305.h` | `mbedtls_poly1305_` | None (but there is Chacha20-Poly1305 [AEAD](#symmetric-encryption)) |
129| `private_access.h` | N/A | No public APIs (internal support header) |
Gilles Peskine3ea22dc2023-11-30 21:07:24 +0100130| `psa_util.h` | N/A | No public APIs (internal support header) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200131| `ripemd160.h` | `mbedtls_ripemd160_` | [Hashes and MAC](#hashes-and-mac) |
132| `rsa.h` | `mbedtls_rsa_` | [Asymmetric cryptography](#asymmetric-cryptography) |
133| `sha1.h` | `mbedtls_sha1_` | [Hashes and MAC](#hashes-and-mac) |
134| `sha3.h` | `mbedtls_sha3_` | [Hashes and MAC](#hashes-and-mac) |
135| `sha256.h` | `mbedtls_sha256_` | [Hashes and MAC](#hashes-and-mac) |
136| `sha512.h` | `mbedtls_sha512_` | [Hashes and MAC](#hashes-and-mac) |
137| `ssl.h` | `mbedtls_ssl_` | No change (not a crypto API) |
138| `ssl_cache.h` | `mbedtls_ssl_cache_` | No change (not a crypto API) |
Gilles Peskine3ea22dc2023-11-30 21:07:24 +0100139| `ssl_ciphersuites.h` | `mbedtls_ssl_ciphersuite_` | No change (not a crypto API) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200140| `ssl_cookie.h` | `mbedtls_ssl_cookie_` | No change (not a crypto API) |
141| `ssl_ticket.h` | `mbedtls_ssl_ticket_` | No change (not a crypto API) |
142| `threading.h` | `mbedtls_threading_` | No change (not a crypto API) |
143| `timing.h` | `mbedtls_timing_` | No change (not a crypto API) |
144| `version.h` | `mbedtls_version_` | No change (not a crypto API) |
145| `x509.h` | `mbedtls_x509` | No change (not a crypto API) |
146| `x509_crl.h` | `mbedtls_x509` | No change (not a crypto API) |
147| `x509_crt.h` | `mbedtls_x509` | No change (not a crypto API) |
148| `x509_csr.h` | `mbedtls_x509` | No change (not a crypto API) |
149
150## Compile-time configuration
151
152### Cryptographic mechanism availability
153
154**This section only applies if `MBEDTLS_PSA_CRYPTO_CONFIG` is enabled.** This option is disabled in the default configuration.
155
156When the configuration option [`MBEDTLS_PSA_CRYPTO_CONFIG`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/mbedtls__config_8h/#mbedtls__config_8h_1a5aca5ddcffb586acad82f9aef26db056) is enabled, the cryptographic mechanisms available through the PSA API are determined by the contents of the header file `"psa/crypto_config.h"`. You can override the file location with the macro [`MBEDTLS_PSA_CRYPTO_CONFIG_FILE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/mbedtls__config_8h/#mbedtls__config_8h_1a25f7e358caa101570cb9519705c2b873), and you can set [`MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/mbedtls__config_8h/#mbedtls__config_8h_1abd1870cc0d2681183a3018a7247cb137) to the path of an additional file (similar to `MBEDTLS_CONFIG_FILE` and `MBEDTLS_USER_CONFIG_FILE` for legacy configuration symbols).
157
158The availability of cryptographic mechanisms in the PSA API is based on a systematic pattern:
159
160* To make `PSA_ALG_aaa` available, enable `PSA_WANT_ALG_aaa`.
Gilles Peskinedfe67072023-11-29 21:12:39 +0100161 For parametrized algorithms, there is a `PSA_WANT_` symbol both for the main macro and for each argument. For example, to make `PSA_ALG_HMAC(PSA_ALG_SHA_256)` available, enable both `PSA_WANT_ALG_HMAC` and `PSA_WANT_ALG_SHA_256`.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200162
163* To make `PSA_KEY_TYPE_ttt` available, enable `PSA_WANT_KEY_TYPE_ttt`.
164
165 As an exception, starting in Mbed TLS 3.5.0, for key pair types, the feature selection is more fine-grained, with an additional suffix:
Gilles Peskinedfe67072023-11-29 21:12:39 +0100166 * `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_BASIC` enables basic support for the key type, and in particular support for operations with a key of that type for enabled algorithms. This is automatically enabled if any of the other `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_yyy` options are enabled.
Gilles Peskinef75e65d2023-06-15 18:39:14 +0200167 * `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_IMPORT` enables support for `psa_import_key` to import a key of that type.
168 * `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_GENERATE` enables support for `psa_generate_key` to randomly generate a key of that type.
169 * `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_DERIVE` enables support for `psa_key_derivation_output_key` to deterministically derive a key of that type.
170 * `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_EXPORT` enables support for `psa_export_key` to export a key of that type.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200171
172 Enabling any support for a key pair type automatically enables support for the corresponding public key type, as well as support for `psa_export_public_key` on the private key.
173
174* To make `PSA_ECC_FAMILY_fff` available for size sss, enable `PSA_WANT_ECC_fff_sss`.
175
Gilles Peskinedfe67072023-11-29 21:12:39 +0100176Note that all `PSA_WANT_xxx` symbols must be set to a non-zero value. In particular, setting `PSA_WANT_xxx` to an empty value may not be handled consistently.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200177
178For example, the following configuration enables hashing with SHA-256, AEAD with AES-GCM, signature with deterministic ECDSA using SHA-256 on the curve secp256r1 using a randomly generated key as well as the corresponding verification, and ECDH key exchange on secp256r1 and Curve25519.
179
180```
181#define PSA_WANT_ALG_SHA_256 1
182
183#define PSA_WANT_KEY_TYPE_AES 1
184#define PSA_WANT_ALG_GCM 1
185
186#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
187// ^^ In Mbed TLS <= 3.4, enable PSA_WANT_KEY_TYPE_ECC_KEY_PAIR instead
Gilles Peskinef75e65d2023-06-15 18:39:14 +0200188// ^^ implicitly enables PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC, PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200189#define PSA_WANT_ECC_SECP_R1_256 1 // secp256r1 (suitable for ECDSA and ECDH)
190#define PSA_WANT_ECC_MONTGOMERY_255 1 // Curve25519 (suitable for ECDH)
191#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1
192#define PSA_WANT_ALG_ECDH
193```
194
Gilles Peskinedfe67072023-11-29 21:12:39 +0100195If a mechanism is not enabled by `PSA_WANT_xxx`, Mbed TLS will normally not include it. This allows builds that use few features to have a small code size. However, this is not guaranteed: a mechanism that is not explicitly requested can be enabled because it is a dependency of another configuration option, because it is used internally, or because the granularity is not fine enough to distinguish between it and another mechanism that is requested.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200196
197Under the hood, `PSA_WANT_xxx` enables the necessary legacy modules. Note that if a mechanism has a PSA accelerator driver, the corresponding legacy module is typically not needed. Thus applications that use a cryptographic mechanism both through the legacy API and through the PSA API need to explicitly enable both the `PSA_WANT_xxx` symbols and the `MBEDTLS_xxx` symbols.
198
Gilles Peskine379ff872023-06-15 21:15:21 +0200199### Optimization options
200
201When PSA Crypto mechanisms are implemented by the built-in code from Mbed TLS, the legacy optimization options (e.g. `MBEDTLS_SHA256_SMALLER`, `MBEDTLS_ECP_WINDOW_SIZE`, etc.) apply to the PSA implementation as well (they invoke the same code under the hood).
202
203The PSA Crypto API may use accelerator drivers. In this case any options controlling the driver behavior are driver-specific.
204
Gilles Peskineb33d0ac2023-06-15 18:33:15 +0200205### Self-tests
206
207There is currently [no PSA equivalent to the self-tests](https://github.com/Mbed-TLS/mbedtls/issues/7781) enabled by `MBEDTLS_SELF_TEST`.
208
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200209## Miscellaneous support modules
210
211### Error messages
212
213At the time of writing, there is no equivalent to the error messages provided by `mbedtls_strerror`. However, you can use the companion program `programs/psa/psa_constant_names` to convert various numbers (`psa_status_t`, `psa_algorithm_t`, `psa_key_type_t`, `psa_ecc_family_t`, `psa_dh_family_t`, `psa_key_usage_t`) to their input representation. The conversion doesn't depend on the library configuration or the target platform, so you can use a native build of this program even if you cross-compile your application.
214
215```
216$ programs/psa/psa_constant_names error -138
217PSA_ERROR_BUFFER_TOO_SMALL
218$ programs/psa/psa_constant_names type 0x7112
219PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)
220$ programs/psa/psa_constant_names alg 0x06000609
221PSA_ALG_ECDSA(PSA_ALG_SHA_256)
222```
223
224The other functions in `error.h` are specific to the construction of Mbed TLS error code and are not relevant to the PSA API. PSA error codes are never the combination of multiple codes.
225
226### Constant-time functions
227
228The PSA API does not have an equivalent to the timing-side-channel-resistance utility functions in `constant_time.h`. Continue using `constant_time.h` as needed.
229
230Note that the PSA API does include features that reduce the need for `mbedtls_ct_memcmp`:
231
Gilles Peskinedfe67072023-11-29 21:12:39 +0100232* To compare a MAC with a reference value, use `psa_mac_verify` rather than `psa_mac_compute` followed by `mbedtls_ct_memcmp`, or use `psa_mac_verify_setup` and `psa_mac_verify_finish` in the multi-part case. See “[MAC calculation](#mac-calculation)”.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200233* The AEAD decryption functions take care of verifying the tag. See “[Authenticated cipher operations](#authenticated-cipher-operations)”.
234
235## Symmetric encryption
236
237All PSA APIs have algorithm agility, where the functions depend only on the nature of the operation and the choice of a specific algorithm comes from an argument. There is no special API for a particular block cipher (`aes.h`, `aria.h`, `camellia.h`, `des.h`), a particular block cipher mode (`ccm.h`, `gcm.h`) or a particular stream cipher (`chacha20.h`, `chachapoly.h`). To migrate code using those low-level modules, please follow the recommendations in the following sections, using the same principles as the corresponding `cipher.h` API.
238
239### Cipher mechanism selection
240
241Instead of `mbedtls_cipher_id_t` (`MBEDTLS_CIPHER_ID_xxx` constants), `mbedtls_cipher_type_t` (`MBEDTLS_CIPHER_base_size_mode` constants), `mbedtls_cipher_mode_t` (`MBEDTLS_CIPHER_MODE_xxx` constants) and `mbedtls_cipher_padding_t` (`MBEDTLS_CIPHER_PADDING_xxx` constants), use the [`PSA_KEY_TYPE_xxx` and `PSA_ALG_xxx` constants](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/).
242
243For modes that are based on a block cipher, the key type encodes the choice of block cipher:
244[`PSA_KEY_TYPE_AES`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga6ee54579dcf278c677eda4bb1a29575e),
245[`PSA_KEY_TYPE_ARIA`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#c.PSA_KEY_TYPE_ARIA),
246[`PSA_KEY_TYPE_CAMELLIA`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gad8e5da742343fd5519f9d8a630c2ed81),
247[`PSA_KEY_TYPE_DES`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga577562bfbbc691c820d55ec308333138).
248The algorithm encodes the mode and if relevant the padding type:
249
250* Unauthenticated cipher modes:
251 [`PSA_ALG_CTR`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gad318309706a769cffdc64e4c7e06b2e9),
252 [`PSA_ALG_CFB`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga0088c933e01d671f263a9a1f177cb5bc),
253 [`PSA_ALG_OFB`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gae96bb421fa634c6fa8f571f0112f1ddb),
254 [`PSA_ALG_XTS`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gaa722c0e426a797fd6d99623f59748125),
255 [`PSA_ALG_ECB_NO_PADDING`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gab8f0609cd0f12cccc9c950fd5a81a0e3),
256 [`PSA_ALG_CBC_NO_PADDING`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gacb332d72716958880ee7f97d8365ae66),
257 [`PSA_ALG_CBC_PKCS7`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gaef50d2e9716eb6d476046608e4e0c78c),
258 [`PSA_ALG_CCM_STAR_NO_TAG`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga89627bb27ec3ce642853ab8554a88572).
259* Other padding modes, which are obsolete, are not available in the PSA API. If you need them, handle the padding in your application code and use the `NO_PADDING` algorithm.
260* AEAD modes:
261 [`PSA_ALG_CCM`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gac2c0e7d21f1b2df5e76bcb4a8f84273c),
262 [`PSA_ALG_GCM`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga0d7d02b15aaae490d38277d99f1c637c).
263* KW/KWP modes are not available in the PSA API at the time of writing.
264
265For the ChaCha20 unauthenticated cipher, use [`PSA_KEY_TYPE_CHACHA20`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga901548883b3bce56cc21c3a22cf8d93c) with [`PSA_ALG_STREAM_CIPHER`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gad98c105198f7428f7d1dffcb2cd398cd).
266For the Chacha20+Poly1305 AEAD, use [`PSA_KEY_TYPE_CHACHA20`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga901548883b3bce56cc21c3a22cf8d93c) with [`PSA_ALG_CHACHA20_POLY1305`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga1fec55093541640a71bdd022d4adfb9c)
267
268### Cipher mechanism availability
269
Gilles Peskinedfe67072023-11-29 21:12:39 +0100270For each key type value `PSA_KEY_TYPE_xxx`, the symbol `PSA_WANT_KEY_TYPE_xxx` is defined with a non-zero value if the library is built with support for that key type. For each algorithm value `PSA_ALG_yyy`, the symbol `PSA_WANT_ALG_yyy` is defined with a non-zero value if the library is built with support for that algorithm. Note that for a mechanism to be supported, both the key type and the algorithm must be supported.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200271
272For example, to test if AES-CBC-PKCS7 is supported, in the legacy API, you could write:
273```
274#if defined(MBEDTLS_AES_C) && \
275 defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_CIPHER_PADDING_PKCS7)
276```
277The equivalent in the PSA API is
278```
279#if PSA_WANT_KEY_TYPE_AES && PSA_WANT_ALG_CBC_PKCS7
280```
281
282### Cipher metadata
283
284Both APIs express key sizes in bits. Note however that in the PSA API, the size of a _buffer_ is always expressed in bytes, even if that buffer contains a key.
285
286The following table lists corresponding PSA macros for maximum-size macros that take all supported algorithms into account.
287
288| Legacy macro | PSA macro |
289| ------------ | --------- |
290| `MBEDTLS_MAX_IV_LENGTH` | [`PSA_CIPHER_IV_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_IV_MAX_SIZE), [`PSA_AEAD_NONCE_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#crypto__sizes_8h_1ac2a332765ba4ccfc24935d6f7f48fcc7) |
291| `MBEDTLS_MAX_BLOCK_LENGTH` | [`PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) |
292| `MBEDTLS_MAX_KEY_LENGTH` | no equivalent|
293
294There is no equivalent to the type `mbedtls_cipher_info_t` and the functions `mbedtls_cipher_info_from_type` and `mbedtls_cipher_info_from_values` in the PSA API because it is unnecessary. All macros and functions operate directly on key type values (`psa_key_type_t`, `PSA_KEY_TYPE_xxx` constants) and algorithm values (`psa_algorithm_t`, `PSA_ALG_xxx` constants).
295
296| Legacy function | PSA macro |
297| --------------- | --------- |
298| `mbedtls_cipher_info_get_iv_size` | [`PSA_CIPHER_IV_LENGTH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_IV_LENGTH), [`PSA_AEAD_NONCE_LENGTH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_NONCE_LENGTH) |
299| `mbedtls_cipher_info_get_block_size` | not available (use specific macros for the IV, nonce or tag length) |
300
301The following features have no PSA equivalent:
302
303* `mbedtls_cipher_list`: the PSA API does not currently have a discovery mechanism for cryptographic mechanisms, but one may be added in the future.
304* `mbedtls_cipher_info_has_variable_key_bitlen`, `mbedtls_cipher_info_has_variable_iv_size`: the PSA API does not currently have such mechanism for high-level metadata information.
305* `mbedtls_cipher_info_from_string`: there is no equivalent of Mbed TLS's lookup based on a (nonstandard) name.
306
307### Cipher key management
308
309The legacy API and the PSA API have a different organization of operations in several respects:
310
311* In the legacy API, each operation object contains the necessary key material. In the PSA API, an operation object contains a reference to a key object. To perform a cryptographic operation, you must create a key object first. However, for a one-shot operation, you do not need an operation object, just a single function call.
312* The legacy API uses the same interface for authenticated and non-authenticated ciphers, while the PSA API has separate functions.
313* The legacy API uses the same functions for encryption and decryption, while the PSA API has separate functions where applicable.
314
315Here is an overview of the lifecycle of a key object.
316
3171. First define the attributes of the key by filling a [`psa_key_attributes_t` structure](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga0ec645e1fdafe59d591104451ebf5680). You need to set the following parameters:
318 * Call [`psa_set_key_type`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga6857ef0ecb3fa844d4536939d9c64025) to set the key type to the desired `PSA_KEY_TYPE_xxx` value (see “[Cipher mechanism selection](#cipher-mechanism-selection)”).
319 * Call [`psa_set_key_bits`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaf61683ac87f87687a40262b5afbfa018) to set the key's size in bits. This is optional with `psa_import_key`, which determines the key size from the length of the key material.
320 * Call [`psa_set_key_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaeb8341ca52baa0279475ea3fd3bcdc98) to set the algorithm to the desired `PSA_ALG_xxx` value (see “[Cipher mechanism selection](#cipher-mechanism-selection)”). By design, the same key cannot be used with multiple algorithms.
321 * Call [`psa_set_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga42a65b3c4522ce9b67ea5ea7720e17de) to enable at least [`PSA_KEY_USAGE_ENCRYPT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#c.PSA_KEY_USAGE_ENCRYPT) or [`PSA_KEY_USAGE_DECRYPT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#c.PSA_KEY_USAGE_DECRYPT), depending on which direction you want to use the key in. To allow both directions, use the flag mask `PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT`. The same policy flags cover authenticated and non-authenticated encryption/decryption.
3222. Call one of the key creation functions, passing the attributes defined in the previous step, to get an identifier of type [`psa_key_id_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__types_8h/#_CPPv412psa_key_id_t) to the key object.
323 * Use [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b) to directly import key material.
324 * If the key is randomly generated, use [`psa_generate_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga1985eae417dfbccedf50d5fff54ea8c5).
325 * If the key is derived from other material (for example from a key exchange), use the [key derivation interface](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/) and create the key with [`psa_key_derivation_output_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gada7a6e17222ea9e7a6be6864a00316e1).
3263. Call the functions in the following sections to perform operations on the key. The same key object can be used in multiple operations.
3274. To free the resources used by the key object, call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) after all operations with that key are finished.
328
329### Unauthenticated cipher operations
330
Gilles Peskine5eeca332023-12-04 22:35:12 +0100331Recall the workflow of an unauthenticated cipher operation in the legacy Mbed TLS cipher API:
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200332
3331. Create a cipher context of type `mbedtls_cipher_context_t` and initialize it with `mbedtls_cipher_init`.
3342. Establish the operation parameters (algorithm, key, mode) with `mbedtls_cipher_setup`, `mbedtls_cipher_setkey` (or `mbedtls_cipher_setup_psa`), `mbedtls_cipher_set_padding_mode` if applicable.
3353. Set the IV with `mbedtls_cipher_set_iv` (except for ECB which does not use an IV).
3364. For a one-shot operation, call `mbedtls_cipher_crypt`. To pass the input in multiple parts, call `mbedtls_cipher_update` as many times as necessary followed by `mbedtls_cipher_finish`.
3375. Finally free the resources associated with the operation object by calling `mbedtls_cipher_free`.
338
Gilles Peskine5eeca332023-12-04 22:35:12 +0100339For a one-shot operation (where the whole plaintext or ciphertext is passed as a single input), the equivalent workflow with the PSA API is to call a single function:
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200340
Gilles Peskine4d234f12023-11-30 13:59:49 +0100341* [`psa_cipher_encrypt`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1ga61f02fbfa681c2659546eca52277dbf1) to perform encryption with a random IV of the default size (indicated by [`PSA_CIPHER_IV_LENGTH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_IV_LENGTH)). (To encrypt with a specified IV, use the multi-part API described below.) You can use the macro [`PSA_CIPHER_ENCRYPT_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_ENCRYPT_OUTPUT_SIZE) or [`PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200342* [`psa_cipher_decrypt`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1gab3593f5f14d8c0431dd306d80929215e) to perform decryption with a specified IV. You can use the macro [`PSA_CIPHER_DECRYPT_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_DECRYPT_OUTPUT_SIZE) or [`PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
343
Gilles Peskine5eeca332023-12-04 22:35:12 +0100344For a multi-part operation, the equivalent workflow with the PSA API is as follows:
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200345
3461. Create an operation object of type [`psa_cipher_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1ga1399de29db657e3737bb09927aae51fa) and zero-initialize it (or use the corresponding `INIT` macro).
3472. Select the key and algorithm with [`psa_cipher_encrypt_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1ga587374c0eb8137a572f8e2fc409bb2b4) or [`psa_cipher_decrypt_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1gaa4ba3a167066eaef2ea49abc5dcd1d4b) depending on the desired direction.
3483. When encrypting with a random IV, use [`psa_cipher_generate_iv`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1ga29fd7d32a5729226a2f73e7b6487bd8a). When encrypting with a chosen IV, or when decrypting, set the IV with [`psa_cipher_set_iv`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1ga9caddac1a429a5032d6d4a907fb70ba1). Skip this step with ECB since it does not use an IV.
3494. Call [`psa_cipher_update`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1gac3ca27ac6682917c48247d01fd96cd0f) as many times as needed. You can use [`PSA_CIPHER_UPDATE_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_UPDATE_OUTPUT_SIZE) or [`PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#crypto__sizes_8h_1ab1f6598efd6a7dc56e7ad7e34719eb32) to determine the size of the output buffer.
3505. Call [`psa_cipher_finish`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1ga1dcb58b8befe23f8a4d7a1d49c99249b) to obtain the last part of the output. You can use [`PSA_CIPHER_FINISH_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_FINISH_OUTPUT_SIZE) or [`PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
351
352If you need to interrupt the operation after calling the setup function without calling the finish function, call [`psa_cipher_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1gaad482cdca2098bca0620596aaa02eaa4).
353
354### Authenticated cipher operations
355
Gilles Peskine5eeca332023-12-04 22:35:12 +0100356Recall the workflow of an authenticated cipher operation in the legacy Mbed TLS cipher API (or similar workflows in the `chachapoly`, `ccm` and `gcm` modules):
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200357
3581. Create a cipher context of type `mbedtls_cipher_context_t` and initialize it with `mbedtls_cipher_init`.
3592. Establish the operation parameters (algorithm, key, mode) with `mbedtls_cipher_setup`, `mbedtls_cipher_setkey` (or `mbedtls_cipher_setup_psa`), `mbedtls_cipher_set_padding_mode` if applicable.
3603. Set the nonce with `mbedtls_cipher_set_iv` (or the `starts` function for low-level modules). For CCM, which requires direct use of the `ccm` module, also call `mbedtls_ccm_set_lengths` to set the length of the additional data and of the plaintext.
3614. Call `mbedtls_cipher_update_ad` to pass the unencrypted additional data.
3625. Call `mbedtls_cipher_update` as many times as necessary to pass the input plaintext or ciphertext.
3636. Call `mbedtls_cipher_finish` to obtain the last part of the output. Then call `mbedtls_cipher_write_tag` (when encrypting) or `mbedtls_cipher_check_tag` (when decrypting) to process the authentication tag.
3647. Finally free the resources associated with the operation object by calling `mbedtls_cipher_free`.
365
366Steps 36 can be replaced by a single call to `mbedtls_cipher_auth_encrypt_ext` or `mbedtls_cipher_auth_decrypt_ext` for a one-shot operation (where the whole plaintext or ciphertext is passed as a single input).
367
368For a one-shot operation, the PSA API allows you to call a single function:
369
370* [`psa_aead_encrypt`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1gae72e1eb3c2da3ebd843bb9c8db8df509) to perform authenticated encryption with a random nonce of the default size (indicated by [`PSA_AEAD_NONCE_LENGTH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_NONCE_LENGTH)), with the authentication tag written at the end of the output. (To encrypt with a specified nonce, or to separate the tag from the rest of the ciphertext, use the multi-part API described below.) You can use the macro [`PSA_AEAD_ENCRYPT_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_ENCRYPT_OUTPUT_SIZE) or [`PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
371* [`psa_aead_decrypt`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1gae799f6196a22d50c216c947e0320d3ba) to perform authenticated decryption of a ciphertext with the authentication tag at the end. (If the tag is separate, use the multi-part API described below.) You can use the macro [`PSA_AEAD_DECRYPT_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_DECRYPT_OUTPUT_SIZE) or [`PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
372
Gilles Peskine5eeca332023-12-04 22:35:12 +0100373For a multi-part operation, the equivalent workflow with the PSA API is as follows:
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200374
3751. Create an operation object of type [`psa_aead_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1ga14f6a01afbaa8c5b3d8c5d345cbaa3ed) and zero-initialize it (or use the corresponding `INIT` macro).
3762. Select the key and algorithm with [`psa_aead_encrypt_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1ga2732c40ce8f3619d41359a329e9b46c4) or [`psa_aead_decrypt_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1gaaa5c5018e67a7a6514b7e76b9a14de26) depending on the desired direction.
3773. When encrypting with a random nonce, use [`psa_aead_generate_nonce`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1ga5799df1c555efd35970b65be51cb07d1). When encrypting with a chosen nonce, or when decrypting, set the nonce with [`psa_aead_set_nonce`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1ga59132751a6f843d038924cb217b5e13b). If the algorithm is CCM, you must also call [`psa_aead_set_lengths`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1gad3431e28d05002c2a7b0760610176050) before or after setting the nonce (for other algorithms, this is permitted but not needed).
3784. Call [`psa_aead_update_ad`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1ga6d0eed03f832e5c9c91cb8adf2882569) as many times as needed.
3795. Call [`psa_aead_update`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1gaf6d49864951ca42136b4a9b71ea26e5c) as many times as needed. You can use [`PSA_AEAD_UPDATE_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_UPDATE_OUTPUT_SIZE) or [`PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
3806. Finally:
381 * When encrypting, call [`psa_aead_finish`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1ga759791bbe1763b377c3b5447641f1fc8) to obtain the last part of the ciphertext and the authentication tag. You can use [`PSA_AEAD_FINISH_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_FINISH_OUTPUT_SIZE) or [`PSA_AEAD_FINISH_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_FINISH_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
382 * When decrypting, call [`psa_aead_verify`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1gae0280e2e61a185b893c36d858453f0d0) to obtain the last part of the plaintext and check the authentication tag. You can use [`PSA_AEAD_VERIFY_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_VERIFY_OUTPUT_SIZE) or [`PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
383
384If you need to interrupt the operation after calling the setup function without calling the finish or verify function, call [`psa_aead_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1gae8a5f93d92318c8f592ee9fbb9d36ba0).
385
386### Miscellaneous cipher operation management
387
388The equivalent of `mbedtls_cipher_reset` is to call [`psa_cipher_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__cipher/#group__cipher_1gaad482cdca2098bca0620596aaa02eaa4) or [`psa_aead_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__aead/#group__aead_1gae8a5f93d92318c8f592ee9fbb9d36ba0). Note that you must set the key again with a setup function: the PSA API does not have a special way to reuse an operation object with the same key.
389
390There is no equivalent for the `mbedtls_cipher_get_xxx` functions to extract information from an ongoing PSA cipher or AEAD operation. Applications that need this information will need to save it from the key and operation parameters.
391
392## Hashes and MAC
393
394The PSA API groups functions by purpose rather than by underlying primitive: there is a MAC API (equivalent to `md.h` for HMAC, and `cmac.h` for CMAC) and a hash API (equivalent to `md.h` for hashing). There is no special API for a particular hash algorithm (`md5.h`, `sha1.h`, `sha256.h`, `sha512.h`, `sha3.h`). To migrate code using those low-level modules, please follow the recommendations in the following section, using the same principles as the corresponding `md.h` API.
395
396The PSA API does have a direct interface for the AES-CMAC-PRF-128 from RFC 4615 at the time of writing. You can calculate it using the interface to AES-CMAC.
397
398### Hash mechanism selection
399
400The equivalent to `mbedtls_md_type_t` and `MBEDTLS_MD` constants is the type `psa_algorithm_t` and `PSA_ALG_xxx` constants (the type encompasses all categories of cryptographic algorithms, not just hashes). PSA offers a similar selection of algorithms, but note that SHA-1 and SHA-2 are spelled slightly differently.
401
402| Mbed TLS constant | PSA constant |
403| ---------------------- | ------------------- |
404| `MBEDTLS_MD_MD5` | `PSA_ALG_MD5` |
405| `MBEDTLS_MD_SHA1` | `PSA_ALG_SHA_1` |
406| `MBEDTLS_MD_SHA224` | `PSA_ALG_SHA_224` |
407| `MBEDTLS_MD_SHA256` | `PSA_ALG_SHA_256` |
408| `MBEDTLS_MD_SHA384` | `PSA_ALG_SHA_384` |
409| `MBEDTLS_MD_SHA512` | `PSA_ALG_SHA_512` |
410| `MBEDTLS_MD_RIPEMD160` | `PSA_ALG_RIPEMD160` |
411| `MBEDTLS_MD_SHA3_224` | `PSA_ALG_SHA3_224` |
412| `MBEDTLS_MD_SHA3_256` | `PSA_ALG_SHA3_256` |
413| `MBEDTLS_MD_SHA3_384` | `PSA_ALG_SHA3_384` |
414| `MBEDTLS_MD_SHA3_512` | `PSA_ALG_SHA3_512` |
415
416### MAC mechanism selection
417
418PSA Crypto has a generic API with the same functions for all MAC mechanisms. The mechanism is determined by a combination of an algorithm value of type [`psa_algorithm_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gac2e4d47f1300d73c2f829a6d99252d69) and a key type value of type [`psa_key_type_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga63fce6880ca5933b5d6baa257febf1f6).
419
420* For HMAC, the algorithm is [`PSA_ALG_HMAC`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga70f397425684b3efcde1e0e34c28261f)`(hash)` where `hash` is the underlying hash algorithm (see “[Hash mechanism selection](#hash-mechanism-selection)”),
421 for example `PSA_ALG_HMAC(PSA_ALG_SHA_256)` for HMAC-SHA-256.
422 The key type is [`PSA_KEY_TYPE_HMAC`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__values_8h/#c.PSA_KEY_TYPE_HMAC) regardless of the hash algorithm.
423* For CMAC, the algorithm is [`PSA_ALG_CMAC`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__values_8h/#c.PSA_ALG_CMAC) regardless of the underlying block cipher. The key type determines the block cipher:
424 [`PSA_KEY_TYPE_AES`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga6ee54579dcf278c677eda4bb1a29575e),
425 [`PSA_KEY_TYPE_ARIA`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#c.PSA_KEY_TYPE_ARIA),
426 [`PSA_KEY_TYPE_CAMELLIA`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gad8e5da742343fd5519f9d8a630c2ed81) or
427 [`PSA_KEY_TYPE_DES`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga577562bfbbc691c820d55ec308333138).
428
429### Hash and MAC mechanism availability
430
Gilles Peskinedfe67072023-11-29 21:12:39 +0100431For each key type value `PSA_KEY_TYPE_xxx`, the symbol `PSA_WANT_KEY_TYPE_xxx` is defined with a non-zero value if the library is built with support for that key type. For each algorithm value `PSA_ALG_yyy`, the symbol `PSA_WANT_ALG_yyy` is defined with a non-zero value if the library is built with support for that algorithm. For a compound mechanism, all parts must be supported. In particular, for HMAC, all three of `PSA_WANT_KEY_TYPE_HMAC`, `PSA_WANT_ALG_HMAC` and the underlying hash must be enabled. (A configuration with only one of `PSA_WANT_KEY_TYPE_HMAC` and `PSA_WANT_ALG_HMAC` is technically possible but not useful.)
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200432
433For example, to test if HMAC-SHA-256 is supported, in the legacy API, you could write:
434```
435#if defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C)
436```
437The equivalent in the PSA API is
438```
439#if PSA_WANT_KEY_TYPE_HMAC && PSA_WANT_ALG_HMAC && PSA_WANT_ALG_SHA_256
440```
441
442To test if AES-CMAC is supported, in the legacy API, you could write:
443```
444if defined(MBEDTLS_AES_C) && defined(MBEDTLS_CMAC_C)
445```
446The equivalent in the PSA API is
447```
448#if PSA_WANT_KEY_TYPE_AES && PSA_WANT_ALG_CMAC
449```
450
451### Hash algorithm metadata
452
453There is no equivalent to the type `mbedtls_md_info_t` and the functions `mbedtls_md_info_from_type` and `mbedtls_md_get_type` in the PSA API because it is unnecessary. All macros and functions operate directly on algorithm (`psa_algorithm_t`, `PSA_ALG_xxx` constants).
454
455| Legacy macro | PSA macro |
456| ------------ | --------- |
457| `MBEDTLS_MD_MAX_SIZE` | [`PSA_HASH_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_HASH_MAX_SIZE) |
458| `MBEDTLS_MD_MAX_BLOCK_SIZE` | [`PSA_HMAC_MAX_HASH_BLOCK_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_HMAC_MAX_HASH_BLOCK_SIZE) |
459| `mbedtls_md_get_size` | [`PSA_HASH_LENGTH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_HASH_LENGTH) |
460| `mbedtls_md_get_size_from_type` | [`PSA_HASH_LENGTH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_HASH_LENGTH) |
461
462The following features have no PSA equivalent:
463
464* `mbedtls_md_list`: the PSA API does not currently have a discovery mechanism for cryptographic mechanisms, but one may be added in the future.
465* `mbedtls_md_info_from_ctx`
466* `mbedtls_cipher_info_from_string`, `mbedtls_md_get_name`: there is no equivalent of Mbed TLS's lookup based on a (nonstandard) name.
467
468### Hash calculation
469
470The equivalent of `mbedtls_md` for a one-shot hash calculation is [`psa_hash_compute`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1gac69f7f19d96a56c28cf3799d11b12156). In addition, to compare the hash of a message with an expected value, you can call [`psa_hash_compare`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1ga0c08f4797bec96b886c8c8d7acc2a553) instead of `mbedtls_md` followed by `memcmp` or a constant-time equivalent.
471
472For a multi-part hash calculation, the legacy process is as follows:
473
4741. Create a digest context of type `mbedtls_md_context_t` and initialize it with `mbedtls_md_init`.
4752. Call `mbedtls_md_setup` to select the hash algorithm, with `hmac=0`. Then call `mbedtls_md_starts` to start the hash operation.
4763. Call `mbedtls_md_update` as many times as necessary.
4774. Call `mbedtls_md_finish`. If verifying the hash against an expected value, compare the result with the expected value.
4785. Finally free the resources associated with the operation object by calling `mbedtls_md_free`.
479
480The equivalent process in the PSA API is as follows:
481
4821. Create an operation object of type [`psa_hash_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1ga3c4205d2ce66c4095fc5c78c25273fab) and zero-initialize it (or use the corresponding `INIT` macro).
4832. Call [`psa_hash_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1ga8d72896cf70fc4d514c5c6b978912515) to specify the algorithm.
4843. Call [`psa_hash_update`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1ga65b16ef97d7f650899b7db4b7d1112ff) as many times as necessary.
4854. To obtain the hash, call [`psa_hash_finish`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1ga4795fd06a0067b0adcd92e9627b8c97e). Alternatively, to verify the hash against an expected value, call [`psa_hash_verify`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1ga7be923c5700c9c70ef77ee9b76d1a5c0).
486
487If you need to interrupt the operation after calling the setup function without calling the finish or verify function, call [`psa_hash_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1gab0b4d5f9912a615559497a467b532928).
488
489There is no equivalent to `mbedtls_md_file` in the PSA API. Load the file data and calculate its hash.
490
491### MAC key management
492
493The legacy API and the PSA API have a different organization of operations in several respects:
494
495* In the legacy API, each operation object contains the necessary key material. In the PSA API, an operation object contains a reference to a key object. To perform a cryptographic operation, you must create a key object first. However, for a one-shot operation, you do not need an operation object, just a single function call.
496* The legacy API uses the same interface for authenticated and non-authenticated ciphers, while the PSA API has separate functions.
497* The legacy API uses the same functions for encryption and decryption, while the PSA API has separate functions where applicable.
498
499Here is an overview of the lifecycle of a key object.
500
5011. First define the attributes of the key by filling a [`psa_key_attributes_t` structure](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga0ec645e1fdafe59d591104451ebf5680). You need to set the following parameters:
502 * Call [`psa_set_key_type`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga6857ef0ecb3fa844d4536939d9c64025) to set the key type to the desired `PSA_KEY_TYPE_xxx` value (see “[Cipher mechanism selection](#cipher-mechanism-selection)”).
503 * Call [`psa_set_key_bits`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaf61683ac87f87687a40262b5afbfa018) to set the key's size in bits. This is optional with `psa_import_key`, which determines the key size from the length of the key material.
504 * Call [`psa_set_key_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaeb8341ca52baa0279475ea3fd3bcdc98) to set the algorithm to the desired `PSA_ALG_xxx` value (see “[Cipher mechanism selection](#cipher-mechanism-selection)”). By design, the same key cannot be used with multiple algorithms.
505 * Call [`psa_set_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga42a65b3c4522ce9b67ea5ea7720e17de) to enable at least [`PSA_KEY_USAGE_SIGN_MESSAGE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#c.PSA_KEY_USAGE_SIGN_MESSAGE) to calculate a MAC or [`PSA_KEY_USAGE_VERIFY_MESSAGE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#c.PSA_KEY_USAGE_VERIFY_MESSAGE) to verify the MAC of a message. To allow both directions, use the flag mask `PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE`.
5062. Call one of the key creation functions, passing the attributes defined in the previous step, to get an identifier of type [`psa_key_id_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__types_8h/#_CPPv412psa_key_id_t) to the key object.
507 * Use [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b) to directly import key material.
508 * If the key is randomly generated, use [`psa_generate_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga1985eae417dfbccedf50d5fff54ea8c5).
509 * If the key is derived from other material (for example from a key exchange), use the [key derivation interface](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/) and create the key with [`psa_key_derivation_output_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gada7a6e17222ea9e7a6be6864a00316e1).
5103. Call the functions in the following sections to perform operations on the key. The same key object can be used in multiple operations.
5114. To free the resources used by the key object, call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) after all operations with that key are finished.
512
513### MAC calculation
514
515The process for a HMAC operation in the legacy API is as follows:
516
5171. Create a digest context of type `mbedtls_md_context_t` and initialize it with `mbedtls_md_init`.
5182. Call `mbedtls_md_setup` to select the hash algorithm, with `hmac=1`. Then call `mbedtls_md_hmac_starts` to set the key.
5193. Call `mbedtls_md_hmac_update` as many times as necessary.
5204. Call `mbedtls_md_hmac_finish`. If verifying the MAC against an expected value, compare the result with the expected value. Note that this comparison should be in constant time to avoid a side channel vulnerability, for example using `mbedtls_ct_memcmp`.
5215. Finally free the resources associated with the operation object by calling `mbedtls_md_free`.
522
523The process for a CMAC operation in the legacy API is as follows:
524
5251. Create a cipher context of type `mbedtls_cipher_context_t` and initialize it with `mbedtls_cipher_init`.
5262. Call `mbedtls_cipher_setup` to select the block cipher. Then call `mbedtls_md_cmac_starts` to set the key.
5273. Call `mbedtls_cipher_cmac_update` as many times as necessary.
5284. Call `mbedtls_cipher_cmac_finish`. If verifying the MAC against an expected value, compare the result with the expected value. Note that this comparison should be in constant time to avoid a side channel vulnerability, for example using `mbedtls_ct_memcmp`.
5295. Finally free the resources associated with the operation object by calling `mbedtls_cipher_free`.
530
531The process in the PSA API to calculate a MAC is as follows:
532
5331. Create an operation object of type [`psa_mac_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1ga78f0838b0c4e3db28b26355624d4bd37) and zero-initialize it (or use the corresponding `INIT` macro).
5342. Call [`psa_mac_sign_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1ga03bc3e3c0b7e55b20d2a238e418d46cd) to specify the algorithm and the key. See “[MAC key management](#mac-key-management)” for how to obtain a key identifier.
5353. Call [`psa_mac_update`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1ga5560af371497babefe03c9da4e8a1c05) as many times as necessary.
5364. To obtain the MAC, call [`psa_mac_sign_finish`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1gac22bc0125580c96724a09226cfbc97f2).
537
538To verify a MAC against an expected value, use the following process instead:
539
5401. Create an operation object of type [`psa_mac_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1ga78f0838b0c4e3db28b26355624d4bd37) and zero-initialize it (or use the corresponding `INIT` macro).
5412. Call [`psa_mac_verify_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1ga08ae327fcbc5f8e201172fe11e536984) to specify the algorithm and the key. See “[MAC key management](#mac-key-management)” for how to obtain a key identifier.
5423. Call [`psa_mac_update`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1ga5560af371497babefe03c9da4e8a1c05) as many times as necessary.
5434. To verify the MAC against an expected value, call [`psa_mac_verify_finish`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1gac92b2930d6728e1be4d011c05d485822).
544
545If you need to interrupt the operation after calling the setup function without calling the finish function, call [`psa_mac_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1gacd8dd54855ba1bc0a03f104f252884fd).
546
547The PSA API also offers functions for a one-shot MAC calculation, similar to `mbedtls_cipher_cmac`:
548
549* [`psa_mac_compute`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1gabf02ebd3595ea15436967092b5d52878) to calculate the MAC of a buffer in memory.
550* [`psa_mac_verify`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1gaf6988545df5d5e2466c34d753443b15a) to verify the MAC of a buffer in memory against an expected value.
551
552In both cases, see “[MAC key management](#mac-key-management)” for how to obtain a key identifier.
553
554### Miscellaneous hash or MAC operation management
555
556The equivalent of `mbedtls_md_reset`, `mbedtls_md_hmac_reset` or `mbedtls_cmac_reset` is to call [`psa_hash_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1gab0b4d5f9912a615559497a467b532928) or [`psa_mac_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group___m_a_c/#group___m_a_c_1gacd8dd54855ba1bc0a03f104f252884fd). Note that you must call a setup function to specify the algorithm and the key (for MAC) again, and they can be different ones.
557
558The equivalent of `mbedtls_md_clone` to clone a hash operation is [`psa_hash_clone`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__hash/#group__hash_1ga39673348f3302b4646bd780034a5aeda). A PSA MAC operation cannot be cloned.
559
560## Key derivation
561
562### HKDF
563
564PSA Crypto provides access to HKDF, HKDF-Extract and HKDF-Expand via its [key derivation interface](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/). This is a generic interface using an operation object with one function call for each input and one function call for each output.
565
5661. Create an operation object of type [`psa_key_derivation_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga5f099b63799a0959c3d46718c86c2609) and zero-initialize it (or use the corresponding `INIT` macro).
5672. Call [`psa_key_derivation_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gac0b6a76e45cceb1862752bf041701859) to select the algorithm, which is a value of type [`psa_algorithm_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gac2e4d47f1300d73c2f829a6d99252d69). For HKDF and variants, use one of the macros [`PSA_ALG_HKDF`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__values_8h/#c.PSA_ALG_HKDF), [`PSA_ALG_HKDF_EXTRACT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__values_8h/#c.PSA_ALG_HKDF_EXTRACT) or [`PSA_ALG_HKDF_EXPAND`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__values_8h/#c.PSA_ALG_HKDF_EXPAND) with the [hash algorithm](#hash-mechanism-selection) passed as an argument. For example `PSA_ALG_HKDF(PSA_ALG_SHA_256)` selects HKDF-SHA-256.
5683. Call [`psa_key_derivation_input_bytes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga8fd934dfb0ca45cbf89542ef2a5494c2) on each of the inputs in the order listed below. (Use [`psa_key_derivation_input_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gab2d7ce8705dd8e4a093f4b8a21a0c15a) instead for an input that is a PSA key object.) The input step value for each step is as follows:
569 1. [`PSA_KEY_DERIVATION_INPUT_SALT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__derivation/#group__derivation_1gab62757fb125243562c3947a752470d4a) for the salt used during the extraction step. Omit this step for HKDF-Expand. For HKDF, you may omit this step if the salt is empty.
570 2. [`PSA_KEY_DERIVATION_INPUT_SECRET`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__derivation/#group__derivation_1ga0ddfbe764baba995c402b1b0ef59392e) for the secret input.
571 3. [`PSA_KEY_DERIVATION_INPUT_INFO`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__derivation/#group__derivation_1gacef8df989e09c769233f4b779acb5b7d) for the info string used during the expansion step. Omit this step for HKDF-Extract.
5724. Call [`psa_key_derivation_output_bytes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga06b7eb34a2fa88965f68e3d023fa12b9) to obtain the output of the derivation. You may call this function more than once to retrieve the output in successive chunks. Use [`psa_key_derivation_output_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gada7a6e17222ea9e7a6be6864a00316e1) instead if you want to use a chunk as a PSA key.
5735. Call [`psa_key_derivation_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga90fdd2716124d0bd258826184824675f) to free the resources associated with the key derivation object.
574
575### PKCS#5 module
576
Gilles Peskine02112cc2023-11-30 21:17:27 +0100577Applications currently using `mbedtls_pkcs5_pbkdf2_hmac` or `mbedtls_pkcs5_pbkdf2_hmac_ext` can switch to the PSA key derivation API for PBKDF2. This is a generic interface using an operation object with one function call for each input and one function call for each output.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200578
5791. Create an operation object of type [`psa_key_derivation_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga5f099b63799a0959c3d46718c86c2609) and zero-initialize it (or use the corresponding `INIT` macro).
5802. Call [`psa_key_derivation_setup`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gac0b6a76e45cceb1862752bf041701859) to select the algorithm, which is a value of type [`psa_algorithm_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gac2e4d47f1300d73c2f829a6d99252d69). For PBKDF2-HMAC, select `PSA_ALG_PBKDF2_HMAC(hash)` where `hash` is the underlying hash algorithm (see “[Hash mechanism selection](#hash-mechanism-selection)”).
5813. Call `psa_key_derivation_input_cost` with the step `PSA_KEY_DERIVATION_INPUT_COST` to select the iteration count.
5824. Call [`psa_key_derivation_input_bytes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga8fd934dfb0ca45cbf89542ef2a5494c2) on each of the inputs in the order listed below. (Use [`psa_key_derivation_input_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gab2d7ce8705dd8e4a093f4b8a21a0c15a) instead for an input that is a PSA key object.) The input step value for each step is as follows:
583 1. [`PSA_KEY_DERIVATION_INPUT_SALT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__derivation/#group__derivation_1gab62757fb125243562c3947a752470d4a) for the salt used during the extraction step. You may repeat this step to pass the salt in pieces (for example a salt and a pepper).
584 2. [`PSA_KEY_DERIVATION_INPUT_SECRET`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__derivation/#group__derivation_1ga0ddfbe764baba995c402b1b0ef59392e) for the password.
5855. Call [`psa_key_derivation_output_bytes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga06b7eb34a2fa88965f68e3d023fa12b9) to obtain the output of the derivation. You may call this function more than once to retrieve the output in successive chunks.
586 Use [`psa_key_derivation_output_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gada7a6e17222ea9e7a6be6864a00316e1) instead if you want to use a chunk as a PSA key.
Gilles Peskine02112cc2023-11-30 21:17:27 +0100587 If you want to verify the output against an expected value (for authentication, rather than to derive key material), call [`psa_key_derivation_verify_bytes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gaf01520beb7ba932143ffe733b0795b08) or [`psa_key_derivation_verify_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gac041714e34a94742e8ee006ac7dfea5a) instead of `psa_key_derivation_output_bytes`. (Note that the `verify` functions are not yet present in the 3.5 release of Mbed TLS. They are expected to be released in version 3.6.0.)
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02005886. Call [`psa_key_derivation_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga90fdd2716124d0bd258826184824675f) to free the resources associated with the key derivation object.
589
Gilles Peskine5403cb32023-11-28 18:03:03 +0100590The function `mbedtls_pkcs5_pbes2` is only intended as a support function to parse encrypted private keys in the PK module. It has no PSA equivalent.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200591
592### PKCS#12 module
593
Gilles Peskinec3fd0952023-11-30 21:18:04 +0100594The functions `mbedtls_pkcs12_derivation` and `mbedtls_pkcs12_pbe` are only intended as support functions to parse encrypted private keys in the PK module. They have no PSA equivalent.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200595
596## Random generation
597
598### Random generation interface
599
Gilles Peskine06002c52023-12-04 22:24:25 +0100600The PSA subsystem has an internal random generator. As a consequence, you do not need to instantiate one manually, so most applications using PSA crypto do not need the interfaces from `entropy.h`, `ctr_drbg.h` and `hmac_drbg.h`. See the next sections for remaining use cases for [entropy](#entropy-sources) and [DRBG](#deterministic-pseudorandom-generation).
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200601
602The PSA API uses its internal random generator to generate keys (`psa_generate_key`), nonces for encryption (`psa_cipher_generate_iv`, `psa_cipher_encrypt`, `psa_aead_generate_nonce`, `psa_aead_encrypt`, `psa_asymmetric_encrypt`), and other random material as needed. If you need random data for some other purposes, call [`psa_generate_random`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga1985eae417dfbccedf50d5fff54ea8c5).
603
Gilles Peskinec7b53f32023-06-13 21:31:53 +0200604If your application mixes uses of the PSA crypto API and the mbedtls API and you need to pass an RNG argument to a legacy or X.509/TLS function, include the header file `<mbedtls/psa_util.h>` and use:
605
606* [`mbedtls_psa_get_random`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/psa__util_8h/#_CPPv422mbedtls_psa_get_randomPvPh6size_t) as the `f_rng` argument;
607* [`MBEDTLS_PSA_RANDOM_STATE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/psa__util_8h/#c.MBEDTLS_PSA_RANDOM_STATE) as the `p_rng` argument.
608
Gilles Peskined372da62023-11-28 18:03:53 +0100609You can remove the Mbed TLS RNG boilerplate (`mbedtls_entropy_init`, `mbedtls_ctr_drbg_init`, `mbedtls_ctr_drbg_seed`, `mbedtls_ctr_drbg_random`, `mbedtls_ctr_drbg_free`, `mbedtls_entropy_free` or `hmac_drbg` equivalents of the `ctr_drbg` functions) once you have finished replacing the references to `mbedtls_ctr_drbg_random` (or `mbedtls_hmac_drbg_random`) by `mbedtls_psa_get_random`.
610
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200611### Entropy sources
612
613Unless explicitly configured otherwise, the PSA random generator uses the default entropy sources configured through the legacy interface (`MBEDTLS_ENTROPY_xxx` symbols). Its set of sources is equivalent to an entropy object configured with `mbedtls_entropy_init`.
614
615A future version of Mbed TLS will include a PSA interface for configuring entropy sources. This is likely to replace the legacy interface in Mbed TLS 4.0.
616
617### Deterministic pseudorandom generation
618
619The PSA API does not have a dedicated interface for pseudorandom generation. The [key derivation interface](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/) can serve a similar purpose in some applications, but it does not offer CTR\_DRBG or HMAC\_DRBG. If you need these algorithms, keep using `ctr_drbg.h` and `hmac_drbg.h`, but note that they may be removed from the public API in Mbed TLS 4.0.
620
621## Asymmetric cryptography
622
623The PSA API supports RSA (see “[RSA mechanism selection](#rsa-mechanism-selection)”), elliptic curve cryptography (see “[ECC mechanism selection](#elliptic-curve-mechanism-selection)” and “[EC-JPAKE](#ec-jpake)”) and finite-field Diffie-Hellman (see “[Diffie-Hellman mechanism selection](#diffie-hellman-mechanism-selection)”).
624
625### Key lifecycle for asymmetric cryptography
626
627In the PSA API, keys are referenced by an identifier of type [`psa_key_id_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__types_8h/#_CPPv412psa_key_id_t).
628(Some documentation references [`mbedtls_svc_key_id_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__types_8h/#_CPPv420mbedtls_svc_key_id_t); the two types are identical except when the library is configured for use in a multi-client cryptography service.)
Gilles Peskinedfe67072023-11-29 21:12:39 +0100629The PSA key identifier tends to play the same role as an `mbedtls_pk_context`, `mbedtls_rsa_context` or `mbedtls_ecp_keypair` structure in the legacy API. However, there are major differences in the way the two APIs can be used to create keys or to obtain information about a key.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200630
631Here is an overview of the lifecycle of a PSA key object.
632
6331. First define the attributes of the key by filling a [`psa_key_attributes_t` structure](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga0ec645e1fdafe59d591104451ebf5680). You need to set the following parameters:
634 * Call [`psa_set_key_type`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga6857ef0ecb3fa844d4536939d9c64025) to set the key type to the desired `PSA_KEY_TYPE_xxx` value (see “[RSA mechanism selection](#rsa-mechanism-selection)”, “[Elliptic curve mechanism selection](#elliptic-curve-mechanism-selection)” and “[Diffie-Hellman mechanism selection](#diffie-hellman-mechanism-selection)”).
635 * Call [`psa_set_key_bits`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaf61683ac87f87687a40262b5afbfa018) to set the key's conceptual size in bits. This is optional with `psa_import_key`, which determines the key size from the length of the key material.
Gilles Peskine4d234f12023-11-30 13:59:49 +0100636 * Call [`psa_set_key_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaeb8341ca52baa0279475ea3fd3bcdc98) to set the permitted algorithm to the desired `PSA_ALG_xxx` value (see “[RSA mechanism selection](#rsa-mechanism-selection)”, “[Elliptic curve mechanism selection](#elliptic-curve-mechanism-selection)” and “[Diffie-Hellman mechanism selection](#diffie-hellman-mechanism-selection)” as well as “[Public-key cryptography policies](#public-key-cryptography-policies)”).
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200637 * Call [`psa_set_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga42a65b3c4522ce9b67ea5ea7720e17de) to enable the desired usage types (see “[Public-key cryptography policies](#public-key-cryptography-policies)”).
6382. Call one of the key creation functions, passing the attributes defined in the previous step, to get an identifier of type [`psa_key_id_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__types_8h/#_CPPv412psa_key_id_t) to the key object.
639 * Use [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b) to directly import key material.
640 * If the key is randomly generated, use [`psa_generate_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga1985eae417dfbccedf50d5fff54ea8c5).
641 * If the key is derived from other material (for example from a key exchange), use the [key derivation interface](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/) and create the key with [`psa_key_derivation_output_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gada7a6e17222ea9e7a6be6864a00316e1).
6423. Call the functions in the following sections to perform operations on the key. The same key object can be used in multiple operations.
6434. To free the resources used by the key object, call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) after all operations with that key are finished.
644
645### Public-key cryptography policies
646
647A key's policy indicates what algorithm(s) it can be used with (usage algorithm policy) and what operations are permitted (usage flags).
648
Gilles Peskinedfe67072023-11-29 21:12:39 +0100649The following table lists the relevant usage flags for asymmetric cryptography. You can pass those flags (combined with bitwise-or) to [`psa_set_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga42a65b3c4522ce9b67ea5ea7720e17de).
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200650
651| Usage | Flag |
652| ----- | ---- |
653| export public key | 0 (always permitted) |
654| export private key | [`PSA_KEY_USAGE_EXPORT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1ga7dddccdd1303176e87a4d20c87b589ed) |
655| Sign a message directly | [`PSA_KEY_USAGE_SIGN_MESSAGE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1ga552117ac92b79500cae87d4e65a85c54) |
656| Sign an already-calculated hash | at least one of [`PSA_KEY_USAGE_SIGN_MESSAGE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1ga552117ac92b79500cae87d4e65a85c54) or [`PSA_KEY_USAGE_SIGN_HASH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1ga552117ac92b79500cae87d4e65a85c54) |
657| Verify a message directly | [`PSA_KEY_USAGE_VERIFY_MESSAGE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1gabea7ec4173f4f943110329ac2953b2b1) |
658| Verify an already-calculated hash | at least one of [`PSA_KEY_USAGE_VERIFY_MESSAGE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1gabea7ec4173f4f943110329ac2953b2b1) or [`PSA_KEY_USAGE_VERIFY_HASH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1gafadf131ef2182045e3483d03aadaa1bd) |
Gilles Peskine4d234f12023-11-30 13:59:49 +0100659| Encryption | [`PSA_KEY_USAGE_ENCRYPT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1ga75153b296d045d529d97203a6a995dad) |
660| Decryption | [`PSA_KEY_USAGE_DECRYPT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1gac3f2d2e5983db1edde9f142ca9bf8e6a) |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200661| Key agreement | [`PSA_KEY_USAGE_DERIVE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1gaf19022acc5ef23cf12477f632b48a0b2) |
662
663The sections “[RSA mechanism selection](#rsa-mechanism-selection)”, “[Elliptic curve mechanism selection](#elliptic-curve-mechanism-selection)” and “[Diffie-Hellman mechanism selection](#diffie-hellman-mechanism-selection)” cover the available algorithm values for each key type. Normally, a key can only be used with a single algorithm, following standard good practice. However, there are two ways to relax this requirement.
664
Gilles Peskinedfe67072023-11-29 21:12:39 +0100665* Many signature algorithms encode a hash algorithm. Sometimes the same key may need to be used to sign messages with multiple different hashes. In an algorithm policy, you can use [`PSA_ALG_ANY_HASH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__values_8h/#c.PSA_ALG_ANY_HASH) instead of a hash algorithm value to allow the key to be used with any hash. For example, `psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH))` allows the key to be used with RSASSA-PSS, with different hash algorithms in each operation.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200666* In addition to the algorithm (or wildcard) selected with [`psa_set_key_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaeb8341ca52baa0279475ea3fd3bcdc98), you can use [`psa_set_key_enrollment_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaffa134b74aa52aa3ed9397fcab4005aa) to permit a second algorithm (or wildcard). This is intended for scenarios where a key is normally used with a single algorithm, but needs to be used with a different algorithm for enrollment (such as an ECDH key for which an ECDSA proof-of-possession is also required).
667
668### Asymmetric cryptographic mechanisms
669
670#### RSA mechanism selection
671
672The PK types `MBEDTLS_PK_RSA`, `MBEDTLS_PK_RSASSA_PSS` and `MBEDTLS_PK_RSA_ALT` correspond to RSA key types in the PSA API. In the PSA API, key pairs and public keys are separate object types.
673See “[RSA-ALT interface](#rsa-alt-interface)” for more information about `MBEDTLS_PK_RSA_ALT`.
674
Gilles Peskine951cf392023-11-30 14:01:20 +0100675The PSA API uses policies and algorithm parameters rather than key types to distinguish between RSA-based mechanisms. The PSA algorithm selection corresponds to the `mbedtls_pk_type_t` value passed to `mbedtls_pk_{sign,verify}_ext`. It also replaces the use of `mbedtls_rsa_set_padding` on an `mbedtls_rsa_context` object. See the list of algorithms below and the signature and encryption sections for more information.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200676
677An RSA public key has the type [`PSA_KEY_TYPE_RSA_PUBLIC_KEY`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga9ba0878f56c8bcd1995ac017a74f513b).
678
679An RSA key pair has the type [`PSA_KEY_TYPE_RSA_KEY_PAIR`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga11745b110166e927e2abeabc7d532051). A key with this type can be used both for private-key and public-key operations (there is no separate key type for a private key without the corresponding public key).
680You can always use a private key for operations on the corresponding public key (as long as the policy permits it).
681
682The following cryptographic algorithms work with RSA keys:
683
684* PKCS#1v1.5 RSA signature: [`PSA_ALG_RSA_PKCS1V15_SIGN`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga702ff75385a6ae7d4247033f479439af), [`PSA_ALG_RSA_PKCS1V15_SIGN_RAW`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga4215e2a78dcf834e9a625927faa2a817).
685* PKCS#1v1.5 RSA encryption: [`PSA_ALG_RSA_PKCS1V15_CRYPT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga4c540d3abe43fb9abcb94f2bc51acef9).
686* PKCS#1 RSASSA-PSS signature: [`PSA_ALG_RSA_PSS`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga62152bf4cb4bf6aace5e1be8f143564d), [`PSA_ALG_RSA_PSS_ANY_SALT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga9b7355a2cd6bde88177634d539127f2b).
687* PKCS#1 RSAES-OAEP encryption: [`PSA_ALG_RSA_OAEP`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gaa1235dc3fdd9839c6c1b1a9857344c76).
688
689#### Elliptic curve mechanism selection
690
Gilles Peskine4d234f12023-11-30 13:59:49 +0100691The PK types `MBEDTLS_PK_ECKEY`, `MBEDTLS_PK_ECKEY_DH` and `MBEDTLS_PK_ECDSA` correspond to elliptic-curve key types in the PSA API. In the PSA API, key pairs and public keys are separate object types. The PSA API uses policies and algorithm parameters rather than key types to distinguish between the PK EC types.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200692
693An ECC public key has the type [`PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gad54c03d3b47020e571a72cd01d978cf2) where `curve` is a curve family identifier.
694
695An ECC key pair has the type [`PSA_KEY_TYPE_ECC_KEY_PAIR(curve)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga0b6f5d4d5037c54ffa850d8059c32df0) where `curve` is a curve family identifier. A key with this type can be used both for private-key and public-key operations (there is no separate key type for a private key without the corresponding public key).
696You can always use a private key for operations on the corresponding public key (as long as the policy permits it).
697
698A curve is fully determined by a curve family identifier and the private key size in bits. The following table gives the correspondence between legacy and PSA elliptic curve designations.
699
700| Mbed TLS legacy curve identifier | PSA curve family | Curve bit-size |
701| -------------------------------- | ---------------- | -------------- |
702| `MBEDTLS_ECP_DP_SECP192R1` | [`PSA_ECC_FAMILY_SECP_R1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga48bb340b5544ba617b0f5b89542665a7) | 192 |
703| `MBEDTLS_ECP_DP_SECP224R1` | [`PSA_ECC_FAMILY_SECP_R1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga48bb340b5544ba617b0f5b89542665a7) | 224 |
704| `MBEDTLS_ECP_DP_SECP256R1` | [`PSA_ECC_FAMILY_SECP_R1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga48bb340b5544ba617b0f5b89542665a7) | 256 |
705| `MBEDTLS_ECP_DP_SECP384R1` | [`PSA_ECC_FAMILY_SECP_R1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga48bb340b5544ba617b0f5b89542665a7) | 384 |
706| `MBEDTLS_ECP_DP_SECP521R1` | [`PSA_ECC_FAMILY_SECP_R1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga48bb340b5544ba617b0f5b89542665a7) | 521 |
707| `MBEDTLS_ECP_DP_BP256R1` | [`PSA_ECC_FAMILY_BRAINPOOL_P_R1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gac1643f1baf38b30d07c20a6eac697f15) | 256 |
708| `MBEDTLS_ECP_DP_BP384R1` | [`PSA_ECC_FAMILY_BRAINPOOL_P_R1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gac1643f1baf38b30d07c20a6eac697f15) | 384 |
709| `MBEDTLS_ECP_DP_BP512R1` | [`PSA_ECC_FAMILY_BRAINPOOL_P_R1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gac1643f1baf38b30d07c20a6eac697f15) | 512 |
710| `MBEDTLS_ECP_DP_CURVE25519` | [`PSA_ECC_FAMILY_MONTGOMERY`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga1f624c5cdaf25b21287af33024e1aff8) | 255 |
711| `MBEDTLS_ECP_DP_SECP192K1` | [`PSA_ECC_FAMILY_SECP_K1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga48bb340b5544ba617b0f5b89542665a7) | 192 |
Gilles Peskine2fffc452023-12-04 22:22:07 +0100712| `MBEDTLS_ECP_DP_SECP224K1` | not supported | N/A |
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200713| `MBEDTLS_ECP_DP_SECP256K1` | [`PSA_ECC_FAMILY_SECP_K1`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga48bb340b5544ba617b0f5b89542665a7) | 256 |
714| `MBEDTLS_ECP_DP_CURVE448` | [`PSA_ECC_FAMILY_MONTGOMERY`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga1f624c5cdaf25b21287af33024e1aff8) | 448 |
715
716The following cryptographic algorithms work with ECC keys:
717
718* ECDH key agreement (including X25519 and X448): [`PSA_ALG_ECDH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gab2dbcf71b63785e7dd7b54a100edee43).
719* ECDSA: [`PSA_ALG_ECDSA`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga7e3ce9f514a227d5ba5d8318870452e3), [`PSA_ALG_ECDSA_ANY`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga51d6b6044a62e33cae0cf64bfc3b22a4), [`PSA_ALG_DETERMINISTIC_ECDSA`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga11da566bcd341661c8de921e2ca5ed03).
Gilles Peskine4d234f12023-11-30 13:59:49 +0100720* EC-JPAKE (see “[EC-JPAKE](#ec-jpake)”.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200721
722#### Diffie-Hellman mechanism selection
723
Gilles Peskine5bd4f172023-06-15 18:33:30 +0200724A finite-field Diffie-Hellman key pair has the type [`PSA_KEY_TYPE_DH_KEY_PAIR(group)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gab4f857c4cd56f5fe65ded421e61bcc8c) where `group` is a group family as explained below.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200725
Gilles Peskine5bd4f172023-06-15 18:33:30 +0200726A finite-field Diffie-Hellman public key has the type [`PSA_KEY_TYPE_DH_PUBLIC_KEY(group)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gaa22f0f2ea89b929f2fadc19890cc5d5c) where `group` is a group family as explained below. Due to the design of the API, there is rarely a need to use Diffie-Hellman public key objects.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200727
728The PSA API only supports Diffie-Hellman with predefined groups. A group is fully determined by a group family identifier and the public key size in bits.
729
730| Mbed TLS DH group P value | PSA DH group family | Bit-size |
731| ------------------------- | ------------------- | -------- |
732| `MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN` | [`PSA_DH_FAMILY_RFC7919`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga7be917e67fe4a567fb36864035822ff7) | 2048 |
733| `MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN` | [`PSA_DH_FAMILY_RFC7919`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga7be917e67fe4a567fb36864035822ff7) | 3072 |
734| `MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN` | [`PSA_DH_FAMILY_RFC7919`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga7be917e67fe4a567fb36864035822ff7) | 4096 |
735| `MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN` | [`PSA_DH_FAMILY_RFC7919`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga7be917e67fe4a567fb36864035822ff7) | 6144 |
736| `MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN` | [`PSA_DH_FAMILY_RFC7919`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga7be917e67fe4a567fb36864035822ff7) | 8192 |
737
738A finite-field Diffie-Hellman key can be used for key agreement with the algorithm [`PSA_ALG_FFDH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga0ebbb6f93a05b6511e6f108ffd2d1eb4).
739
740### Creating keys for asymmetric cryptography
741
742The easiest way to create a key pair object is by randomly generating it with [`psa_generate_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga1985eae417dfbccedf50d5fff54ea8c5). Compared with the low-level functions from the legacy API (`mbedtls_rsa_gen_key`, `mbedtls_ecp_gen_privkey`, `mbedtls_ecp_gen_keypair`, `mbedtls_ecp_gen_keypair_base`, `mbedtls_ecdsa_genkey`), this directly creates an object that can be used with high-level APIs, but removes some of the flexibility. Note that if you want to export the generated private key, you must pass the flag [`PSA_KEY_USAGE_EXPORT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1ga7dddccdd1303176e87a4d20c87b589ed) to [`psa_set_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga42a65b3c4522ce9b67ea5ea7720e17de); exporting the public key with [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) is always permitted.
743
744For RSA keys, `psa_generate_key` always uses 65537 as the public exponent. If you need a different public exponent, use the legacy interface to create the key then import it as described in “[Importing legacy keys via the PK module](#importing-legacy-keys-via-the-pk-module)”.
745
Gilles Peskine951cf392023-11-30 14:01:20 +0100746To create a key object from existing material, use [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b). While this function has the same basic goal as the PK parse functions (`mbedtls_pk_parse_key`, `mbedtls_pk_parse_public_key`, `mbedtls_pk_parse_subpubkey`), it is limited to a single format that just contains the number(s) that make up the key, with very little metadata. This format is a substring of one of the formats accepted by the PK functions (except for finite-field Diffie-Hellman which the PK module does not support). The table below summarizes the PSA import/export format for key pairs and public keys; see the documentation of [`psa_export_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga668e35be8d2852ad3feeef74ac6f75bf) and [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) for more details.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200747
748| Key type | PSA import/export format |
749| -------- | ------------------------ |
750| RSA key pair | PKCS#1 RSAPrivateKey DER encoding (including both private exponent and CRT parameters) |
751| RSA public key | PKCS#1 RSAPublicKey DER encoding |
752| ECC key pair | Fixed-length private value (not containing the public key) |
753| ECC public key (Weierstrass curve) | Fixed-length uncompressed point |
754| ECC public key (Montgomery curve) | Fixed-length public value |
755| FFDH key pair | Fixed-length private value (not containing the public key) |
756| FFDH public key | Fixed-length public value |
757
758There is no equivalent of `mbedtls_pk_parse_keyfile` and `mbedtls_pk_parse_public_keyfile`. Either call the legacy function or load the file data manually.
759
760A future extension of the PSA API will support other import formats. Until those are implemented, see the following subsections for ways to use the PK module for key parsing and construct a PSA key object from the PK object.
761
762#### Importing legacy keys via the PK module
763
764You can use glue functions in the PK module to create a key object using the legacy API, then import that object into the PSA subsystem. This is useful for use cases that the PSA API does not currently cover, such as:
765
766* Parsing a key in a format with metadata without knowing its type ahead of time.
767* Importing a key which you have in the form of a list of numbers, rather than the binary encoding required by `psa_import_key`.
Gilles Peskinedfe67072023-11-29 21:12:39 +0100768* Importing a key with less information than what the PSA API needs, for example an ECC public key in a compressed format, an RSA private key without the private exponent, or an RSA private key without the CRT parameters.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200769* Generating an RSA key with $e \ne 65537$.
770
771#### Importing a PK key by wrapping
772
Gilles Peskine5eeca332023-12-04 22:35:12 +0100773If you have a PK object, you can call `mbedtls_pk_wrap_as_opaque` to create a PSA key object with the same key material. (This function is only present in builds with `MBEDTLS_USE_PSA_CRYPTO` enabled. It is experimental and [will likely be replaced by a slightly different interface in a future version of Mbed TLS](https://github.com/Mbed-TLS/mbedtls/issues/7760)). This function automatically determines the PSA key type and lets you specify the usage policy (see “[Public-key cryptography policies](#public-key-cryptography-policies)”). Once you've called this function, you can destroy the PK object. This function calls `psa_import_key` internally; call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) to destroy the PSA key object once your application no longer needs it. Common scenarios where this workflow is useful are:
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200774
775* You have working code that's calling `mbedtls_pk_parse_key`, `mbedtls_pk_parse_public_key`, `mbedtls_pk_parse_subpubkey`, `mbedtls_pk_parse_keyfile` or `mbedtls_pk_parse_public_keyfile` to create a PK object.
776* You have working code that's using the `rsa.h` or `ecp.h` API to create a key object, and there is no PSA equivalent.
777
Gilles Peskine5eeca332023-12-04 22:35:12 +0100778You can use this workflow to import an RSA key via an `mbedtls_rsa_context` object or an ECC key via an `mbedtls_ecp_keypair` object:
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200779
7801. Call `mbedtls_pk_init` then `mbedtls_pk_setup` to set up a PK context for the desired key type (`MBEDTLS_PK_RSA` or `MBEDTLS_PK_ECKEY`).
7812. Call `mbedtls_pk_rsa` or `mbedtls_pk_ec` to obtain the underlying low-level context.
7823. Call `mbedtls_rsa_xxx` or `mbedtls_ecp_xxx` functions to construct the desired key. For example:
783 * `mbedtls_rsa_import` or `mbedtls_rsa_import_raw` followed by `mbedtls_rsa_complete` to create an RSA private key without all the parameters required by the PSA API.
784 * `mbedtls_rsa_gen_key` to generate an RSA private key with a custom public exponent.
7854. Call `mbedtls_pk_wrap_as_opaque` as described above to create a corresponding PSA key object.
7865. Call `mbedtls_pk_free` to free the resources associated with the PK object.
787
788#### Importing a PK key by export-import
789
790This section explains how to export a PK object in the PSA import format. The process depends on the key type. You can use `mbedtls_pk_get_type` or `mbedtls_pk_can_do` to distinguish between RSA and ECC keys. The snippets below assume that the key is in an `mbedtls_pk_context pk`, and omit error checking.
791
792For an RSA private key:
793
794```
795unsigned char buf[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
796size_t length = mbedtls_pk_write_key_der(&pk, buf, sizeof(buf));
797psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
798psa_set_key_attributes(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
799psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_... | ...);
800psa_set_key_algorithm(&attributes, PSA_ALGORITHM_...);
801psa_key_id_t key_id = 0;
802psa_import_key(&attributes, buf + sizeof(buf) - length, length, &key_id);
803mbedtls_pk_free(&pk);
804```
805
Gilles Peskine909cf5a2023-06-20 23:38:39 +0200806For an ECC private key (a future version of Mbed TLS [will provide a more direct way to find the curve family](https://github.com/Mbed-TLS/mbedtls/issues/7764)):
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200807
808```
809unsigned char buf[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
810size_t length = PSA_BITS_TO_BYTES(mbedtls_pk_bitlen(&pk));
811mbedtls_ecp_keypair *ec = mbedtls_pk_ec(&pk);
Gilles Peskine909cf5a2023-06-20 23:38:39 +0200812psa_ecc_curve_t curve;
813{
814 mbedtls_ecp_group grp;
815 mbedtls_ecp_group_init(&grp);
816 mbedtls_ecp_point Q;
817 mbedtls_ecp_point_init(&Q);
818 mbedtls_mpi d;
819 mbedtls_mpi_init(&d);
820 mbedtls_ecp_export(ec, &grp, &d, &Q);
821 size_t bits;
822 curve = mbedtls_ecc_group_to_psa(grp.id, &bits);
823 mbedtls_ecp_group_free(&grp);
824 mbedtls_ecp_point_free(&Q);
825 mbedtls_mpi_free(&d);
826}
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200827mbedtls_ecp_write_key(ec, buf, length);
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200828psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Gilles Peskine909cf5a2023-06-20 23:38:39 +0200829psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200830psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_... | ...);
831psa_set_key_algorithm(&attributes, PSA_ALGORITHM_...);
832psa_key_id_t key_id = 0;
833psa_import_key(&attributes, buf, length, &key_id);
834mbedtls_pk_free(&pk);
835```
836
837For an RSA or ECC public key:
838
839```
840unsigned char buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
841size_t length = mbedtls_pk_write_pubkey(&pk, buf, sizeof(buf));
842psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
843psa_set_key_attributes(&attributes, ...); // need to determine the type manually
844psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_... | ...);
845psa_set_key_algorithm(&attributes, PSA_ALGORITHM_...);
846psa_key_id_t key_id = 0;
847psa_import_key(&attributes, buf + sizeof(buf) - length, length, &key_id);
848mbedtls_pk_free(&pk);
849```
850
851#### Importing an elliptic curve key from ECP
852
853This section explains how to use the `ecp.h` API to create an elliptic curve key in a format suitable for `psa_import_key`.
854
855You can use this, for example, to import an ECC key in the form of a compressed point by calling `mbedtls_ecp_point_read_binary` then following the process below.
856
Gilles Peskine951cf392023-11-30 14:01:20 +0100857The following code snippet illustrates how to import a private key which is initially in an `mbedtls_ecp_keypair` object. (This includes `mbedtls_ecdsa_keypair` objects since that is just a type alias.) Error checks are omitted for simplicity. A future version of Mbed TLS [will provide a function to calculate the curve family](https://github.com/Mbed-TLS/mbedtls/issues/7764).
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200858
859```
860mbedtls_ecp_keypair ec;
861mbedtls_ecp_keypair_init(&ec);
862// Omitted: fill ec with key material
863// (the public key will not be used and does not need to be set)
864unsigned char buf[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
865size_t length = PSA_BITS_TO_BYTES(mbedtls_pk_bitlen(&pk));
866mbedtls_ecp_write_key(&ec, buf, length);
867psa_ecc_curve_t curve = ...; // need to determine the curve family manually
868psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
869psa_set_key_attributes(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
870psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_... | ...);
871psa_set_key_algorithm(&attributes, PSA_ALGORITHM_...);
872psa_key_id_t key_id = 0;
873psa_import_key(&attributes, buf, length, &key_id);
874mbedtls_ecp_keypair_free(&ec);
875```
876The following code snippet illustrates how to import a private key which is initially in an `mbedtls_ecp_keypair` object. Error checks are omitted for simplicity.
877
878```
879mbedtls_ecp_group grp;
880mbedtls_ecp_group_init(&grp);
881mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_...);
882mbedtls_ecp_point pt;
883mbedtls_ecp_point_init(&pt);
884// Omitted: fill pt with key material
885unsigned char buf[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_PUBLIC_KEY_MAX_SIZE)];
886size_t length;
887mbedtls_ecp_point_write_binary(&grp, &pt, &length, buf, sizeof(buf));
888psa_ecc_curve_t curve = ...; // need to determine the curve family manually
889psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
890psa_set_key_attributes(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve));
891psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_... | ...);
892psa_set_key_algorithm(&attributes, PSA_ALGORITHM_...);
893psa_key_id_t key_id = 0;
894psa_import_key(&attributes, buf, length, &key_id);
895mbedtls_ecp_point_free(&pt);
896mbedtls_ecp_group_free(&grp);
897```
898
899### Key pair and public key metadata
900
901There is no equivalent to the type `mbedtls_pk_info_t` and the functions `mbedtls_pk_info_from_type` in the PSA API because it is unnecessary. All macros and functions operate directly on key type values (`psa_key_type_t`, `PSA_KEY_TYPE_xxx` constants) and algorithm values (`psa_algorithm_t`, `PSA_ALG_xxx` constants).
902
903You can call [`psa_get_key_attributes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gacbbf5c11eac6cd70c87ffb936e1b9be2) to populate a structure with the attributes of a key, then functions such as [`psa_get_key_type`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gae4fb812af4f57aa1ad85e335a865b918) and [`psa_get_key_bits`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga5bee85c2164ad3d4c0d42501241eeb06) to obtain a key's type (`PSA_KEY_TYPE_xxx` value) and size (nominal size in bits).
904
Gilles Peskinedfe67072023-11-29 21:12:39 +0100905The bit-size from `psa_get_key_bits` is the same as the one from `mbedtls_pk_get_bitlen`. To convert to bytes as `mbedtls_pk_get_len` or `mbedtls_rsa_get_len` do, you can use the macro `PSA_BITS_TO_BYTES`. However, note that the PSA API has generic macros for each related buffer size (export, signature size, etc.), so you should generally use those instead. The present document lists those macros where it explains the usage of the corresponding function.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200906
Gilles Peskine951cf392023-11-30 14:01:20 +0100907Most code that calls `mbedtls_pk_get_type` or `mbedtls_pk_can_do` only requires the key's type as reported by [`psa_get_key_type`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gae4fb812af4f57aa1ad85e335a865b918). For code that uses both `mbedtls_pk_context` objects and PSA metadata encoding, [`mbedtls_pk_can_do_ext`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/pk_8h/#pk_8h_1a256d3e8d4323a45aafa7d2b6c59a36f6) checks the compatibility between a key object and a mechanism. If needed, you can also access a key's policy from its attributes with [`psa_get_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaa1af20f142ca722222c6d98678a0c448), [`psa_get_key_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gac255da850a00bbed925390044f016b34) and [`psa_get_key_enrollment_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga39803b62a97198cf630854db9b53c588). The algorithm policy also conveys the padding and hash information provided by `mbedtls_rsa_get_padding_mode` and `mbedtls_rsa_get_md_alg`.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200908
909### Exporting a public key or a key pair
910
911To export a PSA key pair or public key, call [`psa_export_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga668e35be8d2852ad3feeef74ac6f75bf). If the key is a key pair, its policy must allow `PSA_KEY_USAGE_EXPORT` (see “[Public-key cryptography policies](#public-key-cryptography-policies)”).
912
913To export a PSA public key or to export the public key of a PSA key pair object, call [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062). This is always permitted regardless of the key's policy.
914
915The export format is the same format used for `psa_import_key`, described in “[Creating keys for asymmetric cryptography](#creating-keys-for-asymmetric-cryptography)” above.
916
Gilles Peskine4d234f12023-11-30 13:59:49 +0100917A future extension of the PSA API will support other export formats. Until those are implemented, see “[Exporting a PK key by wrapping](#exporting-a-pk-key-by-wrapping)” for ways to use the PK module to format a PSA key.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200918
919#### Exporting a PK key by wrapping
920
921You can wrap a PSA key object in a PK key context with `mbedtls_pk_setup_opaque`. This allows you to call functions such as `mbedtls_pk_write_key_der`, `mbedtls_pk_write_pubkey_der`, `mbedtls_pk_write_pubkey_pem`, `mbedtls_pk_write_key_pem` or `mbedtls_pk_write_pubkey` to export the key data in various formats.
922
923### Signature operations
924
Gilles Peskinef7746bd2023-11-30 14:01:44 +0100925The equivalent of `mbedtls_pk_sign` or `mbedtls_pk_sign_ext` to sign an already calculated hash is [`psa_sign_hash`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__asymmetric/#group__asymmetric_1ga785e746a31a7b2a35ae5175c5ace3c5c).
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200926The key must be a key pair allowing the usage `PSA_KEY_USAGE_SIGN_HASH` (see “[Public-key cryptography policies](#public-key-cryptography-policies)”).
927Use [`PSA_SIGN_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_SIGN_OUTPUT_SIZE) or [`PSA_SIGNATURE_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_SIGNATURE_MAX_SIZE) (similar to `MBEDTLS_PK_SIGNATURE_MAX_SIZE`) to determine the size of the output buffer.
Gilles Peskinef7746bd2023-11-30 14:01:44 +0100928This is also the equivalent of the type-specific functions `mbedtls_rsa_pkcs1_sign`, `mbedtls_rsa_rsassa_pkcs1_v15_sign`, `mbedtls_rsa_rsassa_pss_sign`, `mbedtls_rsa_rsassa_pss_sign_ext`, `mbedtls_ecdsa_sign`, `mbedtls_ecdsa_sign_det_ext` and `mbedtls_ecdsa_write_signature`. Note that the PSA API uses the raw format for ECDSA signatures, not the ASN.1 format; see “[ECDSA signature](#ecdsa-signature)” for more details.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200929
930The equivalent of `mbedtls_pk_verify` or `mbedtls_pk_verify_ext` to verify an already calculated hash is [`psa_verify_hash`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__asymmetric/#group__asymmetric_1gae2ffbf01e5266391aff22b101a49f5f5).
Gilles Peskine06002c52023-12-04 22:24:25 +0100931The key must be a public key (or a key pair) allowing the usage `PSA_KEY_USAGE_VERIFY_HASH` (see “[Public-key cryptography policies](#public-key-cryptography-policies)”).
Gilles Peskinef7746bd2023-11-30 14:01:44 +0100932This is also the equivalent of the type-specific functions `mbedtls_rsa_pkcs1_verify`, `mbedtls_rsa_rsassa_pkcs1_v15_verify`, `mbedtls_rsa_rsassa_pss_verify`, `mbedtls_rsa_rsassa_pss_verify_ext`, `mbedtls_ecdsa_verify` amd `mbedtls_ecdsa_read_signature`. Note that the PSA API uses the raw format for ECDSA signatures, not the ASN.1 format; see “[ECDSA signature](#ecdsa-signature)” for more details.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200933
934Generally, `psa_sign_hash` and `psa_verify_hash` require the input to have the correct length for the hash (this has historically not always been enforced in the corresponding legacy APIs).
935
936See also “[Restartable ECDSA signature](#restartable-ecdsa-signature)” for a restartable variant of this API.
937
938The PSA API also has functions [`psa_sign_message`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__asymmetric/#group__asymmetric_1ga963ecadae9c38c85826f9a13cf1529b9) and [`psa_verify_message`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__asymmetric/#group__asymmetric_1ga01c11f480b185a4268bebd013df7c14c). These functions combine the hash calculation with the signature calculation or verification.
939For `psa_sign_message`, either the usage flag `PSA_KEY_USAGE_SIGN_MESSAGE` or `PSA_KEY_USAGE_SIGN_HASH` is sufficient.
940For `psa_verify_message`, either the usage flag `PSA_KEY_USAGE_VERIFY_MESSAGE` or `PSA_KEY_USAGE_VERIFY_HASH` is sufficient.
941
942Most signature algorithms involve a hash algorithm. See “[Hash mechanism selection](#hash-mechanism-selection)”.
943
944The following subsections describe the PSA signature mechanisms that correspond to legacy Mbed TLS mechanisms.
945
946#### ECDSA signature
947
Gilles Peskinef7746bd2023-11-30 14:01:44 +0100948**Note: in the PSA API, the format of an ECDSA signature is the raw fixed-size format. This is different from the legacy API** which uses the ASN.1 DER format for ECDSA signatures. A future version of Mbed TLS [will provide a way to convert between the two formats](https://github.com/Mbed-TLS/mbedtls/issues/7765).
Gilles Peskinedfe67072023-11-29 21:12:39 +0100949<!-- The following are specific to the DER format and therefore have no PSA equivalent: MBEDTLS_ECDSA_MAX_SIG_LEN, MBEDTLS_ECDSA_MAX_LEN -->
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200950
Gilles Peskinef7746bd2023-11-30 14:01:44 +0100951ECDSA is the mechanism provided by `mbedtls_pk_sign` and `mbedtls_pk_verify` for ECDSA keys, as well as by `mbedtls_ecdsa_sign`, `mbedtls_ecdsa_sign_det_ext`, `mbedtls_ecdsa_write_signature`, `mbedtls_ecdsa_verify` and `mbedtls_ecdsa_read_signature`.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200952
953The PSA API offers three algorithm constructors for ECDSA. They differ only for signature, and have exactly the same behavior for verification.
954
955* [`PSA_ALG_ECDSA(hash)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga7e3ce9f514a227d5ba5d8318870452e3) is a randomized ECDSA signature of a hash calculated with the algorithm `hash`.
956* [`PSA_ALG_ECDSA_ANY`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga51d6b6044a62e33cae0cf64bfc3b22a4) is equivalent to `PSA_ALG_ECDSA`, but does not require specifying a hash as part of the algorithm. It can only be used with `psa_sign_hash` and `psa_verify_hash`, with no constraint on the length of the hash.
957* [`PSA_ALG_DETERMINISTIC_ECDSA(hash)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga11da566bcd341661c8de921e2ca5ed03) is a deterministic ECDSA signature of a hash calculated with the algorithm `hash`. This is the same as the functionality offered by `MBEDTLS_ECDSA_DETERMINISTIC` in the legacy API.
958 * For `psa_sign_message` with `PSA_ALG_DETERMINISTIC_ECDSA`, the same hash algorithm is used to hash the message and to parametrize the deterministic signature generation.
959
960Unlike the legacy API, where `mbedtls_pk_sign` and `mbedtls_ecdsa_write_signature` automatically select deterministic ECDSA if both are available, the PSA API requires the application to select the preferred variant. ECDSA verification cannot distinguish between randomized and deterministic ECDSA (except in so far as if the same message is signed twice and the signatures are different, then at least one of the signatures is not the determinstic variant), so in most cases switching between the two is a compatible change.
961
962#### Restartable ECDSA signature
963
Gilles Peskine396a2a32023-11-30 11:02:06 +0100964The legacy API includes an API for restartable ECC operations: the operation returns after doing partial computation, and can be resumed. This is intended for highly constrained devices where long cryptographic calculations need to be broken up to poll some inputs, where interrupt-based scheduling is not desired. The legacy API consists of the functions `mbedtls_pk_sign_restartable`, `mbedtls_pk_verify_restartable`, `mbedtls_ecdsa_sign_restartable`, `mbedtls_ecdsa_verify_restartable`, `mbedtls_ecdsa_write_signature_restartable`, `mbedtls_ecdsa_read_signature_restartable`, as well as several configuration and data manipulation functions.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200965
Gilles Peskine396a2a32023-11-30 11:02:06 +0100966The PSA API offers similar functionality via interruptible public-key operations. As of Mbed TLS 3.5, it is only implemented for ECDSA, for the same curves as the legacy API. This will likely be extended to ECDH in the short term. At the time of writing, no extension is planned to other curves or other algorithms.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200967
968The flow of operations for an interruptible signature operation is as follows:
969
9701. Create an operation object of type [`psa_sign_hash_interruptible_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga6948d4653175b1b530a265540066a7e7) and zero-initialize it (or use the corresponding `INIT` macro).
9712. Call [`psa_sign_hash_start`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga441988da830205182b3e791352537fac) with the private key object and the hash to verify.
9723. Call [`psa_sign_hash_complete`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga79849aaa7004a85d2ffbc4b658a333dd) repeatedly until it returns a status other than `PSA_OPERATION_INCOMPLETE`.
973
974The flow of operations for an interruptible signature verification operation is as follows:
975
9761. Create an operation object of type [`psa_verify_hash_interruptible_operation_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga537054cf4909ad1426331ae4ce7148bb) and zero-initialize it (or use the corresponding `INIT` macro).
9772. Call [`psa_verify_hash_start`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga912eb51fb94056858f451f276ee289cb) with the private key object and the hash and signature to verify.
9783. Call [`psa_verify_hash_complete`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga67fe82352bc2f8c0343e231a70a5bc7d) repeatedly until it returns a status other than `PSA_OPERATION_INCOMPLETE`.
979
Gilles Peskine4d234f12023-11-30 13:59:49 +0100980If you need to cancel the operation after calling the start function without waiting for the loop calling the complete function to finish, call [`psa_sign_hash_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1gae893a4813aa8e03bd201fe4f1bbbb403) or [`psa_verify_hash_abort`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga18dc9c0cc27d590c5e3b186094d90f88).
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200981
Gilles Peskine379ff872023-06-15 21:15:21 +0200982Call [`psa_interruptible_set_max_ops`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga6d86790b31657c13705214f373af869e) to set the number of basic operations per call. This is the same unit as `mbedtls_ecp_set_max_ops`. You can retrieve the current value with [`psa_interruptible_get_max_ops`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible__hash/#group__interruptible__hash_1ga73e66a6d93f2690b626fcea20ada62b2). The value is [`PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__interruptible/#group__interruptible_1gad19c1da7f6b7d59d5873d5b68eb943d4) if operations are not restartable, which corresponds to `mbedtls_ecp_restart_is_enabled()` being false.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200983
984#### PKCS#1 v1.5 RSA signature
985
986This mechanism corresponds to `mbedtls_pk_sign`, `mbedtls_pk_verify`, `mbedtls_rsa_pkcs1_sign` and `mbedtls_rsa_pkcs1_verify` for an RSA key, unless PSS has been selected with `mbedtls_rsa_set_padding` on the underlying RSA key context. This mechanism also corresponds to `mbedtls_rsa_rsassa_pkcs1_v15_sign` and `mbedtls_rsa_rsassa_pkcs1_v15_verify`.
987
988The PSA API has two algorithm constructors:
989
990* [`PSA_ALG_RSA_PKCS1V15_SIGN(hash)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga702ff75385a6ae7d4247033f479439af) formats the hash as specified in PKCS#1. The hash algorithm corresponds to the `md_alg` parameter of the legacy functions.
991* [`PSA_ALG_RSA_PKCS1V15_SIGN_RAW`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga4215e2a78dcf834e9a625927faa2a817) uses the “hash” input in lieu of a DigestInfo structure. This is the same as calling the legacy functions with `md_alg=MBEDTLS_MD_NONE`.
992
993#### PKCS#1 RSASSA-PSS signature
994
995This mechanism corresponds to `mbedtls_pk_sign_ext` and `mbedtls_pk_verify_ext` for an RSA key, as well as `mbedtls_pk_sign`, `mbedtls_pk_verify`, `mbedtls_rsa_pkcs1_sign` and `mbedtls_rsa_pkcs1_verify` if PSS has been selected on the underlying RSA context with `mbedlts_rsa_set_padding`.
996It also corresponds to `mbedtls_rsa_rsassa_pss_sign` and `mbedtls_rsa_rsassa_pss_sign_ext`, `mbedtls_rsa_rsassa_pss_verify` and `mbedtls_rsa_rsassa_pss_verify_ext`.
997
Gilles Peskine951cf392023-11-30 14:01:20 +0100998The PSA API has two algorithm constructors: [`PSA_ALG_RSA_PSS(hash)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga62152bf4cb4bf6aace5e1be8f143564d) and [`PSA_ALG_RSA_PSS_ANY_SALT(hash)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga9b7355a2cd6bde88177634d539127f2b). They differ only for verification, and have exactly the same behavior for signature. The hash algorithm `hash` corresponds to the `md_alg` parameter passed to the legacy API. It is used to hash the message, to create the salted hash, and for the mask generation with MGF1. The PSA API does not support using different hash algorithms for these different purposes.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +0200999
1000With respect to the salt length:
1001
1002* When signing, the salt is random, and the salt length is the largest possible salt length up to the hash length. This is the same as passing `MBEDTLS_RSA_SALT_LEN_ANY` as the salt length to `xxx_ext` legacy functions or using a legacy function that does not have a `saltlen` argument.
1003* When verifying, `PSA_ALG_RSA_PSS` requires the the salt length to the largest possible salt length up to the hash length (i.e. the same that would be used for signing).
1004* When verifying, `PSA_ALG_RSA_PSS_ANY_SALT` accepts any salt length. This is the same as passing `MBEDTLS_RSA_SALT_LEN_ANY` as the salt length to `xxx_ext` legacy functions or using a legacy function that does not have a `saltlen` argument.
1005
1006### Asymmetric encryption and decryption
1007
1008The equivalent of `mbedtls_pk_encrypt`, `mbedtls_rsa_pkcs1_encrypt`, `mbedtls_rsa_rsaes_pkcs1_v15_encrypt` or `mbedtls_rsa_rsaes_oaep_encrypt` to encrypt a short message (typically a symmetric key) is [`psa_asymmetric_encrypt`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__asymmetric/#group__asymmetric_1gaa17f61e4ddafd1823d2c834b3706c290).
Gilles Peskine06002c52023-12-04 22:24:25 +01001009The key must be a public key (or a key pair) allowing the usage `PSA_KEY_USAGE_ENCRYPT` (see “[Public-key cryptography policies](#public-key-cryptography-policies)”).
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001010Use the macro [`PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#crypto__sizes_8h_1a66ba3bd93e5ec52870ccc3848778bad8) or [`PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE) to determine the output buffer size.
1011
1012The equivalent of `mbedtls_pk_decrypt`, `mbedtls_rsa_pkcs1_decrypt`, `mbedtls_rsa_rsaes_pkcs1_v15_decrypt` or `mbedtls_rsa_rsaes_oaep_decrypt` to decrypt a short message (typically a symmetric key) is [`psa_asymmetric_decrypt`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__asymmetric/#group__asymmetric_1ga4f968756f6b22aab362b598b202d83d7).
1013The key must be a key pair allowing the usage `PSA_KEY_USAGE_DECRYPT` (see “[Public-key cryptography policies](#public-key-cryptography-policies)”).
1014Use the macro [`PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#crypto__sizes_8h_1a61a246f3eac41989821d982e56fea6c1) or [`PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE) to determine the output buffer size.
1015
1016The following subsections describe the PSA asymmetric encryption mechanisms that correspond to legacy Mbed TLS mechanisms.
1017
1018#### RSA PKCS#1v1.5 encryption
1019
1020This is the mechanism used by the PK functions and by `mbedtls_rsa_pkcs1_{encrypt,decrypt}` unless `mbedtls_rsa_set_padding` has been called on the underlying RSA key context.
1021This is also the mechanism used by `mbedtls_rsa_rsaes_pkcs1_v15_{encrypt,decrypt}`.
1022
1023The PSA algorithm is [`PSA_ALG_RSA_PKCS1V15_CRYPT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga4c540d3abe43fb9abcb94f2bc51acef9).
1024
1025Beware that PKCS#1v1.5 decryption is subject to padding oracle attacks. Revealing when `psa_asymmetric_decrypt` returns `PSA_ERROR_INVALID_PADDING` may allow an adversary to decrypt arbitrary ciphertexts.
1026
1027#### RSA RSAES-OAEP
1028
1029This is the mechanism used by `mbedtls_rsa_rsaes_oaep_{encrypt,decrypt}`.
1030
1031The PSA algorithm is [`PSA_ALG_RSA_OAEP(hash)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gaa1235dc3fdd9839c6c1b1a9857344c76) where `hash` is a hash algorithm value (`PSA_ALG_xxx`, see “[Hash mechanism selection](#hash-mechanism-selection)”).
1032
1033As with the PK API, the mask generation is MGF1, the label is empty, and the same hash algorithm is used for MGF1 and to hash the label. The PSA API does not offer a way to choose a different label or a different hash algorithm for the label.
1034
Gilles Peskine379ff872023-06-15 21:15:21 +02001035### Private-public key consistency
1036
1037There is no direct equivalent of the functions `mbedtls_rsa_check_privkey`, `mbedtls_rsa_check_pubkey`,`mbedtls_ecp_check_privkey`, `mbedtls_ecp_check_pubkey`. The PSA API performs some basic checks when it imports a key, and may perform additional checks before performing an operation if needed, so it will never perform an operation on a key that does not satisfy these checks, but the details of when the check is performed may change between versions of the library.
1038
Gilles Peskinedfe67072023-11-29 21:12:39 +01001039The legacy API provides functions `mbedtls_pk_check_pair`, `mbedtls_rsa_check_pub_priv` and `mbedtls_ecp_check_pub_priv`, which can be used to check the consistency between a private key and a public key. To perform such a check with the PSA API, you can export the public keys; this works because the PSA representation of public keys is canonical.
Gilles Peskine379ff872023-06-15 21:15:21 +02001040
1041* Prepare a key object containing the private key, for example with [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b).
1042* Prepare a key object containing the public key, for example with [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b).
1043* Export both public keys with [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) (this is possible regardless of the usage policies on the keys) and compare the output.
1044 ```
1045 // Error checking omitted
1046 unsigned char pub1[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
1047 unsigned char pub2[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
1048 size_t length1, length2;
1049 psa_export_public_key(key1, pub1, sizeof(pub1), &length1);
1050 psa_export_public_key(key2, pub2, sizeof(pub2), &length2);
1051 if (length1 == length2 && !memcmp(pub1, pub2, length1))
1052 puts("The keys match");
1053 else
1054 puts("The keys do not match");
1055 ```
1056
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001057### PK functionality with no PSA equivalent
1058
1059There is no PSA equivalent of the debug functionality provided by `mbedtls_pk_debug`. Use `psa_export_key` to export the key if desired.
1060
1061There is no PSA equivalent to Mbed TLS's custom key type names exposed by `mbedtls_pk_get_name`.
1062
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001063### Key agreement
1064
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001065The PSA API has a generic interface for key agreement, covering the main use of both `ecdh.h` and `dhm.h`.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001066
Gilles Peskine06002c52023-12-04 22:24:25 +01001067<!-- TODO: static FFDH/ECDH (including `mbedtls_ecdh_get_params`)
1068 https://github.com/Mbed-TLS/mbedtls/pull/7766#discussion_r1410568541
1069 -->
Gilles Peskined79854b2023-11-30 14:01:59 +01001070
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001071#### Diffie-Hellman key pair management
1072
1073The PSA API manipulates keys as such, rather than via an operation context. Thus, to use Diffie-Hellman, you need to create a key object, then perform the key exchange, then destroy the key. There is no equivalent to the types `mbedtls_ecdh_context` and `mbedtls_dhm_context`.
1074
1075Here is an overview of the lifecycle of a key object.
1076
10771. First define the attributes of the key by filling a [`psa_key_attributes_t` structure](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga0ec645e1fdafe59d591104451ebf5680). You need to set the following parameters:
1078 * Call [`psa_set_key_type`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga6857ef0ecb3fa844d4536939d9c64025) to set the key type to the desired `PSA_KEY_TYPE_xxx` value:
1079 * [`PSA_KEY_TYPE_DH_KEY_PAIR(group)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gab4f857c4cd56f5fe65ded421e61bcc8c) for finite-field Diffie-Hellman (see “[Diffie-Hellman mechanism selection](#diffie-hellman-mechanism-selection)”).
1080 * [`PSA_KEY_TYPE_ECC_KEY_PAIR(curve)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga0b6f5d4d5037c54ffa850d8059c32df0) for elliptic-curve Diffie-Hellman (see “[Elliptic curve mechanism selection](#elliptic-curve-mechanism-selection)”).
1081 * Call [`psa_set_key_bits`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaf61683ac87f87687a40262b5afbfa018) to set the private key size in bits. This is optional with `psa_import_key`, which determines the key size from the length of the key material.
1082 * Call [`psa_set_key_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaeb8341ca52baa0279475ea3fd3bcdc98) to select the appropriate algorithm:
1083 * [`PSA_ALG_ECDH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1gab2dbcf71b63785e7dd7b54a100edee43) or [`PSA_ALG_FFDH`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga0ebbb6f93a05b6511e6f108ffd2d1eb4) for a raw key agreement.
1084 * [`PSA_ALG_KEY_AGREEMENT(ka, kdf)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__crypto__types/#group__crypto__types_1ga78bb81cffb87a635c247725eeb2a2682) if the key will be used as part of a key derivation, where:
1085 * `ka` is either `PSA_ALG_ECDH` or `PSA_ALG_FFDH`.
1086 * `kdf` is a key derivation algorithm.
1087 * Call [`psa_set_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga42a65b3c4522ce9b67ea5ea7720e17de) to enable at least [`PSA_KEY_USAGE_DERIVE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#c.PSA_KEY_USAGE_DERIVE). See “[Public-key cryptography policies](#public-key-cryptography-policies)” for more information.
10882. Call one of the key creation functions, passing the attributes defined in the previous step, to get an identifier of type [`psa_key_id_t`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__types_8h/#_CPPv412psa_key_id_t) to the key object.
1089 * Use [`psa_generate_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga1985eae417dfbccedf50d5fff54ea8c5) to generate a random key. This is normally the case for a Diffie-Hellman key.
1090 * Use [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b) to directly import key material.
1091 * If the key is derived deterministically from other material, use the [key derivation interface](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/) and create the key with [`psa_key_derivation_output_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1gada7a6e17222ea9e7a6be6864a00316e1).
10923. Call the functions in the following sections to perform operations on the key. The same key object can be used in multiple operations.
10934. To free the resources used by the key object, call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) after all operations with that key are finished.
1094
1095#### Performing a key agreement
1096
1097Call [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) to obtain the public key that needs to be sent to the other party.
1098Use the macros [`PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE) or [`PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) to determine the size of the output buffer.
1099
1100Call [`psa_raw_key_agreement`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga90fdd2716124d0bd258826184824675f) to calculate the shared secret from your private key and the other party's public key.
1101Use the macros [`PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE) or [`PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) to determine the size of the output buffer.
1102
1103Call [`psa_key_derivation_key_agreement`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga2cd5a8ac906747d3204ec442db78745f) instead of `psa_raw_key_agreement` to use the resulting shared secret as the secret input to a key derivation. See “[HKDF](#hkdf)” for an example of the key derivation interface.
1104
Gilles Peskine5eeca332023-12-04 22:35:12 +01001105#### Translating a legacy key agreement contextless workflow
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001106
Gilles Peskine5eeca332023-12-04 22:35:12 +01001107A typical workflow for ECDH using the legacy API without a context object is:
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001108
11091. Initialize objects:
1110 * `mbedtls_ecp_group grp` for the curve;
1111 * `mbedtls_mpi our_priv` for our private key;
1112 * `mbedtls_ecp_point our_pub` for our public key;
1113 * `mbedtls_ecp_point their_pub` for their public key (this may be the same variable as `our_pub` if the application does not need to hold both at the same time);
1114 * `mbedtls_mpi z` for the shared secret (this may be the same variable as `our_priv` when doing ephemeral ECDH).
11152. Call `mbedtls_ecp_group_load` on `grp` to select the curve.
11163. Call `mbedtls_ecdh_gen_public` on `grp`, `our_priv` (output) and `our_pub` (output) to generate a key pair and retrieve the corresponding public key.
Gilles Peskinedfe67072023-11-29 21:12:39 +010011174. Send `our_pub` to the peer. Retrieve the peer's public key and import it into `their_pub`. These two actions may be performed in either order.
Gilles Peskine5bd4f172023-06-15 18:33:30 +020011185. Call `mbedtls_ecdh_compute_shared` on `grp`, `z` (output), `their_pub` and `our_priv`.
11196. Use the raw shared secret `z`, typically, to construct a shared key.
11207. Free `grp`, `our_priv`, `our_pub`, `their_pub` and `z`.
1121
Gilles Peskine5eeca332023-12-04 22:35:12 +01001122The corresponding workflow with the PSA API is as follows:
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001123
11241. Initialize objects:
1125 * `psa_key_id_t our_key`: a handle to our key pair;
1126 * `psa_key_attributes_t attributes`: key attributes used in steps 2–3;;
1127 * `our_pub`: a buffer of size [`PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, bits)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE) (where `key_type` is the value passed to `psa_set_key_size` in step 2) or [`PSA_EXPORT_PUBLIC_KEY_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) to hold our key.
1128 * `their_pub`: a buffer of the same size, to hold the peer's key. This can be the same as `our_pub` if the application does not need to hold both at the same time;
1129 * `shared_secret`: a buffer of size [`PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, bits)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE) or [`PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) (if not using a key derivation operation).
Gilles Peskine06002c52023-12-04 22:24:25 +010011302. Prepare an attribute structure as described in “[Diffie-Hellman key pair management](#diffie-hellman-key-pair-management)”, in particular selecting the curve with `psa_set_key_type`.
Gilles Peskine5bd4f172023-06-15 18:33:30 +020011313. Call [`psa_generate_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga1985eae417dfbccedf50d5fff54ea8c5) on `attributes` and `our_key` (output) to generate a key pair, then [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) on `our_key` and `our_pub` (output) to obtain our public key.
Gilles Peskinedfe67072023-11-29 21:12:39 +010011324. Send `our_pub` to the peer. Retrieve the peer's public key and import it into `their_pub`. These two actions may be performed in either order.
Gilles Peskine5bd4f172023-06-15 18:33:30 +020011335. Call [`psa_raw_key_agreement`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga90fdd2716124d0bd258826184824675f) on `our_key`, `their_pub` and `shared_secret` (output).
1134 Alternatively, call `psa_key_derivation_key_agreement` to use the shared secret directly in a key derivation operation (see “[Performing a key agreement](#performing-a-key-agreement)”).
11356. Call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) on `key_id`, and free the memory buffers.
1136
1137Steps 4–5 are only performed once for ephemeral Diffie-Hellman, but repeated multiple times for static Diffie-Hellman.
1138
Gilles Peskine5eeca332023-12-04 22:35:12 +01001139#### Translating a legacy key agreement TLS server workflow
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001140
Gilles Peskine5eeca332023-12-04 22:35:12 +01001141The legacy API offers the following workflow for a Diffie-Hellman key agreement in a TLS server. This workflow can also be used with other protocols, on the side of the party that selects the curve or group and sends its public key first.
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001142
11431. Setup phase:
1144 1. Initialize a context of type `mbedtls_ecdh_context` or `mbedtls_dhm_context` with `mbedtls_ecdh_init` or `mbedtls_dhm_init`.
1145 2. Call `mbedtls_ecdh_setup` or `mbedtls_dhm_set_group` to select the curve or group.
1146 3. Call `mbedtls_ecdh_make_params` or `mbedtls_dhm_make_params` to generate our key pair and obtain a TLS ServerKeyExchange message encoding the selected curve/group and our public key.
11472. Send the ServerKeyExchange message to the peer.
11483. Retrieve the peer's public key.
11494. Call `mbedtls_ecdh_read_public` or `mbedtls_dhm_read_public` on the peer's public key, then call `mbedtls_ecdh_calc_secret` or `mbedtls_dhm_calc_secret` to calculate the shared secret.
11505. Free the context with `mbedtls_ecdh_free` or `mbedtls_dhm_free`.
1151
Gilles Peskine5eeca332023-12-04 22:35:12 +01001152The corresponding workflow with the PSA API is as follows:
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001153
11541. Setup phase:
1155 1. Generate an ECDH or DHM key pair with `psa_generate_key` as described in “[Diffie-Hellman key pair management](#diffie-hellman-key-pair-management)”.
1156 2. Call [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) to obtain our public key.
1157 3. Format a ServerKeyExchange message containing the curve/group selection and our public key.
11582. Send the ServerKeyExchange message to the peer.
11593. Retrieve the peer's public key.
11604. Call [`psa_raw_key_agreement`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga90fdd2716124d0bd258826184824675f) on `our_key`, `their_pub` and `shared_secret` (output).
1161 Alternatively, call `psa_key_derivation_key_agreement` to use the shared secret directly in a key derivation operation (see “[Performing a key agreement](#performing-a-key-agreement)”).
11625. Call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) to free the resources associated with our key pair.
1163
Gilles Peskine5eeca332023-12-04 22:35:12 +01001164#### Translating a legacy key agreement TLS client workflow
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001165
Gilles Peskine5eeca332023-12-04 22:35:12 +01001166The legacy API offers the following workflow for a Diffie-Hellman key agreement in a TLS client. This workflow can also be used with other protocols, on the side of the party that receives a message indicating both the choice of curve or group, and the peer's public key.
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001167
11681. Upon reception of a TLS ServerKeyExchange message received from the peer, which encodes the selected curve/group and the peer's public key:
1169 1. Initialize a context of type `mbedtls_ecdh_context` or `mbedtls_dhm_context` with `mbedtls_ecdh_init` or `mbedtls_dhm_init`.
1170 2. Call `mbedtls_ecdh_read_params` or `mbedtls_dhm_read_params` to input the data from the ServerKeyExchange message.
11712. Call `mbedtls_ecdh_make_public` or `mbedtls_dh_make_public` to generate our private key and export our public key.
11723. Send our public key to the peer.
11734. Call `mbedtls_ecdh_calc_secret` or `mbedtls_dhm_calc_secret` to calculate the shared secret.
11745. Free the context with `mbedtls_ecdh_free` or `mbedtls_dhm_free`.
1175
Gilles Peskine5eeca332023-12-04 22:35:12 +01001176The corresponding workflow with the PSA API is as follows:
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001177
11781. Upon reception of a TLS ServerKeyExchange message received from the peer, which encodes the selected curve/group and the peer's public key:
Gilles Peskinedfe67072023-11-29 21:12:39 +01001179 1. Decode the selected curve/group and use this to determine a PSA key type (`PSA_KEY_TYPE_ECC_KEY_PAIR(curve)` or `PSA_KEY_TYPE_DH_KEY_PAIR(group)`), a key size and an algorithm.
Gilles Peskine5bd4f172023-06-15 18:33:30 +020011802. Generate an ECDH or DHM key pair with `psa_generate_key` as described in “[Diffie-Hellman key pair management](#diffie-hellman-key-pair-management)”.
1181 Call [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) to obtain our public key.
11823. Send our public key to the peer.
11834. Call [`psa_raw_key_agreement`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__derivation/#group__key__derivation_1ga90fdd2716124d0bd258826184824675f) on `our_key`, `their_pub` and `shared_secret` (output).
1184 Alternatively, call `psa_key_derivation_key_agreement` to use the shared secret directly in a key derivation operation (see “[Performing a key agreement](#performing-a-key-agreement)”).
11855. Call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) to free the resources associated with our key pair.
1186
1187#### ECDH and DHM metadata functions
1188
Gilles Peskined79854b2023-11-30 14:01:59 +01001189You can obtain data and metadata from an ECDH key agreement through the PSA API as follows:
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001190
1191* With either side, accessing the group: call [`psa_get_key_attributes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gacbbf5c11eac6cd70c87ffb936e1b9be2) on the key identifier, then [`psa_get_key_type`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gae4fb812af4f57aa1ad85e335a865b918) and [`psa_get_key_bits`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga5bee85c2164ad3d4c0d42501241eeb06) to obtain metadata about the key.
Gilles Peskined79854b2023-11-30 14:01:59 +01001192* Accessing our public key: call [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) on the PSA key identifier.
1193* Accessing our private key: call [`psa_export_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga668e35be8d2852ad3feeef74ac6f75bf) on the key identifier. Note that the key policy must allow `PSA_KEY_USAGE_EXPORT` (see “[Public-key cryptography policies](#public-key-cryptography-policies)”).
1194* Accessing the peer's public key: there is no PSA equivalent since the PSA API only uses the peer's public key to immediately calculate the shared secret. If your application needs the peer's public key for some other purpose, store it separately.
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001195
1196The functions `mbedtls_dhm_get_bitlen`, `mbedtls_dhm_get_len` and `mbedtls_dhm_get_value` allow the caller to obtain metadata about the keys used for the key exchange. The PSA equivalents access the key identifier:
1197
1198* `mbedtls_dhm_get_bitlen`, `mbedtls_dhm_get_len`: call [`psa_get_key_attributes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gacbbf5c11eac6cd70c87ffb936e1b9be2) on the PSA key identifier, then [`psa_get_key_bits`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga5bee85c2164ad3d4c0d42501241eeb06).
1199* `mbedtls_dhm_get_value` for `MBEDTLS_DHM_PARAM_X` (our private key): call [`psa_export_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga668e35be8d2852ad3feeef74ac6f75bf) on the key identifier. Note that the key policy must allow `PSA_KEY_USAGE_EXPORT` (see “[Public-key cryptography policies](#public-key-cryptography-policies)”).
Gilles Peskinedfe67072023-11-29 21:12:39 +01001200* `mbedtls_dhm_get_value` for `MBEDTLS_DHM_PARAM_GX` (our public key): call [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) on the PSA key identifier.
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001201* `mbedtls_dhm_get_value` for `MBEDTLS_DHM_PARAM_GY` (peer's public key): the there is no PSA equivalent since the PSA API only uses the peer's public key to immediately calculate the shared secret. If your application needs the peer's public key for some other purpose, store it separately.
1202* `mbedtls_dhm_get_value` for `MBEDTLS_DHM_PARAM_K` (shared secret): this is the value calculated by `psa_raw_key_agreement` or `psa_key_derivation_key_agreement`. If you need to use it multiple times (for example to derive multiple values independently), call `psa_raw_key_agreement` and make a copy.
1203* `mbedtls_dhm_get_value` for `MBEDTLS_DHM_PARAM_P` or `MBEDTLS_DHM_PARAM_G` (group parameters): [there is no PSA API to retrieve these values](https://github.com/Mbed-TLS/mbedtls/issues/7780).
1204
1205The PSA API for finite-field Diffie-Hellman only supports predefined groups. Therefore there is no equivalent to `mbedtls_dhm_parse_dhm`, `mbedtls_dhm_parse_dhmfile`, and the `MBEDTLS_DHM_xxx_BIN` macros.
1206
1207#### Restartable key agreement
1208
1209Restartable key agreement is not yet available through the PSA API. It will be added in a future version of the library.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001210
1211### Additional information about Elliptic-curve cryptography
1212
Gilles Peskine379ff872023-06-15 21:15:21 +02001213#### Information about a curve
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001214
Gilles Peskine379ff872023-06-15 21:15:21 +02001215The legacy API identifies a curve by an `MBEDTLS_ECP_DP_xxx` value of type `mbedtls_ecp_group_id`. The PSA API identifies a curve by a `PSA_ECC_FAMILY_xxx` value and the private value's bit-size. See “[Elliptic curve mechanism selection](#elliptic-curve-mechanism-selection)” for the correspondence between the two sets of values.
1216
1217There is no PSA equivalent of the `mbedtls_ecp_group` data structure (and so no equivalent to `mbedtls_ecp_group_init`, `mbedtls_ecp_group_load`, `mbedtls_ecp_group_copy` and `mbedtls_ecp_group_free`) or of the `mbedtls_ecp_curve_info` data structure (and so no equivalent to `mbedtls_ecp_curve_info_from_grp_id`) because they are not needed. All API elements identify the curve directly by its family and size.
1218
1219The bit-size used by the PSA API is the size of the private key. For most curves, the PSA bit-size, the `bit_size` field in `mbedtls_ecp_curve_info`, the `nbits` field in `mbedtls_ecp_group` and the `pbits` field in `mbedtls_ecp_group` are the same. The following table lists curves for which they are different.
1220
1221| Curve | `grp->nbits` | `grp->pbits` | `curve_info->bit_size` | PSA bit-size |
1222| ----- | ------------ | ------------ | ---------------------- | ------------ |
Gilles Peskine06002c52023-12-04 22:24:25 +01001223| secp224k1 | 225 | 224 | 224 | not supported |
Gilles Peskine379ff872023-06-15 21:15:21 +02001224| Curve25519 | 253 | 255 | 256 | 255 |
1225| Curve448 | 446 | 448 | 448 | 448 |
1226
1227There is no exact PSA equivalent of the type `mbedtls_ecp_curve_type` and the function `mbedtls_ecp_get_type`, but the curve family encodes the same information. `PSA_ECC_FAMILY_MONTGOMERY` is the only Montgomery family. All other families supported in Mbed TLS 3.4.0 are short Weierstrass families.
1228
1229There is no PSA equivalent for the following functionality:
1230
Gilles Peskine603f0fc2023-06-20 23:38:21 +02001231* The `name` field of `mbedtls_ecp_curve_info`, and the function `mbedtls_ecp_curve_info_from_name`. There is no equivalent of Mbed TLS's lookup based on the name used for the curve in TLS specifications.
Gilles Peskine379ff872023-06-15 21:15:21 +02001232* The `tls_id` field of `mbedtls_ecp_curve_info`, the constant `MBEDTLS_ECP_TLS_NAMED_CURVE`, and the functions `mbedtls_ecp_curve_info_from_tls_id`, `mbedtls_ecp_tls_read_group`, `mbedtls_ecp_tls_read_group_id` and `mbedtls_ecp_tls_write_group`. The PSA crypto API does not have this dedicated support for the TLS protocol.
1233* Retrieving the parameters of a curve from the fields of an `mbedtls_ecp_group` structure.
1234
1235#### Information about supported curves
1236
1237The PSA API does not currently have a discovery mechanism for cryptographic mechanisms (although one may be added in the future). Thus there is no equivalent for `MBEDTLS_ECP_DP_MAX` and the functions `mbedtls_ecp_curve_list` and `mbedtls_ecp_grp_id_list`.
1238
Gilles Peskinedfe67072023-11-29 21:12:39 +01001239The API provides macros that give the maximum supported sizes for various kinds of objects. The following table lists equivalents for `MBEDTLS_ECP_MAX_xxx` macros.
Gilles Peskine379ff872023-06-15 21:15:21 +02001240
1241| Legacy macro | PSA equivalent |
1242| ------------ | -------------- |
1243| `MBEDTLS_ECP_MAX_BITS` | [`PSA_VENDOR_ECC_MAX_CURVE_BITS`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_VENDOR_ECC_MAX_CURVE_BITS) |
1244| `MBEDTLS_ECP_MAX_BYTES` | `PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)` |
1245| `MBEDTLS_ECP_MAX_PT_LEN` | [`PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__sizes_8h/#c.PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE) |
1246
1247#### Restartable ECC
1248
1249The PSA API supports the equivalent of restartable operations, but only for signatures at the time of writing. See “[Restartable ECDSA signature](#restartable-ecdsa-signature)”.
1250
1251There is no PSA API for elliptic curve arithmetic as such, and therefore no equivalent of `mbedtls_ecp_restart_ctx` and functions that operate on it.
1252
1253There is PSA no equivalent of the `MBEDTLS_ECP_OPS_xxx` constants.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001254
1255#### ECC functionality with no PSA equivalent
1256
Gilles Peskine5bd4f172023-06-15 18:33:30 +02001257There is no PSA equivalent of `mbedtls_ecdsa_can_do` and `mbedtls_ecdh_can_do` to query the capabilities of a curve at runtime. Check the documentation of each curve family to see what algorithms it supports.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001258
1259There is no PSA equivalent to the types `mbedtls_ecdsa_context` and `mbedtls_ecdsa_restart_ctx`, and to basic ECDSA context manipulation functions including `mbedtls_ecdsa_from_keypair`, because they are not needed: the PSA API does not have ECDSA-specific context types.
1260
Gilles Peskine379ff872023-06-15 21:15:21 +02001261#### No curve arithmetic
1262
1263The PSA API is a cryptography API, not an arithmetic API. As a consequence, there is no PSA equivalent for the ECC arithmetic functionality exposed by `ecp.h`:
1264
1265* Manipulation of point objects and input-output: the type `mbedtls_ecp_point` and functions operating on it (`mbedtls_ecp_point_xxx`, `mbedtls_ecp_copy`, `mbedtls_ecp_{set,is}_zero`, `mbedtls_ecp_tls_{read,write}_point`). Note that the PSA export format for public keys corresponds to the uncompressed point format (`MBEDTLS_ECP_PF_UNCOMPRESSED`), so [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b), [`psa_export_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga668e35be8d2852ad3feeef74ac6f75bf) and [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) are equivalent to `mbedtls_ecp_point_read_binary` and `mbedtls_ecp_point_write_binary` for uncompressed points. The PSA API does not currently support compressed points, but it is likely that such support will be added in the future.
1266* Manipulation of key pairs as such, with a bridge to bignum arithmetic (`mbedtls_ecp_keypair` type, `mbedtls_ecp_export`). However, the PSA export format for ECC private keys used by [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b), [`psa_export_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga668e35be8d2852ad3feeef74ac6f75bf) is the same as the format used by `mbedtls_ecp_read_key` and `mbedtls_ecp_write_key`.
1267* Elliptic curve arithmetic (`mbedtls_ecp_mul`, `mbedtls_ecp_muladd` and their restartable variants).
1268
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001269### Additional information about RSA
1270
1271#### RSA-ALT interface
1272
1273Implementers of the RSA-ALT interface (`MBEDTLS_PK_RSA_ALT` pk type, `mbedtls_pk_setup_rsa_alt` setup function) should migrate to the [PSA cryptoprocessor driver interface](https://github.com/Mbed-TLS/mbedtls/blob/development/docs/psa-driver-example-and-guide.md).
1274
1275* If the purpose of the ALT interface is acceleration only: use the accelerator driver interface. This is fully transparent to application code.
1276* If the purpose of the ALT interface is to isolate the private key in a high-security environment: use the opaque driver interface. This is mostly transparent to user code. Code that uses a key via its key identifier does not need to know whether the key is transparent (equivalent of `MBEDTLS_PK_RSA`) or opaque (equivalent of `MBEDTLS_PK_RSA_ALT`). When creating a key, it will be transparent by default; to create an opaque key, call [`psa_set_key_lifetime`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gac03ccf09ca6d36cc3d5b43f8303db6f7) to set the key's location to the chosen location value for the driver, e.g.
1277 ```
1278 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
1279 PSA_KEY_PERSISTENCE_VOLATILE, MY_RSA_DRIVER_LOCATION));
1280 ```
1281
Gilles Peskinedfe67072023-11-29 21:12:39 +01001282The PSA subsystem uses its internal random generator both for randomized algorithms and to generate blinding values. As a consequence, none of the API functions take an RNG parameter.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001283
1284#### RSA functionality with no PSA equivalent
1285
Gilles Peskined96aa1b2023-11-29 21:13:02 +01001286The PSA API does not provide direct access to the exponentiation primitive as with `mbedtls_rsa_public` and `mbedtls_rsa_private`. If you need an RSA-based mechanism that is not supported by the PSA API, please [submit an issue on GitHub](https://github.com/ARM-software/psa-api/issues) so that we can extend the API to support it.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001287
1288The PSA API does not support constructing RSA keys progressively from numbers with `mbedtls_rsa_import` or `mbedtls_rsa_import_raw` followed by `mbedtls_rsa_complete`. See “[Importing a PK key by wrapping](#importing-a-pk-key-by-wrapping)”.
1289
1290There is no direct equivalent of `mbedtls_rsa_export`, `mbedtls_rsa_export_raw` and `mbedtls_rsa_export_crt` to export some of the numbers in a key. You can export the whole key with `psa_export_key`, or with `psa_export_public_key` to export the public key from a key pair object. See also “[Exporting a public key or a key pair](#exporting-a-public-key-or-a-key-pair)”.
1291
Gilles Peskine379ff872023-06-15 21:15:21 +02001292A PSA key object is immutable, so there is no need for an equivalent of `mbedtls_rsa_copy`. (There is a function `psa_copy_key`, but it is only useful to make a copy of a key with a different policy of ownership; both concepts are out of scope of this document since they have no equivalent in the legacy API.)
1293
Gilles Peskinedbcfc7d2023-11-30 21:04:06 +01001294### LMS signatures
1295
1296A future version of Mbed TLS will support LMS keys and signatures through the PSA API (`psa_generate_key`, `psa_export_public_key`, `psa_import_key`, `psa_sign_hash`, `psa_verify_hash`, etc.). However, this is likely to happen after Mbed TLS 4.0, therefore the next major version of Mbed TLS will likely keep the existing `lms.h` interface.
1297
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001298### PK format support interfaces
1299
Gilles Peskinedbcfc7d2023-11-30 21:04:06 +01001300The interfaces in `base64.h`, `asn1.h`, `asn1write.h`, `oid.h` and `pem.h` are intended to support X.509 and key file formats. They have no PSA equivalent since they are not directly about cryptography.
1301
1302In Mbed TLS 4.0, we are planning to keep the ASN.1 interfaces mostly unchanged. The evolution of Base64, OID and PEM as separate interfaces is still undecided at the time of writing.
Gilles Peskine5ad8ca22023-06-13 19:49:18 +02001303
1304## EC-JPAKE
1305
1306The PSA API exposes EC-JPAKE via the algorithm [`PSA_ALG_JPAKE`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__extra_8h/#c.PSA_ALG_JPAKE) and the PAKE API functions. At the time of writing, the PAKE API is still experimental, but it should offer the same functionality as the legacy `ecjpake.h`. Please consult the documentation of your version of Mbed TLS for more information.