xref: /optee_os/lib/libmbedtls/mbedtls/library/psa_crypto.c (revision cb03400251f98aed22a2664509e3ed9e183800b0)
1b0563631STom Van Eyck /*
2b0563631STom Van Eyck  *  PSA crypto layer on top of Mbed TLS crypto
3b0563631STom Van Eyck  */
4b0563631STom Van Eyck /*
5b0563631STom Van Eyck  *  Copyright The Mbed TLS Contributors
6b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7b0563631STom Van Eyck  */
8b0563631STom Van Eyck 
9b0563631STom Van Eyck #include "common.h"
10b0563631STom Van Eyck #include "psa_crypto_core_common.h"
11b0563631STom Van Eyck 
12b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
13b0563631STom Van Eyck 
14b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
15b0563631STom Van Eyck #include "check_crypto_config.h"
16b0563631STom Van Eyck #endif
17b0563631STom Van Eyck 
18b0563631STom Van Eyck #include "psa/crypto.h"
19b0563631STom Van Eyck #include "psa/crypto_values.h"
20b0563631STom Van Eyck 
21b0563631STom Van Eyck #include "psa_crypto_cipher.h"
22b0563631STom Van Eyck #include "psa_crypto_core.h"
23b0563631STom Van Eyck #include "psa_crypto_invasive.h"
24b0563631STom Van Eyck #include "psa_crypto_driver_wrappers.h"
25b0563631STom Van Eyck #include "psa_crypto_driver_wrappers_no_static.h"
26b0563631STom Van Eyck #include "psa_crypto_ecp.h"
27b0563631STom Van Eyck #include "psa_crypto_ffdh.h"
28b0563631STom Van Eyck #include "psa_crypto_hash.h"
29b0563631STom Van Eyck #include "psa_crypto_mac.h"
30b0563631STom Van Eyck #include "psa_crypto_rsa.h"
31b0563631STom Van Eyck #include "psa_crypto_ecp.h"
32b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
33b0563631STom Van Eyck #include "psa_crypto_se.h"
34b0563631STom Van Eyck #endif
35b0563631STom Van Eyck #include "psa_crypto_slot_management.h"
36b0563631STom Van Eyck /* Include internal declarations that are useful for implementing persistently
37b0563631STom Van Eyck  * stored keys. */
38b0563631STom Van Eyck #include "psa_crypto_storage.h"
39b0563631STom Van Eyck 
40b0563631STom Van Eyck #include "psa_crypto_random_impl.h"
41b0563631STom Van Eyck 
42b0563631STom Van Eyck #include <stdlib.h>
43b0563631STom Van Eyck #include <string.h>
44b0563631STom Van Eyck #include "mbedtls/platform.h"
45b0563631STom Van Eyck 
46b0563631STom Van Eyck #include "mbedtls/aes.h"
47b0563631STom Van Eyck #include "mbedtls/asn1.h"
48b0563631STom Van Eyck #include "mbedtls/asn1write.h"
49b0563631STom Van Eyck #include "mbedtls/bignum.h"
50b0563631STom Van Eyck #include "mbedtls/camellia.h"
51b0563631STom Van Eyck #include "mbedtls/chacha20.h"
52b0563631STom Van Eyck #include "mbedtls/chachapoly.h"
53b0563631STom Van Eyck #include "mbedtls/cipher.h"
54b0563631STom Van Eyck #include "mbedtls/ccm.h"
55b0563631STom Van Eyck #include "mbedtls/cmac.h"
56b0563631STom Van Eyck #include "mbedtls/constant_time.h"
57b0563631STom Van Eyck #include "mbedtls/des.h"
58b0563631STom Van Eyck #include "mbedtls/ecdh.h"
59b0563631STom Van Eyck #include "mbedtls/ecp.h"
60b0563631STom Van Eyck #include "mbedtls/entropy.h"
61b0563631STom Van Eyck #include "mbedtls/error.h"
62b0563631STom Van Eyck #include "mbedtls/gcm.h"
63b0563631STom Van Eyck #include "mbedtls/md5.h"
64b0563631STom Van Eyck #include "mbedtls/pk.h"
65b0563631STom Van Eyck #include "pk_wrap.h"
66b0563631STom Van Eyck #include "mbedtls/platform_util.h"
67b0563631STom Van Eyck #include "mbedtls/error.h"
68b0563631STom Van Eyck #include "mbedtls/ripemd160.h"
69b0563631STom Van Eyck #include "mbedtls/rsa.h"
70b0563631STom Van Eyck #include "mbedtls/sha1.h"
71b0563631STom Van Eyck #include "mbedtls/sha256.h"
72b0563631STom Van Eyck #include "mbedtls/sha512.h"
73b0563631STom Van Eyck #include "mbedtls/psa_util.h"
74b0563631STom Van Eyck #include "mbedtls/threading.h"
75b0563631STom Van Eyck 
76b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) ||          \
77b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) ||  \
78b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
79b0563631STom Van Eyck #define BUILTIN_ALG_ANY_HKDF 1
80b0563631STom Van Eyck #endif
81b0563631STom Van Eyck 
82b0563631STom Van Eyck /****************************************************************/
83b0563631STom Van Eyck /* Global data, support functions and library management */
84b0563631STom Van Eyck /****************************************************************/
85b0563631STom Van Eyck 
86b0563631STom Van Eyck static int key_type_is_raw_bytes(psa_key_type_t type)
87b0563631STom Van Eyck {
88b0563631STom Van Eyck     return PSA_KEY_TYPE_IS_UNSTRUCTURED(type);
89b0563631STom Van Eyck }
90b0563631STom Van Eyck 
91b0563631STom Van Eyck /* Values for psa_global_data_t::rng_state */
92b0563631STom Van Eyck #define RNG_NOT_INITIALIZED 0
93b0563631STom Van Eyck #define RNG_INITIALIZED 1
94b0563631STom Van Eyck #define RNG_SEEDED 2
95b0563631STom Van Eyck 
96b0563631STom Van Eyck /* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized
97b0563631STom Van Eyck  * variables as arguments. */
98b0563631STom Van Eyck typedef enum {
99b0563631STom Van Eyck     PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1,
100b0563631STom Van Eyck     PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS,
101b0563631STom Van Eyck     PSA_CRYPTO_SUBSYSTEM_RNG,
102b0563631STom Van Eyck     PSA_CRYPTO_SUBSYSTEM_TRANSACTION,
103b0563631STom Van Eyck } mbedtls_psa_crypto_subsystem;
104b0563631STom Van Eyck 
105b0563631STom Van Eyck /* Initialization flags for global_data::initialized */
106b0563631STom Van Eyck #define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED    0x01
107b0563631STom Van Eyck #define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED          0x02
108b0563631STom Van Eyck #define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED        0x04
109b0563631STom Van Eyck 
110b0563631STom Van Eyck #define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED                ( \
111b0563631STom Van Eyck         PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \
112b0563631STom Van Eyck         PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \
113b0563631STom Van Eyck         PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)
114b0563631STom Van Eyck 
115b0563631STom Van Eyck typedef struct {
116b0563631STom Van Eyck     uint8_t initialized;
117b0563631STom Van Eyck     uint8_t rng_state;
118b0563631STom Van Eyck     mbedtls_psa_random_context_t rng;
119b0563631STom Van Eyck } psa_global_data_t;
120b0563631STom Van Eyck 
121b0563631STom Van Eyck static psa_global_data_t global_data;
122b0563631STom Van Eyck 
123b0563631STom Van Eyck static uint8_t psa_get_initialized(void)
124b0563631STom Van Eyck {
125b0563631STom Van Eyck     uint8_t initialized;
126b0563631STom Van Eyck 
127b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
128b0563631STom Van Eyck     mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
129b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
130b0563631STom Van Eyck 
131b0563631STom Van Eyck     initialized = global_data.rng_state == RNG_SEEDED;
132b0563631STom Van Eyck 
133b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
134b0563631STom Van Eyck     mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
135b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
136b0563631STom Van Eyck 
137b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
138b0563631STom Van Eyck     mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
139b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
140b0563631STom Van Eyck 
141b0563631STom Van Eyck     initialized =
142b0563631STom Van Eyck         (initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED));
143b0563631STom Van Eyck 
144b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
145b0563631STom Van Eyck     mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
146b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
147b0563631STom Van Eyck 
148b0563631STom Van Eyck     return initialized;
149b0563631STom Van Eyck }
150b0563631STom Van Eyck 
151b0563631STom Van Eyck static uint8_t psa_get_drivers_initialized(void)
152b0563631STom Van Eyck {
153b0563631STom Van Eyck     uint8_t initialized;
154b0563631STom Van Eyck 
155b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
156b0563631STom Van Eyck     mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
157b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
158b0563631STom Van Eyck 
159b0563631STom Van Eyck     initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0;
160b0563631STom Van Eyck 
161b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
162b0563631STom Van Eyck     mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
163b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
164b0563631STom Van Eyck 
165b0563631STom Van Eyck     return initialized;
166b0563631STom Van Eyck }
167b0563631STom Van Eyck 
168b0563631STom Van Eyck #define GUARD_MODULE_INITIALIZED        \
169b0563631STom Van Eyck     if (psa_get_initialized() == 0)     \
170b0563631STom Van Eyck     return PSA_ERROR_BAD_STATE;
171b0563631STom Van Eyck 
172b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
173b0563631STom Van Eyck 
174b0563631STom Van Eyck /* Declare a local copy of an input buffer and a variable that will be used
175b0563631STom Van Eyck  * to store a pointer to the start of the buffer.
176b0563631STom Van Eyck  *
177b0563631STom Van Eyck  * Note: This macro must be called before any operations which may jump to
178b0563631STom Van Eyck  * the exit label, so that the local input copy object is safe to be freed.
179b0563631STom Van Eyck  *
180b0563631STom Van Eyck  * Assumptions:
181b0563631STom Van Eyck  * - input is the name of a pointer to the buffer to be copied
182b0563631STom Van Eyck  * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope
183b0563631STom Van Eyck  * - input_copy_name is a name that is unused in the current scope
184b0563631STom Van Eyck  */
185b0563631STom Van Eyck #define LOCAL_INPUT_DECLARE(input, input_copy_name) \
186b0563631STom Van Eyck     psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \
187b0563631STom Van Eyck     const uint8_t *input_copy_name = NULL;
188b0563631STom Van Eyck 
189b0563631STom Van Eyck /* Allocate a copy of the buffer input and set the pointer input_copy to
190b0563631STom Van Eyck  * point to the start of the copy.
191b0563631STom Van Eyck  *
192b0563631STom Van Eyck  * Assumptions:
193b0563631STom Van Eyck  * - psa_status_t status exists
194b0563631STom Van Eyck  * - An exit label is declared
195b0563631STom Van Eyck  * - input is the name of a pointer to the buffer to be copied
196b0563631STom Van Eyck  * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called
197b0563631STom Van Eyck  */
198b0563631STom Van Eyck #define LOCAL_INPUT_ALLOC(input, length, input_copy) \
199b0563631STom Van Eyck     status = psa_crypto_local_input_alloc(input, length, \
200b0563631STom Van Eyck                                           &LOCAL_INPUT_COPY_OF_##input); \
201b0563631STom Van Eyck     if (status != PSA_SUCCESS) { \
202b0563631STom Van Eyck         goto exit; \
203b0563631STom Van Eyck     } \
204b0563631STom Van Eyck     input_copy = LOCAL_INPUT_COPY_OF_##input.buffer;
205b0563631STom Van Eyck 
206b0563631STom Van Eyck /* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC()
207b0563631STom Van Eyck  *
208b0563631STom Van Eyck  * Assumptions:
209b0563631STom Van Eyck  * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC()
210b0563631STom Van Eyck  * - input is the name of the original buffer that was copied
211b0563631STom Van Eyck  */
212b0563631STom Van Eyck #define LOCAL_INPUT_FREE(input, input_copy) \
213b0563631STom Van Eyck     input_copy = NULL; \
214b0563631STom Van Eyck     psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input);
215b0563631STom Van Eyck 
216b0563631STom Van Eyck /* Declare a local copy of an output buffer and a variable that will be used
217b0563631STom Van Eyck  * to store a pointer to the start of the buffer.
218b0563631STom Van Eyck  *
219b0563631STom Van Eyck  * Note: This macro must be called before any operations which may jump to
220b0563631STom Van Eyck  * the exit label, so that the local output copy object is safe to be freed.
221b0563631STom Van Eyck  *
222b0563631STom Van Eyck  * Assumptions:
223b0563631STom Van Eyck  * - output is the name of a pointer to the buffer to be copied
224b0563631STom Van Eyck  * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope
225b0563631STom Van Eyck  * - output_copy_name is a name that is unused in the current scope
226b0563631STom Van Eyck  */
227b0563631STom Van Eyck #define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \
228b0563631STom Van Eyck     psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \
229b0563631STom Van Eyck     uint8_t *output_copy_name = NULL;
230b0563631STom Van Eyck 
231b0563631STom Van Eyck /* Allocate a copy of the buffer output and set the pointer output_copy to
232b0563631STom Van Eyck  * point to the start of the copy.
233b0563631STom Van Eyck  *
234b0563631STom Van Eyck  * Assumptions:
235b0563631STom Van Eyck  * - psa_status_t status exists
236b0563631STom Van Eyck  * - An exit label is declared
237b0563631STom Van Eyck  * - output is the name of a pointer to the buffer to be copied
238b0563631STom Van Eyck  * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called
239b0563631STom Van Eyck  */
240b0563631STom Van Eyck #define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \
241b0563631STom Van Eyck     status = psa_crypto_local_output_alloc(output, length, \
242b0563631STom Van Eyck                                            &LOCAL_OUTPUT_COPY_OF_##output); \
243b0563631STom Van Eyck     if (status != PSA_SUCCESS) { \
244b0563631STom Van Eyck         goto exit; \
245b0563631STom Van Eyck     } \
246b0563631STom Van Eyck     output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer;
247b0563631STom Van Eyck 
248b0563631STom Van Eyck /* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC()
249b0563631STom Van Eyck  * after first copying back its contents to the original buffer.
250b0563631STom Van Eyck  *
251b0563631STom Van Eyck  * Assumptions:
252b0563631STom Van Eyck  * - psa_status_t status exists
253b0563631STom Van Eyck  * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC()
254b0563631STom Van Eyck  * - output is the name of the original buffer that was copied
255b0563631STom Van Eyck  */
256b0563631STom Van Eyck #define LOCAL_OUTPUT_FREE(output, output_copy) \
257b0563631STom Van Eyck     output_copy = NULL; \
258b0563631STom Van Eyck     do { \
259b0563631STom Van Eyck         psa_status_t local_output_status; \
260b0563631STom Van Eyck         local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \
261b0563631STom Van Eyck         if (local_output_status != PSA_SUCCESS) { \
262b0563631STom Van Eyck             /* Since this error case is an internal error, it's more serious than \
263b0563631STom Van Eyck              * any existing error code and so it's fine to overwrite the existing \
264b0563631STom Van Eyck              * status. */ \
265b0563631STom Van Eyck             status = local_output_status; \
266b0563631STom Van Eyck         } \
267b0563631STom Van Eyck     } while (0)
268b0563631STom Van Eyck #else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */
269b0563631STom Van Eyck #define LOCAL_INPUT_DECLARE(input, input_copy_name) \
270b0563631STom Van Eyck     const uint8_t *input_copy_name = NULL;
271b0563631STom Van Eyck #define LOCAL_INPUT_ALLOC(input, length, input_copy) \
272b0563631STom Van Eyck     input_copy = input;
273b0563631STom Van Eyck #define LOCAL_INPUT_FREE(input, input_copy) \
274b0563631STom Van Eyck     input_copy = NULL;
275b0563631STom Van Eyck #define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \
276b0563631STom Van Eyck     uint8_t *output_copy_name = NULL;
277b0563631STom Van Eyck #define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \
278b0563631STom Van Eyck     output_copy = output;
279b0563631STom Van Eyck #define LOCAL_OUTPUT_FREE(output, output_copy) \
280b0563631STom Van Eyck     output_copy = NULL;
281b0563631STom Van Eyck #endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */
282b0563631STom Van Eyck 
283b0563631STom Van Eyck 
284b0563631STom Van Eyck int psa_can_do_hash(psa_algorithm_t hash_alg)
285b0563631STom Van Eyck {
286b0563631STom Van Eyck     (void) hash_alg;
287b0563631STom Van Eyck     return psa_get_drivers_initialized();
288b0563631STom Van Eyck }
289b0563631STom Van Eyck 
290b0563631STom Van Eyck int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg)
291b0563631STom Van Eyck {
292b0563631STom Van Eyck     (void) key_type;
293b0563631STom Van Eyck     (void) cipher_alg;
294b0563631STom Van Eyck     return psa_get_drivers_initialized();
295b0563631STom Van Eyck }
296b0563631STom Van Eyck 
297b0563631STom Van Eyck 
298b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) ||       \
299b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) ||     \
300b0563631STom Van Eyck     defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
301b0563631STom Van Eyck static int psa_is_dh_key_size_valid(size_t bits)
302b0563631STom Van Eyck {
303b0563631STom Van Eyck     switch (bits) {
304b0563631STom Van Eyck #if defined(PSA_WANT_DH_RFC7919_2048)
305b0563631STom Van Eyck         case 2048:
306b0563631STom Van Eyck             return 1;
307b0563631STom Van Eyck #endif /* PSA_WANT_DH_RFC7919_2048 */
308b0563631STom Van Eyck #if defined(PSA_WANT_DH_RFC7919_3072)
309b0563631STom Van Eyck         case 3072:
310b0563631STom Van Eyck             return 1;
311b0563631STom Van Eyck #endif /* PSA_WANT_DH_RFC7919_3072 */
312b0563631STom Van Eyck #if defined(PSA_WANT_DH_RFC7919_4096)
313b0563631STom Van Eyck         case 4096:
314b0563631STom Van Eyck             return 1;
315b0563631STom Van Eyck #endif /* PSA_WANT_DH_RFC7919_4096 */
316b0563631STom Van Eyck #if defined(PSA_WANT_DH_RFC7919_6144)
317b0563631STom Van Eyck         case 6144:
318b0563631STom Van Eyck             return 1;
319b0563631STom Van Eyck #endif /* PSA_WANT_DH_RFC7919_6144 */
320b0563631STom Van Eyck #if defined(PSA_WANT_DH_RFC7919_8192)
321b0563631STom Van Eyck         case 8192:
322b0563631STom Van Eyck             return 1;
323b0563631STom Van Eyck #endif /* PSA_WANT_DH_RFC7919_8192 */
324b0563631STom Van Eyck         default:
325b0563631STom Van Eyck             return 0;
326b0563631STom Van Eyck     }
327b0563631STom Van Eyck }
328b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT ||
329b0563631STom Van Eyck           MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||
330b0563631STom Van Eyck           PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */
331b0563631STom Van Eyck 
332b0563631STom Van Eyck psa_status_t mbedtls_to_psa_error(int ret)
333b0563631STom Van Eyck {
334b0563631STom Van Eyck     /* Mbed TLS error codes can combine a high-level error code and a
335b0563631STom Van Eyck      * low-level error code. The low-level error usually reflects the
336b0563631STom Van Eyck      * root cause better, so dispatch on that preferably. */
337b0563631STom Van Eyck     int low_level_ret = -(-ret & 0x007f);
338b0563631STom Van Eyck     switch (low_level_ret != 0 ? low_level_ret : ret) {
339b0563631STom Van Eyck         case 0:
340b0563631STom Van Eyck             return PSA_SUCCESS;
341b0563631STom Van Eyck 
342b0563631STom Van Eyck #if defined(MBEDTLS_AES_C)
343b0563631STom Van Eyck         case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH:
344b0563631STom Van Eyck         case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH:
345b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
346b0563631STom Van Eyck         case MBEDTLS_ERR_AES_BAD_INPUT_DATA:
347b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
348b0563631STom Van Eyck #endif
349b0563631STom Van Eyck 
350b0563631STom Van Eyck #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_ASN1_WRITE_C)
351b0563631STom Van Eyck         case MBEDTLS_ERR_ASN1_OUT_OF_DATA:
352b0563631STom Van Eyck         case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG:
353b0563631STom Van Eyck         case MBEDTLS_ERR_ASN1_INVALID_LENGTH:
354b0563631STom Van Eyck         case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH:
355b0563631STom Van Eyck         case MBEDTLS_ERR_ASN1_INVALID_DATA:
356b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
357b0563631STom Van Eyck         case MBEDTLS_ERR_ASN1_ALLOC_FAILED:
358b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
359b0563631STom Van Eyck         case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL:
360b0563631STom Van Eyck             return PSA_ERROR_BUFFER_TOO_SMALL;
361b0563631STom Van Eyck #endif
362b0563631STom Van Eyck 
363b0563631STom Van Eyck #if defined(MBEDTLS_CAMELLIA_C)
364b0563631STom Van Eyck         case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA:
365b0563631STom Van Eyck         case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH:
366b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
367b0563631STom Van Eyck #endif
368b0563631STom Van Eyck 
369b0563631STom Van Eyck #if defined(MBEDTLS_CCM_C)
370b0563631STom Van Eyck         case MBEDTLS_ERR_CCM_BAD_INPUT:
371b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
372b0563631STom Van Eyck         case MBEDTLS_ERR_CCM_AUTH_FAILED:
373b0563631STom Van Eyck             return PSA_ERROR_INVALID_SIGNATURE;
374b0563631STom Van Eyck #endif
375b0563631STom Van Eyck 
376b0563631STom Van Eyck #if defined(MBEDTLS_CHACHA20_C)
377b0563631STom Van Eyck         case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA:
378b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
379b0563631STom Van Eyck #endif
380b0563631STom Van Eyck 
381b0563631STom Van Eyck #if defined(MBEDTLS_CHACHAPOLY_C)
382b0563631STom Van Eyck         case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE:
383b0563631STom Van Eyck             return PSA_ERROR_BAD_STATE;
384b0563631STom Van Eyck         case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED:
385b0563631STom Van Eyck             return PSA_ERROR_INVALID_SIGNATURE;
386b0563631STom Van Eyck #endif
387b0563631STom Van Eyck 
388b0563631STom Van Eyck #if defined(MBEDTLS_CIPHER_C)
389b0563631STom Van Eyck         case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:
390b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
391b0563631STom Van Eyck         case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA:
392b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
393b0563631STom Van Eyck         case MBEDTLS_ERR_CIPHER_ALLOC_FAILED:
394b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
395b0563631STom Van Eyck         case MBEDTLS_ERR_CIPHER_INVALID_PADDING:
396b0563631STom Van Eyck             return PSA_ERROR_INVALID_PADDING;
397b0563631STom Van Eyck         case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED:
398b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
399b0563631STom Van Eyck         case MBEDTLS_ERR_CIPHER_AUTH_FAILED:
400b0563631STom Van Eyck             return PSA_ERROR_INVALID_SIGNATURE;
401b0563631STom Van Eyck         case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT:
402b0563631STom Van Eyck             return PSA_ERROR_CORRUPTION_DETECTED;
403b0563631STom Van Eyck #endif
404b0563631STom Van Eyck 
405b0563631STom Van Eyck #if !(defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) ||      \
406b0563631STom Van Eyck             defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE))
407b0563631STom Van Eyck         /* Only check CTR_DRBG error codes if underlying mbedtls_xxx
408b0563631STom Van Eyck          * functions are passed a CTR_DRBG instance. */
409b0563631STom Van Eyck         case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
410b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_ENTROPY;
411b0563631STom Van Eyck         case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG:
412b0563631STom Van Eyck         case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG:
413b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
414b0563631STom Van Eyck         case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR:
415b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_ENTROPY;
416b0563631STom Van Eyck #endif
417b0563631STom Van Eyck 
418b0563631STom Van Eyck #if defined(MBEDTLS_DES_C)
419b0563631STom Van Eyck         case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH:
420b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
421b0563631STom Van Eyck #endif
422b0563631STom Van Eyck 
423b0563631STom Van Eyck         case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED:
424b0563631STom Van Eyck         case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE:
425b0563631STom Van Eyck         case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED:
426b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_ENTROPY;
427b0563631STom Van Eyck 
428b0563631STom Van Eyck #if defined(MBEDTLS_GCM_C)
429b0563631STom Van Eyck         case MBEDTLS_ERR_GCM_AUTH_FAILED:
430b0563631STom Van Eyck             return PSA_ERROR_INVALID_SIGNATURE;
431b0563631STom Van Eyck         case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL:
432b0563631STom Van Eyck             return PSA_ERROR_BUFFER_TOO_SMALL;
433b0563631STom Van Eyck         case MBEDTLS_ERR_GCM_BAD_INPUT:
434b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
435b0563631STom Van Eyck #endif
436b0563631STom Van Eyck 
437b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) &&        \
438b0563631STom Van Eyck             defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
439b0563631STom Van Eyck         /* Only check HMAC_DRBG error codes if underlying mbedtls_xxx
440b0563631STom Van Eyck          * functions are passed a HMAC_DRBG instance. */
441b0563631STom Van Eyck         case MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED:
442b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_ENTROPY;
443b0563631STom Van Eyck         case MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG:
444b0563631STom Van Eyck         case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG:
445b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
446b0563631STom Van Eyck         case MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR:
447b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_ENTROPY;
448b0563631STom Van Eyck #endif
449b0563631STom Van Eyck 
450b0563631STom Van Eyck #if defined(MBEDTLS_MD_LIGHT)
451b0563631STom Van Eyck         case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:
452b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
453b0563631STom Van Eyck         case MBEDTLS_ERR_MD_BAD_INPUT_DATA:
454b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
455b0563631STom Van Eyck         case MBEDTLS_ERR_MD_ALLOC_FAILED:
456b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
457b0563631STom Van Eyck #if defined(MBEDTLS_FS_IO)
458b0563631STom Van Eyck         case MBEDTLS_ERR_MD_FILE_IO_ERROR:
459b0563631STom Van Eyck             return PSA_ERROR_STORAGE_FAILURE;
460b0563631STom Van Eyck #endif
461b0563631STom Van Eyck #endif
462b0563631STom Van Eyck 
463b0563631STom Van Eyck #if defined(MBEDTLS_BIGNUM_C)
464b0563631STom Van Eyck #if defined(MBEDTLS_FS_IO)
465b0563631STom Van Eyck         case MBEDTLS_ERR_MPI_FILE_IO_ERROR:
466b0563631STom Van Eyck             return PSA_ERROR_STORAGE_FAILURE;
467b0563631STom Van Eyck #endif
468b0563631STom Van Eyck         case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
469b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
470b0563631STom Van Eyck         case MBEDTLS_ERR_MPI_INVALID_CHARACTER:
471b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
472b0563631STom Van Eyck         case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
473b0563631STom Van Eyck             return PSA_ERROR_BUFFER_TOO_SMALL;
474b0563631STom Van Eyck         case MBEDTLS_ERR_MPI_NEGATIVE_VALUE:
475b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
476b0563631STom Van Eyck         case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO:
477b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
478b0563631STom Van Eyck         case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE:
479b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
480b0563631STom Van Eyck         case MBEDTLS_ERR_MPI_ALLOC_FAILED:
481b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
482b0563631STom Van Eyck #endif
483b0563631STom Van Eyck 
484b0563631STom Van Eyck #if defined(MBEDTLS_PK_C)
485b0563631STom Van Eyck         case MBEDTLS_ERR_PK_ALLOC_FAILED:
486b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
487b0563631STom Van Eyck         case MBEDTLS_ERR_PK_TYPE_MISMATCH:
488b0563631STom Van Eyck         case MBEDTLS_ERR_PK_BAD_INPUT_DATA:
489b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
490b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || defined(MBEDTLS_FS_IO) || \
491b0563631STom Van Eyck             defined(MBEDTLS_PSA_ITS_FILE_C)
492b0563631STom Van Eyck         case MBEDTLS_ERR_PK_FILE_IO_ERROR:
493b0563631STom Van Eyck             return PSA_ERROR_STORAGE_FAILURE;
494b0563631STom Van Eyck #endif
495b0563631STom Van Eyck         case MBEDTLS_ERR_PK_KEY_INVALID_VERSION:
496b0563631STom Van Eyck         case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT:
497b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
498b0563631STom Van Eyck         case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG:
499b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
500b0563631STom Van Eyck         case MBEDTLS_ERR_PK_PASSWORD_REQUIRED:
501b0563631STom Van Eyck         case MBEDTLS_ERR_PK_PASSWORD_MISMATCH:
502b0563631STom Van Eyck             return PSA_ERROR_NOT_PERMITTED;
503b0563631STom Van Eyck         case MBEDTLS_ERR_PK_INVALID_PUBKEY:
504b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
505b0563631STom Van Eyck         case MBEDTLS_ERR_PK_INVALID_ALG:
506b0563631STom Van Eyck         case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE:
507b0563631STom Van Eyck         case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE:
508b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
509b0563631STom Van Eyck         case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH:
510b0563631STom Van Eyck             return PSA_ERROR_INVALID_SIGNATURE;
511b0563631STom Van Eyck         case MBEDTLS_ERR_PK_BUFFER_TOO_SMALL:
512b0563631STom Van Eyck             return PSA_ERROR_BUFFER_TOO_SMALL;
513b0563631STom Van Eyck #endif
514b0563631STom Van Eyck 
515b0563631STom Van Eyck         case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED:
516b0563631STom Van Eyck             return PSA_ERROR_HARDWARE_FAILURE;
517b0563631STom Van Eyck         case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
518b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
519b0563631STom Van Eyck 
520b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
521b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_BAD_INPUT_DATA:
522b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
523b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_INVALID_PADDING:
524b0563631STom Van Eyck             return PSA_ERROR_INVALID_PADDING;
525b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_KEY_GEN_FAILED:
526b0563631STom Van Eyck             return PSA_ERROR_HARDWARE_FAILURE;
527b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED:
528b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
529b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_PUBLIC_FAILED:
530b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_PRIVATE_FAILED:
531b0563631STom Van Eyck             return PSA_ERROR_CORRUPTION_DETECTED;
532b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_VERIFY_FAILED:
533b0563631STom Van Eyck             return PSA_ERROR_INVALID_SIGNATURE;
534b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
535b0563631STom Van Eyck             return PSA_ERROR_BUFFER_TOO_SMALL;
536b0563631STom Van Eyck         case MBEDTLS_ERR_RSA_RNG_FAILED:
537b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_ENTROPY;
538b0563631STom Van Eyck #endif
539b0563631STom Van Eyck 
540b0563631STom Van Eyck #if defined(MBEDTLS_ECP_LIGHT)
541b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
542b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_INVALID_KEY:
543b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
544b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
545b0563631STom Van Eyck             return PSA_ERROR_BUFFER_TOO_SMALL;
546b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:
547b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
548b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:
549b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_VERIFY_FAILED:
550b0563631STom Van Eyck             return PSA_ERROR_INVALID_SIGNATURE;
551b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_ALLOC_FAILED:
552b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
553b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_RANDOM_FAILED:
554b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_ENTROPY;
555b0563631STom Van Eyck 
556b0563631STom Van Eyck #if defined(MBEDTLS_ECP_RESTARTABLE)
557b0563631STom Van Eyck         case MBEDTLS_ERR_ECP_IN_PROGRESS:
558b0563631STom Van Eyck             return PSA_OPERATION_INCOMPLETE;
559b0563631STom Van Eyck #endif
560b0563631STom Van Eyck #endif
561b0563631STom Van Eyck 
562b0563631STom Van Eyck         case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
563b0563631STom Van Eyck             return PSA_ERROR_CORRUPTION_DETECTED;
564b0563631STom Van Eyck 
565b0563631STom Van Eyck         default:
566b0563631STom Van Eyck             return PSA_ERROR_GENERIC_ERROR;
567b0563631STom Van Eyck     }
568b0563631STom Van Eyck }
569b0563631STom Van Eyck 
570b0563631STom Van Eyck /**
571b0563631STom Van Eyck  * \brief                       For output buffers which contain "tags"
572b0563631STom Van Eyck  *                              (outputs that may be checked for validity like
573b0563631STom Van Eyck  *                              hashes, MACs and signatures), fill the unused
574b0563631STom Van Eyck  *                              part of the output buffer (the whole buffer on
575b0563631STom Van Eyck  *                              error, the trailing part on success) with
576b0563631STom Van Eyck  *                              something that isn't a valid tag (barring an
577b0563631STom Van Eyck  *                              attack on the tag and deliberately-crafted
578b0563631STom Van Eyck  *                              input), in case the caller doesn't check the
579b0563631STom Van Eyck  *                              return status properly.
580b0563631STom Van Eyck  *
581b0563631STom Van Eyck  * \param output_buffer         Pointer to buffer to wipe. May not be NULL
582b0563631STom Van Eyck  *                              unless \p output_buffer_size is zero.
583b0563631STom Van Eyck  * \param status                Status of function called to generate
584b0563631STom Van Eyck  *                              output_buffer originally
585b0563631STom Van Eyck  * \param output_buffer_size    Size of output buffer. If zero, \p output_buffer
586b0563631STom Van Eyck  *                              could be NULL.
587b0563631STom Van Eyck  * \param output_buffer_length  Length of data written to output_buffer, must be
588b0563631STom Van Eyck  *                              less than \p output_buffer_size
589b0563631STom Van Eyck  */
590b0563631STom Van Eyck static void psa_wipe_tag_output_buffer(uint8_t *output_buffer, psa_status_t status,
591b0563631STom Van Eyck                                        size_t output_buffer_size, size_t output_buffer_length)
592b0563631STom Van Eyck {
593b0563631STom Van Eyck     size_t offset = 0;
594b0563631STom Van Eyck 
595b0563631STom Van Eyck     if (output_buffer_size == 0) {
596b0563631STom Van Eyck         /* If output_buffer_size is 0 then we have nothing to do. We must not
597b0563631STom Van Eyck            call memset because output_buffer may be NULL in this case */
598b0563631STom Van Eyck         return;
599b0563631STom Van Eyck     }
600b0563631STom Van Eyck 
601b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
602b0563631STom Van Eyck         offset = output_buffer_length;
603b0563631STom Van Eyck     }
604b0563631STom Van Eyck 
605b0563631STom Van Eyck     memset(output_buffer + offset, '!', output_buffer_size - offset);
606b0563631STom Van Eyck }
607b0563631STom Van Eyck 
608b0563631STom Van Eyck 
609b0563631STom Van Eyck psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type,
610b0563631STom Van Eyck                                                     size_t bits)
611b0563631STom Van Eyck {
612b0563631STom Van Eyck     /* Check that the bit size is acceptable for the key type */
613b0563631STom Van Eyck     switch (type) {
614b0563631STom Van Eyck         case PSA_KEY_TYPE_RAW_DATA:
615b0563631STom Van Eyck         case PSA_KEY_TYPE_HMAC:
616b0563631STom Van Eyck         case PSA_KEY_TYPE_DERIVE:
617b0563631STom Van Eyck         case PSA_KEY_TYPE_PASSWORD:
618b0563631STom Van Eyck         case PSA_KEY_TYPE_PASSWORD_HASH:
619b0563631STom Van Eyck             break;
620b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_AES)
621b0563631STom Van Eyck         case PSA_KEY_TYPE_AES:
622b0563631STom Van Eyck             if (bits != 128 && bits != 192 && bits != 256) {
623b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
624b0563631STom Van Eyck             }
625b0563631STom Van Eyck             break;
626b0563631STom Van Eyck #endif
627b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_ARIA)
628b0563631STom Van Eyck         case PSA_KEY_TYPE_ARIA:
629b0563631STom Van Eyck             if (bits != 128 && bits != 192 && bits != 256) {
630b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
631b0563631STom Van Eyck             }
632b0563631STom Van Eyck             break;
633b0563631STom Van Eyck #endif
634b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
635b0563631STom Van Eyck         case PSA_KEY_TYPE_CAMELLIA:
636b0563631STom Van Eyck             if (bits != 128 && bits != 192 && bits != 256) {
637b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
638b0563631STom Van Eyck             }
639b0563631STom Van Eyck             break;
640b0563631STom Van Eyck #endif
641b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_DES)
642b0563631STom Van Eyck         case PSA_KEY_TYPE_DES:
643b0563631STom Van Eyck             if (bits != 64 && bits != 128 && bits != 192) {
644b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
645b0563631STom Van Eyck             }
646b0563631STom Van Eyck             break;
647b0563631STom Van Eyck #endif
648b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_CHACHA20)
649b0563631STom Van Eyck         case PSA_KEY_TYPE_CHACHA20:
650b0563631STom Van Eyck             if (bits != 256) {
651b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
652b0563631STom Van Eyck             }
653b0563631STom Van Eyck             break;
654b0563631STom Van Eyck #endif
655b0563631STom Van Eyck         default:
656b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
657b0563631STom Van Eyck     }
658b0563631STom Van Eyck     if (bits % 8 != 0) {
659b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
660b0563631STom Van Eyck     }
661b0563631STom Van Eyck 
662b0563631STom Van Eyck     return PSA_SUCCESS;
663b0563631STom Van Eyck }
664b0563631STom Van Eyck 
665b0563631STom Van Eyck /** Check whether a given key type is valid for use with a given MAC algorithm
666b0563631STom Van Eyck  *
667b0563631STom Van Eyck  * Upon successful return of this function, the behavior of #PSA_MAC_LENGTH
668b0563631STom Van Eyck  * when called with the validated \p algorithm and \p key_type is well-defined.
669b0563631STom Van Eyck  *
670b0563631STom Van Eyck  * \param[in] algorithm     The specific MAC algorithm (can be wildcard).
671b0563631STom Van Eyck  * \param[in] key_type      The key type of the key to be used with the
672b0563631STom Van Eyck  *                          \p algorithm.
673b0563631STom Van Eyck  *
674b0563631STom Van Eyck  * \retval #PSA_SUCCESS
675b0563631STom Van Eyck  *         The \p key_type is valid for use with the \p algorithm
676b0563631STom Van Eyck  * \retval #PSA_ERROR_INVALID_ARGUMENT
677b0563631STom Van Eyck  *         The \p key_type is not valid for use with the \p algorithm
678b0563631STom Van Eyck  */
679b0563631STom Van Eyck MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do(
680b0563631STom Van Eyck     psa_algorithm_t algorithm,
681b0563631STom Van Eyck     psa_key_type_t key_type)
682b0563631STom Van Eyck {
683b0563631STom Van Eyck     if (PSA_ALG_IS_HMAC(algorithm)) {
684b0563631STom Van Eyck         if (key_type == PSA_KEY_TYPE_HMAC) {
685b0563631STom Van Eyck             return PSA_SUCCESS;
686b0563631STom Van Eyck         }
687b0563631STom Van Eyck     }
688b0563631STom Van Eyck 
689b0563631STom Van Eyck     if (PSA_ALG_IS_BLOCK_CIPHER_MAC(algorithm)) {
690b0563631STom Van Eyck         /* Check that we're calling PSA_BLOCK_CIPHER_BLOCK_LENGTH with a cipher
691b0563631STom Van Eyck          * key. */
692b0563631STom Van Eyck         if ((key_type & PSA_KEY_TYPE_CATEGORY_MASK) ==
693b0563631STom Van Eyck             PSA_KEY_TYPE_CATEGORY_SYMMETRIC) {
694b0563631STom Van Eyck             /* PSA_BLOCK_CIPHER_BLOCK_LENGTH returns 1 for stream ciphers and
695b0563631STom Van Eyck              * the block length (larger than 1) for block ciphers. */
696b0563631STom Van Eyck             if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1) {
697b0563631STom Van Eyck                 return PSA_SUCCESS;
698b0563631STom Van Eyck             }
699b0563631STom Van Eyck         }
700b0563631STom Van Eyck     }
701b0563631STom Van Eyck 
702b0563631STom Van Eyck     return PSA_ERROR_INVALID_ARGUMENT;
703b0563631STom Van Eyck }
704b0563631STom Van Eyck 
705b0563631STom Van Eyck psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot,
706b0563631STom Van Eyck                                          size_t buffer_length)
707b0563631STom Van Eyck {
708b0563631STom Van Eyck     if (slot->key.data != NULL) {
709b0563631STom Van Eyck         return PSA_ERROR_ALREADY_EXISTS;
710b0563631STom Van Eyck     }
711b0563631STom Van Eyck 
712b0563631STom Van Eyck     slot->key.data = mbedtls_calloc(1, buffer_length);
713b0563631STom Van Eyck     if (slot->key.data == NULL) {
714b0563631STom Van Eyck         return PSA_ERROR_INSUFFICIENT_MEMORY;
715b0563631STom Van Eyck     }
716b0563631STom Van Eyck 
717b0563631STom Van Eyck     slot->key.bytes = buffer_length;
718b0563631STom Van Eyck     return PSA_SUCCESS;
719b0563631STom Van Eyck }
720b0563631STom Van Eyck 
721b0563631STom Van Eyck psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot,
722b0563631STom Van Eyck                                              const uint8_t *data,
723b0563631STom Van Eyck                                              size_t data_length)
724b0563631STom Van Eyck {
725b0563631STom Van Eyck     psa_status_t status = psa_allocate_buffer_to_slot(slot,
726b0563631STom Van Eyck                                                       data_length);
727b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
728b0563631STom Van Eyck         return status;
729b0563631STom Van Eyck     }
730b0563631STom Van Eyck 
731b0563631STom Van Eyck     memcpy(slot->key.data, data, data_length);
732b0563631STom Van Eyck     return PSA_SUCCESS;
733b0563631STom Van Eyck }
734b0563631STom Van Eyck 
735b0563631STom Van Eyck psa_status_t psa_import_key_into_slot(
736b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
737b0563631STom Van Eyck     const uint8_t *data, size_t data_length,
738b0563631STom Van Eyck     uint8_t *key_buffer, size_t key_buffer_size,
739b0563631STom Van Eyck     size_t *key_buffer_length, size_t *bits)
740b0563631STom Van Eyck {
741b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
742b0563631STom Van Eyck     psa_key_type_t type = attributes->type;
743b0563631STom Van Eyck 
744b0563631STom Van Eyck     /* zero-length keys are never supported. */
745b0563631STom Van Eyck     if (data_length == 0) {
746b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
747b0563631STom Van Eyck     }
748b0563631STom Van Eyck 
749b0563631STom Van Eyck     if (key_type_is_raw_bytes(type)) {
750b0563631STom Van Eyck         *bits = PSA_BYTES_TO_BITS(data_length);
751b0563631STom Van Eyck 
752b0563631STom Van Eyck         status = psa_validate_unstructured_key_bit_size(attributes->type,
753b0563631STom Van Eyck                                                         *bits);
754b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
755b0563631STom Van Eyck             return status;
756b0563631STom Van Eyck         }
757b0563631STom Van Eyck 
758b0563631STom Van Eyck         /* Copy the key material. */
759b0563631STom Van Eyck         memcpy(key_buffer, data, data_length);
760b0563631STom Van Eyck         *key_buffer_length = data_length;
761b0563631STom Van Eyck         (void) key_buffer_size;
762b0563631STom Van Eyck 
763b0563631STom Van Eyck         return PSA_SUCCESS;
764b0563631STom Van Eyck     } else if (PSA_KEY_TYPE_IS_ASYMMETRIC(type)) {
765b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \
766b0563631STom Van Eyck         defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
767b0563631STom Van Eyck         if (PSA_KEY_TYPE_IS_DH(type)) {
768b0563631STom Van Eyck             if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) {
769b0563631STom Van Eyck                 return PSA_ERROR_NOT_SUPPORTED;
770b0563631STom Van Eyck             }
771b0563631STom Van Eyck             return mbedtls_psa_ffdh_import_key(attributes,
772b0563631STom Van Eyck                                                data, data_length,
773b0563631STom Van Eyck                                                key_buffer, key_buffer_size,
774b0563631STom Van Eyck                                                key_buffer_length,
775b0563631STom Van Eyck                                                bits);
776b0563631STom Van Eyck         }
777b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) ||
778b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */
779b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
780b0563631STom Van Eyck         defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
781b0563631STom Van Eyck         if (PSA_KEY_TYPE_IS_ECC(type)) {
782b0563631STom Van Eyck             return mbedtls_psa_ecp_import_key(attributes,
783b0563631STom Van Eyck                                               data, data_length,
784b0563631STom Van Eyck                                               key_buffer, key_buffer_size,
785b0563631STom Van Eyck                                               key_buffer_length,
786b0563631STom Van Eyck                                               bits);
787b0563631STom Van Eyck         }
788b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
789b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
790b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
791b0563631STom Van Eyck         defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
792b0563631STom Van Eyck         defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
793b0563631STom Van Eyck         if (PSA_KEY_TYPE_IS_RSA(type)) {
794b0563631STom Van Eyck             return mbedtls_psa_rsa_import_key(attributes,
795b0563631STom Van Eyck                                               data, data_length,
796b0563631STom Van Eyck                                               key_buffer, key_buffer_size,
797b0563631STom Van Eyck                                               key_buffer_length,
798b0563631STom Van Eyck                                               bits);
799b0563631STom Van Eyck         }
800b0563631STom Van Eyck #endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&
801b0563631STom Van Eyck            defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
802b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
803b0563631STom Van Eyck     }
804b0563631STom Van Eyck 
805b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
806b0563631STom Van Eyck }
807b0563631STom Van Eyck 
808b0563631STom Van Eyck /** Calculate the intersection of two algorithm usage policies.
809b0563631STom Van Eyck  *
810b0563631STom Van Eyck  * Return 0 (which allows no operation) on incompatibility.
811b0563631STom Van Eyck  */
812b0563631STom Van Eyck static psa_algorithm_t psa_key_policy_algorithm_intersection(
813b0563631STom Van Eyck     psa_key_type_t key_type,
814b0563631STom Van Eyck     psa_algorithm_t alg1,
815b0563631STom Van Eyck     psa_algorithm_t alg2)
816b0563631STom Van Eyck {
817b0563631STom Van Eyck     /* Common case: both sides actually specify the same policy. */
818b0563631STom Van Eyck     if (alg1 == alg2) {
819b0563631STom Van Eyck         return alg1;
820b0563631STom Van Eyck     }
821b0563631STom Van Eyck     /* If the policies are from the same hash-and-sign family, check
822b0563631STom Van Eyck      * if one is a wildcard. If so the other has the specific algorithm. */
823b0563631STom Van Eyck     if (PSA_ALG_IS_SIGN_HASH(alg1) &&
824b0563631STom Van Eyck         PSA_ALG_IS_SIGN_HASH(alg2) &&
825b0563631STom Van Eyck         (alg1 & ~PSA_ALG_HASH_MASK) == (alg2 & ~PSA_ALG_HASH_MASK)) {
826b0563631STom Van Eyck         if (PSA_ALG_SIGN_GET_HASH(alg1) == PSA_ALG_ANY_HASH) {
827b0563631STom Van Eyck             return alg2;
828b0563631STom Van Eyck         }
829b0563631STom Van Eyck         if (PSA_ALG_SIGN_GET_HASH(alg2) == PSA_ALG_ANY_HASH) {
830b0563631STom Van Eyck             return alg1;
831b0563631STom Van Eyck         }
832b0563631STom Van Eyck     }
833b0563631STom Van Eyck     /* If the policies are from the same AEAD family, check whether
834b0563631STom Van Eyck      * one of them is a minimum-tag-length wildcard. Calculate the most
835b0563631STom Van Eyck      * restrictive tag length. */
836b0563631STom Van Eyck     if (PSA_ALG_IS_AEAD(alg1) && PSA_ALG_IS_AEAD(alg2) &&
837b0563631STom Van Eyck         (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg1, 0) ==
838b0563631STom Van Eyck          PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg2, 0))) {
839b0563631STom Van Eyck         size_t alg1_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg1);
840b0563631STom Van Eyck         size_t alg2_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg2);
841b0563631STom Van Eyck         size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len;
842b0563631STom Van Eyck 
843b0563631STom Van Eyck         /* If both are wildcards, return most restrictive wildcard */
844b0563631STom Van Eyck         if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&
845b0563631STom Van Eyck             ((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {
846b0563631STom Van Eyck             return PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
847b0563631STom Van Eyck                 alg1, restricted_len);
848b0563631STom Van Eyck         }
849b0563631STom Van Eyck         /* If only one is a wildcard, return specific algorithm if compatible. */
850b0563631STom Van Eyck         if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&
851b0563631STom Van Eyck             (alg1_len <= alg2_len)) {
852b0563631STom Van Eyck             return alg2;
853b0563631STom Van Eyck         }
854b0563631STom Van Eyck         if (((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&
855b0563631STom Van Eyck             (alg2_len <= alg1_len)) {
856b0563631STom Van Eyck             return alg1;
857b0563631STom Van Eyck         }
858b0563631STom Van Eyck     }
859b0563631STom Van Eyck     /* If the policies are from the same MAC family, check whether one
860b0563631STom Van Eyck      * of them is a minimum-MAC-length policy. Calculate the most
861b0563631STom Van Eyck      * restrictive tag length. */
862b0563631STom Van Eyck     if (PSA_ALG_IS_MAC(alg1) && PSA_ALG_IS_MAC(alg2) &&
863b0563631STom Van Eyck         (PSA_ALG_FULL_LENGTH_MAC(alg1) ==
864b0563631STom Van Eyck          PSA_ALG_FULL_LENGTH_MAC(alg2))) {
865b0563631STom Van Eyck         /* Validate the combination of key type and algorithm. Since the base
866b0563631STom Van Eyck          * algorithm of alg1 and alg2 are the same, we only need this once. */
867b0563631STom Van Eyck         if (PSA_SUCCESS != psa_mac_key_can_do(alg1, key_type)) {
868b0563631STom Van Eyck             return 0;
869b0563631STom Van Eyck         }
870b0563631STom Van Eyck 
871b0563631STom Van Eyck         /* Get the (exact or at-least) output lengths for both sides of the
872b0563631STom Van Eyck          * requested intersection. None of the currently supported algorithms
873b0563631STom Van Eyck          * have an output length dependent on the actual key size, so setting it
874b0563631STom Van Eyck          * to a bogus value of 0 is currently OK.
875b0563631STom Van Eyck          *
876b0563631STom Van Eyck          * Note that for at-least-this-length wildcard algorithms, the output
877b0563631STom Van Eyck          * length is set to the shortest allowed length, which allows us to
878b0563631STom Van Eyck          * calculate the most restrictive tag length for the intersection. */
879b0563631STom Van Eyck         size_t alg1_len = PSA_MAC_LENGTH(key_type, 0, alg1);
880b0563631STom Van Eyck         size_t alg2_len = PSA_MAC_LENGTH(key_type, 0, alg2);
881b0563631STom Van Eyck         size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len;
882b0563631STom Van Eyck 
883b0563631STom Van Eyck         /* If both are wildcards, return most restrictive wildcard */
884b0563631STom Van Eyck         if (((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&
885b0563631STom Van Eyck             ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {
886b0563631STom Van Eyck             return PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg1, restricted_len);
887b0563631STom Van Eyck         }
888b0563631STom Van Eyck 
889b0563631STom Van Eyck         /* If only one is an at-least-this-length policy, the intersection would
890b0563631STom Van Eyck          * be the other (fixed-length) policy as long as said fixed length is
891b0563631STom Van Eyck          * equal to or larger than the shortest allowed length. */
892b0563631STom Van Eyck         if ((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {
893b0563631STom Van Eyck             return (alg1_len <= alg2_len) ? alg2 : 0;
894b0563631STom Van Eyck         }
895b0563631STom Van Eyck         if ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {
896b0563631STom Van Eyck             return (alg2_len <= alg1_len) ? alg1 : 0;
897b0563631STom Van Eyck         }
898b0563631STom Van Eyck 
899b0563631STom Van Eyck         /* If none of them are wildcards, check whether they define the same tag
900b0563631STom Van Eyck          * length. This is still possible here when one is default-length and
901b0563631STom Van Eyck          * the other specific-length. Ensure to always return the
902b0563631STom Van Eyck          * specific-length version for the intersection. */
903b0563631STom Van Eyck         if (alg1_len == alg2_len) {
904b0563631STom Van Eyck             return PSA_ALG_TRUNCATED_MAC(alg1, alg1_len);
905b0563631STom Van Eyck         }
906b0563631STom Van Eyck     }
907b0563631STom Van Eyck     /* If the policies are incompatible, allow nothing. */
908b0563631STom Van Eyck     return 0;
909b0563631STom Van Eyck }
910b0563631STom Van Eyck 
911b0563631STom Van Eyck static int psa_key_algorithm_permits(psa_key_type_t key_type,
912b0563631STom Van Eyck                                      psa_algorithm_t policy_alg,
913b0563631STom Van Eyck                                      psa_algorithm_t requested_alg)
914b0563631STom Van Eyck {
915b0563631STom Van Eyck     /* Common case: the policy only allows requested_alg. */
916b0563631STom Van Eyck     if (requested_alg == policy_alg) {
917b0563631STom Van Eyck         return 1;
918b0563631STom Van Eyck     }
919b0563631STom Van Eyck     /* If policy_alg is a hash-and-sign with a wildcard for the hash,
920b0563631STom Van Eyck      * and requested_alg is the same hash-and-sign family with any hash,
921b0563631STom Van Eyck      * then requested_alg is compliant with policy_alg. */
922b0563631STom Van Eyck     if (PSA_ALG_IS_SIGN_HASH(requested_alg) &&
923b0563631STom Van Eyck         PSA_ALG_SIGN_GET_HASH(policy_alg) == PSA_ALG_ANY_HASH) {
924b0563631STom Van Eyck         return (policy_alg & ~PSA_ALG_HASH_MASK) ==
925b0563631STom Van Eyck                (requested_alg & ~PSA_ALG_HASH_MASK);
926b0563631STom Van Eyck     }
927b0563631STom Van Eyck     /* If policy_alg is a wildcard AEAD algorithm of the same base as
928b0563631STom Van Eyck      * the requested algorithm, check the requested tag length to be
929b0563631STom Van Eyck      * equal-length or longer than the wildcard-specified length. */
930b0563631STom Van Eyck     if (PSA_ALG_IS_AEAD(policy_alg) &&
931b0563631STom Van Eyck         PSA_ALG_IS_AEAD(requested_alg) &&
932b0563631STom Van Eyck         (PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, 0) ==
933b0563631STom Van Eyck          PSA_ALG_AEAD_WITH_SHORTENED_TAG(requested_alg, 0)) &&
934b0563631STom Van Eyck         ((policy_alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {
935b0563631STom Van Eyck         return PSA_ALG_AEAD_GET_TAG_LENGTH(policy_alg) <=
936b0563631STom Van Eyck                PSA_ALG_AEAD_GET_TAG_LENGTH(requested_alg);
937b0563631STom Van Eyck     }
938b0563631STom Van Eyck     /* If policy_alg is a MAC algorithm of the same base as the requested
939b0563631STom Van Eyck      * algorithm, check whether their MAC lengths are compatible. */
940b0563631STom Van Eyck     if (PSA_ALG_IS_MAC(policy_alg) &&
941b0563631STom Van Eyck         PSA_ALG_IS_MAC(requested_alg) &&
942b0563631STom Van Eyck         (PSA_ALG_FULL_LENGTH_MAC(policy_alg) ==
943b0563631STom Van Eyck          PSA_ALG_FULL_LENGTH_MAC(requested_alg))) {
944b0563631STom Van Eyck         /* Validate the combination of key type and algorithm. Since the policy
945b0563631STom Van Eyck          * and requested algorithms are the same, we only need this once. */
946b0563631STom Van Eyck         if (PSA_SUCCESS != psa_mac_key_can_do(policy_alg, key_type)) {
947b0563631STom Van Eyck             return 0;
948b0563631STom Van Eyck         }
949b0563631STom Van Eyck 
950b0563631STom Van Eyck         /* Get both the requested output length for the algorithm which is to be
951b0563631STom Van Eyck          * verified, and the default output length for the base algorithm.
952b0563631STom Van Eyck          * Note that none of the currently supported algorithms have an output
953b0563631STom Van Eyck          * length dependent on actual key size, so setting it to a bogus value
954b0563631STom Van Eyck          * of 0 is currently OK. */
955b0563631STom Van Eyck         size_t requested_output_length = PSA_MAC_LENGTH(
956b0563631STom Van Eyck             key_type, 0, requested_alg);
957b0563631STom Van Eyck         size_t default_output_length = PSA_MAC_LENGTH(
958b0563631STom Van Eyck             key_type, 0,
959b0563631STom Van Eyck             PSA_ALG_FULL_LENGTH_MAC(requested_alg));
960b0563631STom Van Eyck 
961b0563631STom Van Eyck         /* If the policy is default-length, only allow an algorithm with
962b0563631STom Van Eyck          * a declared exact-length matching the default. */
963b0563631STom Van Eyck         if (PSA_MAC_TRUNCATED_LENGTH(policy_alg) == 0) {
964b0563631STom Van Eyck             return requested_output_length == default_output_length;
965b0563631STom Van Eyck         }
966b0563631STom Van Eyck 
967b0563631STom Van Eyck         /* If the requested algorithm is default-length, allow it if the policy
968b0563631STom Van Eyck          * length exactly matches the default length. */
969b0563631STom Van Eyck         if (PSA_MAC_TRUNCATED_LENGTH(requested_alg) == 0 &&
970b0563631STom Van Eyck             PSA_MAC_TRUNCATED_LENGTH(policy_alg) == default_output_length) {
971b0563631STom Van Eyck             return 1;
972b0563631STom Van Eyck         }
973b0563631STom Van Eyck 
974b0563631STom Van Eyck         /* If policy_alg is an at-least-this-length wildcard MAC algorithm,
975b0563631STom Van Eyck          * check for the requested MAC length to be equal to or longer than the
976b0563631STom Van Eyck          * minimum allowed length. */
977b0563631STom Van Eyck         if ((policy_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {
978b0563631STom Van Eyck             return PSA_MAC_TRUNCATED_LENGTH(policy_alg) <=
979b0563631STom Van Eyck                    requested_output_length;
980b0563631STom Van Eyck         }
981b0563631STom Van Eyck     }
982b0563631STom Van Eyck     /* If policy_alg is a generic key agreement operation, then using it for
983b0563631STom Van Eyck      * a key derivation with that key agreement should also be allowed. This
984b0563631STom Van Eyck      * behaviour is expected to be defined in a future specification version. */
985b0563631STom Van Eyck     if (PSA_ALG_IS_RAW_KEY_AGREEMENT(policy_alg) &&
986b0563631STom Van Eyck         PSA_ALG_IS_KEY_AGREEMENT(requested_alg)) {
987b0563631STom Van Eyck         return PSA_ALG_KEY_AGREEMENT_GET_BASE(requested_alg) ==
988b0563631STom Van Eyck                policy_alg;
989b0563631STom Van Eyck     }
990b0563631STom Van Eyck     /* If it isn't explicitly permitted, it's forbidden. */
991b0563631STom Van Eyck     return 0;
992b0563631STom Van Eyck }
993b0563631STom Van Eyck 
994b0563631STom Van Eyck /** Test whether a policy permits an algorithm.
995b0563631STom Van Eyck  *
996b0563631STom Van Eyck  * The caller must test usage flags separately.
997b0563631STom Van Eyck  *
998b0563631STom Van Eyck  * \note This function requires providing the key type for which the policy is
999b0563631STom Van Eyck  *       being validated, since some algorithm policy definitions (e.g. MAC)
1000b0563631STom Van Eyck  *       have different properties depending on what kind of cipher it is
1001b0563631STom Van Eyck  *       combined with.
1002b0563631STom Van Eyck  *
1003b0563631STom Van Eyck  * \retval PSA_SUCCESS                  When \p alg is a specific algorithm
1004b0563631STom Van Eyck  *                                      allowed by the \p policy.
1005b0563631STom Van Eyck  * \retval PSA_ERROR_INVALID_ARGUMENT   When \p alg is not a specific algorithm
1006b0563631STom Van Eyck  * \retval PSA_ERROR_NOT_PERMITTED      When \p alg is a specific algorithm, but
1007b0563631STom Van Eyck  *                                      the \p policy does not allow it.
1008b0563631STom Van Eyck  */
1009b0563631STom Van Eyck static psa_status_t psa_key_policy_permits(const psa_key_policy_t *policy,
1010b0563631STom Van Eyck                                            psa_key_type_t key_type,
1011b0563631STom Van Eyck                                            psa_algorithm_t alg)
1012b0563631STom Van Eyck {
1013b0563631STom Van Eyck     /* '0' is not a valid algorithm */
1014b0563631STom Van Eyck     if (alg == 0) {
1015b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
1016b0563631STom Van Eyck     }
1017b0563631STom Van Eyck 
1018b0563631STom Van Eyck     /* A requested algorithm cannot be a wildcard. */
1019b0563631STom Van Eyck     if (PSA_ALG_IS_WILDCARD(alg)) {
1020b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
1021b0563631STom Van Eyck     }
1022b0563631STom Van Eyck 
1023b0563631STom Van Eyck     if (psa_key_algorithm_permits(key_type, policy->alg, alg) ||
1024b0563631STom Van Eyck         psa_key_algorithm_permits(key_type, policy->alg2, alg)) {
1025b0563631STom Van Eyck         return PSA_SUCCESS;
1026b0563631STom Van Eyck     } else {
1027b0563631STom Van Eyck         return PSA_ERROR_NOT_PERMITTED;
1028b0563631STom Van Eyck     }
1029b0563631STom Van Eyck }
1030b0563631STom Van Eyck 
1031b0563631STom Van Eyck /** Restrict a key policy based on a constraint.
1032b0563631STom Van Eyck  *
1033b0563631STom Van Eyck  * \note This function requires providing the key type for which the policy is
1034b0563631STom Van Eyck  *       being restricted, since some algorithm policy definitions (e.g. MAC)
1035b0563631STom Van Eyck  *       have different properties depending on what kind of cipher it is
1036b0563631STom Van Eyck  *       combined with.
1037b0563631STom Van Eyck  *
1038b0563631STom Van Eyck  * \param[in] key_type      The key type for which to restrict the policy
1039b0563631STom Van Eyck  * \param[in,out] policy    The policy to restrict.
1040b0563631STom Van Eyck  * \param[in] constraint    The policy constraint to apply.
1041b0563631STom Van Eyck  *
1042b0563631STom Van Eyck  * \retval #PSA_SUCCESS
1043b0563631STom Van Eyck  *         \c *policy contains the intersection of the original value of
1044b0563631STom Van Eyck  *         \c *policy and \c *constraint.
1045b0563631STom Van Eyck  * \retval #PSA_ERROR_INVALID_ARGUMENT
1046b0563631STom Van Eyck  *         \c key_type, \c *policy and \c *constraint are incompatible.
1047b0563631STom Van Eyck  *         \c *policy is unchanged.
1048b0563631STom Van Eyck  */
1049b0563631STom Van Eyck static psa_status_t psa_restrict_key_policy(
1050b0563631STom Van Eyck     psa_key_type_t key_type,
1051b0563631STom Van Eyck     psa_key_policy_t *policy,
1052b0563631STom Van Eyck     const psa_key_policy_t *constraint)
1053b0563631STom Van Eyck {
1054b0563631STom Van Eyck     psa_algorithm_t intersection_alg =
1055b0563631STom Van Eyck         psa_key_policy_algorithm_intersection(key_type, policy->alg,
1056b0563631STom Van Eyck                                               constraint->alg);
1057b0563631STom Van Eyck     psa_algorithm_t intersection_alg2 =
1058b0563631STom Van Eyck         psa_key_policy_algorithm_intersection(key_type, policy->alg2,
1059b0563631STom Van Eyck                                               constraint->alg2);
1060b0563631STom Van Eyck     if (intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0) {
1061b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
1062b0563631STom Van Eyck     }
1063b0563631STom Van Eyck     if (intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0) {
1064b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
1065b0563631STom Van Eyck     }
1066b0563631STom Van Eyck     policy->usage &= constraint->usage;
1067b0563631STom Van Eyck     policy->alg = intersection_alg;
1068b0563631STom Van Eyck     policy->alg2 = intersection_alg2;
1069b0563631STom Van Eyck     return PSA_SUCCESS;
1070b0563631STom Van Eyck }
1071b0563631STom Van Eyck 
1072b0563631STom Van Eyck /** Get the description of a key given its identifier and policy constraints
1073b0563631STom Van Eyck  *  and lock it.
1074b0563631STom Van Eyck  *
1075b0563631STom Van Eyck  * The key must have allow all the usage flags set in \p usage. If \p alg is
1076b0563631STom Van Eyck  * nonzero, the key must allow operations with this algorithm. If \p alg is
1077b0563631STom Van Eyck  * zero, the algorithm is not checked.
1078b0563631STom Van Eyck  *
1079b0563631STom Van Eyck  * In case of a persistent key, the function loads the description of the key
1080b0563631STom Van Eyck  * into a key slot if not already done.
1081b0563631STom Van Eyck  *
1082b0563631STom Van Eyck  * On success, the returned key slot has been registered for reading.
1083b0563631STom Van Eyck  * It is the responsibility of the caller to then unregister
1084b0563631STom Van Eyck  * once they have finished reading the contents of the slot.
1085b0563631STom Van Eyck  * The caller unregisters by calling psa_unregister_read() or
1086b0563631STom Van Eyck  * psa_unregister_read_under_mutex(). psa_unregister_read() must be called
1087b0563631STom Van Eyck  * if and only if the caller already holds the global key slot mutex
1088b0563631STom Van Eyck  * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates
1089b0563631STom Van Eyck  * the unregister with mutex lock and unlock operations.
1090b0563631STom Van Eyck  */
1091b0563631STom Van Eyck static psa_status_t psa_get_and_lock_key_slot_with_policy(
1092b0563631STom Van Eyck     mbedtls_svc_key_id_t key,
1093b0563631STom Van Eyck     psa_key_slot_t **p_slot,
1094b0563631STom Van Eyck     psa_key_usage_t usage,
1095b0563631STom Van Eyck     psa_algorithm_t alg)
1096b0563631STom Van Eyck {
1097b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
1098b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
1099b0563631STom Van Eyck 
1100b0563631STom Van Eyck     status = psa_get_and_lock_key_slot(key, p_slot);
1101b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1102b0563631STom Van Eyck         return status;
1103b0563631STom Van Eyck     }
1104b0563631STom Van Eyck     slot = *p_slot;
1105b0563631STom Van Eyck 
1106b0563631STom Van Eyck     /* Enforce that usage policy for the key slot contains all the flags
1107b0563631STom Van Eyck      * required by the usage parameter. There is one exception: public
1108b0563631STom Van Eyck      * keys can always be exported, so we treat public key objects as
1109b0563631STom Van Eyck      * if they had the export flag. */
1110b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) {
1111b0563631STom Van Eyck         usage &= ~PSA_KEY_USAGE_EXPORT;
1112b0563631STom Van Eyck     }
1113b0563631STom Van Eyck 
1114b0563631STom Van Eyck     if ((slot->attr.policy.usage & usage) != usage) {
1115b0563631STom Van Eyck         status = PSA_ERROR_NOT_PERMITTED;
1116b0563631STom Van Eyck         goto error;
1117b0563631STom Van Eyck     }
1118b0563631STom Van Eyck 
1119b0563631STom Van Eyck     /* Enforce that the usage policy permits the requested algorithm. */
1120b0563631STom Van Eyck     if (alg != 0) {
1121b0563631STom Van Eyck         status = psa_key_policy_permits(&slot->attr.policy,
1122b0563631STom Van Eyck                                         slot->attr.type,
1123b0563631STom Van Eyck                                         alg);
1124b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
1125b0563631STom Van Eyck             goto error;
1126b0563631STom Van Eyck         }
1127b0563631STom Van Eyck     }
1128b0563631STom Van Eyck 
1129b0563631STom Van Eyck     return PSA_SUCCESS;
1130b0563631STom Van Eyck 
1131b0563631STom Van Eyck error:
1132b0563631STom Van Eyck     *p_slot = NULL;
1133b0563631STom Van Eyck     psa_unregister_read_under_mutex(slot);
1134b0563631STom Van Eyck 
1135b0563631STom Van Eyck     return status;
1136b0563631STom Van Eyck }
1137b0563631STom Van Eyck 
1138b0563631STom Van Eyck /** Get a key slot containing a transparent key and lock it.
1139b0563631STom Van Eyck  *
1140b0563631STom Van Eyck  * A transparent key is a key for which the key material is directly
1141b0563631STom Van Eyck  * available, as opposed to a key in a secure element and/or to be used
1142b0563631STom Van Eyck  * by a secure element.
1143b0563631STom Van Eyck  *
1144b0563631STom Van Eyck  * This is a temporary function that may be used instead of
1145b0563631STom Van Eyck  * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support
1146b0563631STom Van Eyck  * for a cryptographic operation.
1147b0563631STom Van Eyck  *
1148b0563631STom Van Eyck  * On success, the returned key slot has been registered for reading.
1149b0563631STom Van Eyck  * It is the responsibility of the caller to then unregister
1150b0563631STom Van Eyck  * once they have finished reading the contents of the slot.
1151b0563631STom Van Eyck  * The caller unregisters by calling psa_unregister_read() or
1152b0563631STom Van Eyck  * psa_unregister_read_under_mutex(). psa_unregister_read() must be called
1153b0563631STom Van Eyck  * if and only if the caller already holds the global key slot mutex
1154b0563631STom Van Eyck  * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates
1155b0563631STom Van Eyck  * psa_unregister_read() with mutex lock and unlock operations.
1156b0563631STom Van Eyck  */
1157b0563631STom Van Eyck static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy(
1158b0563631STom Van Eyck     mbedtls_svc_key_id_t key,
1159b0563631STom Van Eyck     psa_key_slot_t **p_slot,
1160b0563631STom Van Eyck     psa_key_usage_t usage,
1161b0563631STom Van Eyck     psa_algorithm_t alg)
1162b0563631STom Van Eyck {
1163b0563631STom Van Eyck     psa_status_t status = psa_get_and_lock_key_slot_with_policy(key, p_slot,
1164b0563631STom Van Eyck                                                                 usage, alg);
1165b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1166b0563631STom Van Eyck         return status;
1167b0563631STom Van Eyck     }
1168b0563631STom Van Eyck 
1169b0563631STom Van Eyck     if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) {
1170b0563631STom Van Eyck         psa_unregister_read_under_mutex(*p_slot);
1171b0563631STom Van Eyck         *p_slot = NULL;
1172b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
1173b0563631STom Van Eyck     }
1174b0563631STom Van Eyck 
1175b0563631STom Van Eyck     return PSA_SUCCESS;
1176b0563631STom Van Eyck }
1177b0563631STom Van Eyck 
1178b0563631STom Van Eyck psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot)
1179b0563631STom Van Eyck {
1180b0563631STom Van Eyck     if (slot->key.data != NULL) {
1181b0563631STom Van Eyck         mbedtls_zeroize_and_free(slot->key.data, slot->key.bytes);
1182b0563631STom Van Eyck     }
1183b0563631STom Van Eyck 
1184b0563631STom Van Eyck     slot->key.data = NULL;
1185b0563631STom Van Eyck     slot->key.bytes = 0;
1186b0563631STom Van Eyck 
1187b0563631STom Van Eyck     return PSA_SUCCESS;
1188b0563631STom Van Eyck }
1189b0563631STom Van Eyck 
1190b0563631STom Van Eyck /** Completely wipe a slot in memory, including its policy.
1191b0563631STom Van Eyck  * Persistent storage is not affected. */
1192b0563631STom Van Eyck psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot)
1193b0563631STom Van Eyck {
1194b0563631STom Van Eyck     psa_status_t status = psa_remove_key_data_from_memory(slot);
1195b0563631STom Van Eyck 
1196b0563631STom Van Eyck     /*
1197b0563631STom Van Eyck      * As the return error code may not be handled in case of multiple errors,
1198b0563631STom Van Eyck      * do our best to report an unexpected amount of registered readers or
1199b0563631STom Van Eyck      * an unexpected state.
1200b0563631STom Van Eyck      * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that the slot is valid for
1201b0563631STom Van Eyck      * wiping.
1202b0563631STom Van Eyck      * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the
1203b0563631STom Van Eyck      * function is called as part of the execution of a test suite, the
1204b0563631STom Van Eyck      * execution of the test suite is stopped in error if the assertion fails.
1205b0563631STom Van Eyck      */
1206b0563631STom Van Eyck     switch (slot->state) {
1207b0563631STom Van Eyck         case PSA_SLOT_FULL:
1208b0563631STom Van Eyck         /* In this state psa_wipe_key_slot() must only be called if the
1209b0563631STom Van Eyck          * caller is the last reader. */
1210b0563631STom Van Eyck         case PSA_SLOT_PENDING_DELETION:
1211b0563631STom Van Eyck             /* In this state psa_wipe_key_slot() must only be called if the
1212b0563631STom Van Eyck              * caller is the last reader. */
1213*cb034002SJerome Forissier             if (slot->var.occupied.registered_readers != 1) {
1214*cb034002SJerome Forissier                 MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 1);
1215b0563631STom Van Eyck                 status = PSA_ERROR_CORRUPTION_DETECTED;
1216b0563631STom Van Eyck             }
1217b0563631STom Van Eyck             break;
1218b0563631STom Van Eyck         case PSA_SLOT_FILLING:
1219b0563631STom Van Eyck             /* In this state registered_readers must be 0. */
1220*cb034002SJerome Forissier             if (slot->var.occupied.registered_readers != 0) {
1221*cb034002SJerome Forissier                 MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 0);
1222b0563631STom Van Eyck                 status = PSA_ERROR_CORRUPTION_DETECTED;
1223b0563631STom Van Eyck             }
1224b0563631STom Van Eyck             break;
1225b0563631STom Van Eyck         case PSA_SLOT_EMPTY:
1226b0563631STom Van Eyck             /* The slot is already empty, it cannot be wiped. */
1227b0563631STom Van Eyck             MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->state != PSA_SLOT_EMPTY);
1228b0563631STom Van Eyck             status = PSA_ERROR_CORRUPTION_DETECTED;
1229b0563631STom Van Eyck             break;
1230b0563631STom Van Eyck         default:
1231b0563631STom Van Eyck             /* The slot's state is invalid. */
1232b0563631STom Van Eyck             status = PSA_ERROR_CORRUPTION_DETECTED;
1233b0563631STom Van Eyck     }
1234b0563631STom Van Eyck 
1235*cb034002SJerome Forissier #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
1236*cb034002SJerome Forissier     size_t slice_index = slot->slice_index;
1237*cb034002SJerome Forissier #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
1238*cb034002SJerome Forissier 
1239*cb034002SJerome Forissier 
1240b0563631STom Van Eyck     /* Multipart operations may still be using the key. This is safe
1241b0563631STom Van Eyck      * because all multipart operation objects are independent from
1242b0563631STom Van Eyck      * the key slot: if they need to access the key after the setup
1243b0563631STom Van Eyck      * phase, they have a copy of the key. Note that this means that
1244b0563631STom Van Eyck      * key material can linger until all operations are completed. */
1245b0563631STom Van Eyck     /* At this point, key material and other type-specific content has
1246b0563631STom Van Eyck      * been wiped. Clear remaining metadata. We can call memset and not
1247b0563631STom Van Eyck      * zeroize because the metadata is not particularly sensitive.
1248b0563631STom Van Eyck      * This memset also sets the slot's state to PSA_SLOT_EMPTY. */
1249b0563631STom Van Eyck     memset(slot, 0, sizeof(*slot));
1250*cb034002SJerome Forissier 
1251*cb034002SJerome Forissier #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
1252*cb034002SJerome Forissier     /* If the slot is already corrupted, something went deeply wrong,
1253*cb034002SJerome Forissier      * like a thread still using the slot or a stray pointer leading
1254*cb034002SJerome Forissier      * to the slot's memory being used for another object. Let the slot
1255*cb034002SJerome Forissier      * leak rather than make the corruption worse. */
1256*cb034002SJerome Forissier     if (status == PSA_SUCCESS) {
1257*cb034002SJerome Forissier         status = psa_free_key_slot(slice_index, slot);
1258*cb034002SJerome Forissier     }
1259*cb034002SJerome Forissier #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
1260*cb034002SJerome Forissier 
1261b0563631STom Van Eyck     return status;
1262b0563631STom Van Eyck }
1263b0563631STom Van Eyck 
1264b0563631STom Van Eyck psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key)
1265b0563631STom Van Eyck {
1266b0563631STom Van Eyck     psa_key_slot_t *slot;
1267b0563631STom Van Eyck     psa_status_t status; /* status of the last operation */
1268b0563631STom Van Eyck     psa_status_t overall_status = PSA_SUCCESS;
1269b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1270b0563631STom Van Eyck     psa_se_drv_table_entry_t *driver;
1271b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1272b0563631STom Van Eyck 
1273b0563631STom Van Eyck     if (mbedtls_svc_key_id_is_null(key)) {
1274b0563631STom Van Eyck         return PSA_SUCCESS;
1275b0563631STom Van Eyck     }
1276b0563631STom Van Eyck 
1277b0563631STom Van Eyck     /*
1278b0563631STom Van Eyck      * Get the description of the key in a key slot, and register to read it.
1279b0563631STom Van Eyck      * In the case of a persistent key, this will load the key description
1280b0563631STom Van Eyck      * from persistent memory if not done yet.
1281b0563631STom Van Eyck      * We cannot avoid this loading as without it we don't know if
1282b0563631STom Van Eyck      * the key is operated by an SE or not and this information is needed by
1283b0563631STom Van Eyck      * the current implementation. */
1284b0563631STom Van Eyck     status = psa_get_and_lock_key_slot(key, &slot);
1285b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1286b0563631STom Van Eyck         return status;
1287b0563631STom Van Eyck     }
1288b0563631STom Van Eyck 
1289b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
1290b0563631STom Van Eyck     /* We cannot unlock between setting the state to PENDING_DELETION
1291b0563631STom Van Eyck      * and destroying the key in storage, as otherwise another thread
1292b0563631STom Van Eyck      * could load the key into a new slot and the key will not be
1293b0563631STom Van Eyck      * fully destroyed. */
1294b0563631STom Van Eyck     PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(
1295b0563631STom Van Eyck                                     &mbedtls_threading_key_slot_mutex));
1296b0563631STom Van Eyck 
1297b0563631STom Van Eyck     if (slot->state == PSA_SLOT_PENDING_DELETION) {
1298b0563631STom Van Eyck         /* Another thread has destroyed the key between us locking the slot
1299b0563631STom Van Eyck          * and us gaining the mutex. Unregister from the slot,
1300b0563631STom Van Eyck          * and report that the key does not exist. */
1301b0563631STom Van Eyck         status = psa_unregister_read(slot);
1302b0563631STom Van Eyck 
1303b0563631STom Van Eyck         PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
1304b0563631STom Van Eyck                                   &mbedtls_threading_key_slot_mutex));
1305b0563631STom Van Eyck         return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status;
1306b0563631STom Van Eyck     }
1307b0563631STom Van Eyck #endif
1308b0563631STom Van Eyck     /* Set the key slot containing the key description's state to
1309b0563631STom Van Eyck      * PENDING_DELETION. This stops new operations from registering
1310b0563631STom Van Eyck      * to read the slot. Current readers can safely continue to access
1311b0563631STom Van Eyck      * the key within the slot; the last registered reader will
1312b0563631STom Van Eyck      * automatically wipe the slot when they call psa_unregister_read().
1313b0563631STom Van Eyck      * If the key is persistent, we can now delete the copy of the key
1314b0563631STom Van Eyck      * from memory. If the key is opaque, we require the driver to
1315b0563631STom Van Eyck      * deal with the deletion. */
1316b0563631STom Van Eyck     overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL,
1317b0563631STom Van Eyck                                                    PSA_SLOT_PENDING_DELETION);
1318b0563631STom Van Eyck 
1319b0563631STom Van Eyck     if (overall_status != PSA_SUCCESS) {
1320b0563631STom Van Eyck         goto exit;
1321b0563631STom Van Eyck     }
1322b0563631STom Van Eyck 
1323b0563631STom Van Eyck     if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) {
1324b0563631STom Van Eyck         /* Refuse the destruction of a read-only key (which may or may not work
1325b0563631STom Van Eyck          * if we attempt it, depending on whether the key is merely read-only
1326b0563631STom Van Eyck          * by policy or actually physically read-only).
1327b0563631STom Van Eyck          * Just do the best we can, which is to wipe the copy in memory
1328b0563631STom Van Eyck          * (done in this function's cleanup code). */
1329b0563631STom Van Eyck         overall_status = PSA_ERROR_NOT_PERMITTED;
1330b0563631STom Van Eyck         goto exit;
1331b0563631STom Van Eyck     }
1332b0563631STom Van Eyck 
1333b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1334b0563631STom Van Eyck     driver = psa_get_se_driver_entry(slot->attr.lifetime);
1335b0563631STom Van Eyck     if (driver != NULL) {
1336b0563631STom Van Eyck         /* For a key in a secure element, we need to do three things:
1337b0563631STom Van Eyck          * remove the key file in internal storage, destroy the
1338b0563631STom Van Eyck          * key inside the secure element, and update the driver's
1339b0563631STom Van Eyck          * persistent data. Start a transaction that will encompass these
1340b0563631STom Van Eyck          * three actions. */
1341b0563631STom Van Eyck         psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_DESTROY_KEY);
1342b0563631STom Van Eyck         psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
1343b0563631STom Van Eyck         psa_crypto_transaction.key.slot = psa_key_slot_get_slot_number(slot);
1344b0563631STom Van Eyck         psa_crypto_transaction.key.id = slot->attr.id;
1345b0563631STom Van Eyck         status = psa_crypto_save_transaction();
1346b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
1347b0563631STom Van Eyck             (void) psa_crypto_stop_transaction();
1348b0563631STom Van Eyck             /* We should still try to destroy the key in the secure
1349b0563631STom Van Eyck              * element and the key metadata in storage. This is especially
1350b0563631STom Van Eyck              * important if the error is that the storage is full.
1351b0563631STom Van Eyck              * But how to do it exactly without risking an inconsistent
1352b0563631STom Van Eyck              * state after a reset?
1353b0563631STom Van Eyck              * https://github.com/ARMmbed/mbed-crypto/issues/215
1354b0563631STom Van Eyck              */
1355b0563631STom Van Eyck             overall_status = status;
1356b0563631STom Van Eyck             goto exit;
1357b0563631STom Van Eyck         }
1358b0563631STom Van Eyck 
1359b0563631STom Van Eyck         status = psa_destroy_se_key(driver,
1360b0563631STom Van Eyck                                     psa_key_slot_get_slot_number(slot));
1361b0563631STom Van Eyck         if (overall_status == PSA_SUCCESS) {
1362b0563631STom Van Eyck             overall_status = status;
1363b0563631STom Van Eyck         }
1364b0563631STom Van Eyck     }
1365b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1366b0563631STom Van Eyck 
1367b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
1368b0563631STom Van Eyck     if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
1369b0563631STom Van Eyck         /* Destroy the copy of the persistent key from storage.
1370b0563631STom Van Eyck          * The slot will still hold a copy of the key until the last reader
1371b0563631STom Van Eyck          * unregisters. */
1372b0563631STom Van Eyck         status = psa_destroy_persistent_key(slot->attr.id);
1373b0563631STom Van Eyck         if (overall_status == PSA_SUCCESS) {
1374b0563631STom Van Eyck             overall_status = status;
1375b0563631STom Van Eyck         }
1376b0563631STom Van Eyck     }
1377b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
1378b0563631STom Van Eyck 
1379b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1380b0563631STom Van Eyck     if (driver != NULL) {
1381b0563631STom Van Eyck         status = psa_save_se_persistent_data(driver);
1382b0563631STom Van Eyck         if (overall_status == PSA_SUCCESS) {
1383b0563631STom Van Eyck             overall_status = status;
1384b0563631STom Van Eyck         }
1385b0563631STom Van Eyck         status = psa_crypto_stop_transaction();
1386b0563631STom Van Eyck         if (overall_status == PSA_SUCCESS) {
1387b0563631STom Van Eyck             overall_status = status;
1388b0563631STom Van Eyck         }
1389b0563631STom Van Eyck     }
1390b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1391b0563631STom Van Eyck 
1392b0563631STom Van Eyck exit:
1393b0563631STom Van Eyck     /* Unregister from reading the slot. If we are the last active reader
1394b0563631STom Van Eyck      * then this will wipe the slot. */
1395b0563631STom Van Eyck     status = psa_unregister_read(slot);
1396b0563631STom Van Eyck     /* Prioritize CORRUPTION_DETECTED from unregistering over
1397b0563631STom Van Eyck      * a storage error. */
1398b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1399b0563631STom Van Eyck         overall_status = status;
1400b0563631STom Van Eyck     }
1401b0563631STom Van Eyck 
1402b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
1403b0563631STom Van Eyck     /* Don't overwrite existing errors if the unlock fails. */
1404b0563631STom Van Eyck     status = overall_status;
1405b0563631STom Van Eyck     PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
1406b0563631STom Van Eyck                               &mbedtls_threading_key_slot_mutex));
1407b0563631STom Van Eyck #endif
1408b0563631STom Van Eyck 
1409b0563631STom Van Eyck     return overall_status;
1410b0563631STom Van Eyck }
1411b0563631STom Van Eyck 
1412b0563631STom Van Eyck /** Retrieve all the publicly-accessible attributes of a key.
1413b0563631STom Van Eyck  */
1414b0563631STom Van Eyck psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,
1415b0563631STom Van Eyck                                     psa_key_attributes_t *attributes)
1416b0563631STom Van Eyck {
1417b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
1418b0563631STom Van Eyck     psa_key_slot_t *slot;
1419b0563631STom Van Eyck 
1420b0563631STom Van Eyck     psa_reset_key_attributes(attributes);
1421b0563631STom Van Eyck 
1422b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0);
1423b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1424b0563631STom Van Eyck         return status;
1425b0563631STom Van Eyck     }
1426b0563631STom Van Eyck 
1427b0563631STom Van Eyck     *attributes = slot->attr;
1428b0563631STom Van Eyck 
1429b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1430b0563631STom Van Eyck     if (psa_get_se_driver_entry(slot->attr.lifetime) != NULL) {
1431b0563631STom Van Eyck         psa_set_key_slot_number(attributes,
1432b0563631STom Van Eyck                                 psa_key_slot_get_slot_number(slot));
1433b0563631STom Van Eyck     }
1434b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1435b0563631STom Van Eyck 
1436b0563631STom Van Eyck     return psa_unregister_read_under_mutex(slot);
1437b0563631STom Van Eyck }
1438b0563631STom Van Eyck 
1439b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1440b0563631STom Van Eyck psa_status_t psa_get_key_slot_number(
1441b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
1442b0563631STom Van Eyck     psa_key_slot_number_t *slot_number)
1443b0563631STom Van Eyck {
1444b0563631STom Van Eyck     if (attributes->has_slot_number) {
1445b0563631STom Van Eyck         *slot_number = attributes->slot_number;
1446b0563631STom Van Eyck         return PSA_SUCCESS;
1447b0563631STom Van Eyck     } else {
1448b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
1449b0563631STom Van Eyck     }
1450b0563631STom Van Eyck }
1451b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1452b0563631STom Van Eyck 
1453b0563631STom Van Eyck static psa_status_t psa_export_key_buffer_internal(const uint8_t *key_buffer,
1454b0563631STom Van Eyck                                                    size_t key_buffer_size,
1455b0563631STom Van Eyck                                                    uint8_t *data,
1456b0563631STom Van Eyck                                                    size_t data_size,
1457b0563631STom Van Eyck                                                    size_t *data_length)
1458b0563631STom Van Eyck {
1459b0563631STom Van Eyck     if (key_buffer_size > data_size) {
1460b0563631STom Van Eyck         return PSA_ERROR_BUFFER_TOO_SMALL;
1461b0563631STom Van Eyck     }
1462b0563631STom Van Eyck     memcpy(data, key_buffer, key_buffer_size);
1463b0563631STom Van Eyck     memset(data + key_buffer_size, 0,
1464b0563631STom Van Eyck            data_size - key_buffer_size);
1465b0563631STom Van Eyck     *data_length = key_buffer_size;
1466b0563631STom Van Eyck     return PSA_SUCCESS;
1467b0563631STom Van Eyck }
1468b0563631STom Van Eyck 
1469b0563631STom Van Eyck psa_status_t psa_export_key_internal(
1470b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
1471b0563631STom Van Eyck     const uint8_t *key_buffer, size_t key_buffer_size,
1472b0563631STom Van Eyck     uint8_t *data, size_t data_size, size_t *data_length)
1473b0563631STom Van Eyck {
1474b0563631STom Van Eyck     psa_key_type_t type = attributes->type;
1475b0563631STom Van Eyck 
1476b0563631STom Van Eyck     if (key_type_is_raw_bytes(type) ||
1477b0563631STom Van Eyck         PSA_KEY_TYPE_IS_RSA(type)   ||
1478b0563631STom Van Eyck         PSA_KEY_TYPE_IS_ECC(type)   ||
1479b0563631STom Van Eyck         PSA_KEY_TYPE_IS_DH(type)) {
1480b0563631STom Van Eyck         return psa_export_key_buffer_internal(
1481b0563631STom Van Eyck             key_buffer, key_buffer_size,
1482b0563631STom Van Eyck             data, data_size, data_length);
1483b0563631STom Van Eyck     } else {
1484b0563631STom Van Eyck         /* This shouldn't happen in the reference implementation, but
1485b0563631STom Van Eyck            it is valid for a special-purpose implementation to omit
1486b0563631STom Van Eyck            support for exporting certain key types. */
1487b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
1488b0563631STom Van Eyck     }
1489b0563631STom Van Eyck }
1490b0563631STom Van Eyck 
1491b0563631STom Van Eyck psa_status_t psa_export_key(mbedtls_svc_key_id_t key,
1492b0563631STom Van Eyck                             uint8_t *data_external,
1493b0563631STom Van Eyck                             size_t data_size,
1494b0563631STom Van Eyck                             size_t *data_length)
1495b0563631STom Van Eyck {
1496b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
1497b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
1498b0563631STom Van Eyck     psa_key_slot_t *slot;
1499b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(data_external, data);
1500b0563631STom Van Eyck 
1501b0563631STom Van Eyck     /* Reject a zero-length output buffer now, since this can never be a
1502b0563631STom Van Eyck      * valid key representation. This way we know that data must be a valid
1503b0563631STom Van Eyck      * pointer and we can do things like memset(data, ..., data_size). */
1504b0563631STom Van Eyck     if (data_size == 0) {
1505b0563631STom Van Eyck         return PSA_ERROR_BUFFER_TOO_SMALL;
1506b0563631STom Van Eyck     }
1507b0563631STom Van Eyck 
1508b0563631STom Van Eyck     /* Set the key to empty now, so that even when there are errors, we always
1509b0563631STom Van Eyck      * set data_length to a value between 0 and data_size. On error, setting
1510b0563631STom Van Eyck      * the key to empty is a good choice because an empty key representation is
1511b0563631STom Van Eyck      * unlikely to be accepted anywhere. */
1512b0563631STom Van Eyck     *data_length = 0;
1513b0563631STom Van Eyck 
1514b0563631STom Van Eyck     /* Export requires the EXPORT flag. There is an exception for public keys,
1515b0563631STom Van Eyck      * which don't require any flag, but
1516b0563631STom Van Eyck      * psa_get_and_lock_key_slot_with_policy() takes care of this.
1517b0563631STom Van Eyck      */
1518b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot,
1519b0563631STom Van Eyck                                                    PSA_KEY_USAGE_EXPORT, 0);
1520b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1521b0563631STom Van Eyck         return status;
1522b0563631STom Van Eyck     }
1523b0563631STom Van Eyck 
1524b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(data_external, data_size, data);
1525b0563631STom Van Eyck 
1526b0563631STom Van Eyck     status = psa_driver_wrapper_export_key(&slot->attr,
1527b0563631STom Van Eyck                                            slot->key.data, slot->key.bytes,
1528b0563631STom Van Eyck                                            data, data_size, data_length);
1529b0563631STom Van Eyck 
1530b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
1531b0563631STom Van Eyck exit:
1532b0563631STom Van Eyck #endif
1533b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
1534b0563631STom Van Eyck 
1535b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(data_external, data);
1536b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
1537b0563631STom Van Eyck }
1538b0563631STom Van Eyck 
1539b0563631STom Van Eyck psa_status_t psa_export_public_key_internal(
1540b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
1541b0563631STom Van Eyck     const uint8_t *key_buffer,
1542b0563631STom Van Eyck     size_t key_buffer_size,
1543b0563631STom Van Eyck     uint8_t *data,
1544b0563631STom Van Eyck     size_t data_size,
1545b0563631STom Van Eyck     size_t *data_length)
1546b0563631STom Van Eyck {
1547b0563631STom Van Eyck     psa_key_type_t type = attributes->type;
1548b0563631STom Van Eyck 
1549b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
1550b0563631STom Van Eyck         (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) ||
1551b0563631STom Van Eyck          PSA_KEY_TYPE_IS_DH(type))) {
1552b0563631STom Van Eyck         /* Exporting public -> public */
1553b0563631STom Van Eyck         return psa_export_key_buffer_internal(
1554b0563631STom Van Eyck             key_buffer, key_buffer_size,
1555b0563631STom Van Eyck             data, data_size, data_length);
1556b0563631STom Van Eyck     } else if (PSA_KEY_TYPE_IS_RSA(type)) {
1557b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
1558b0563631STom Van Eyck         defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
1559b0563631STom Van Eyck         return mbedtls_psa_rsa_export_public_key(attributes,
1560b0563631STom Van Eyck                                                  key_buffer,
1561b0563631STom Van Eyck                                                  key_buffer_size,
1562b0563631STom Van Eyck                                                  data,
1563b0563631STom Van Eyck                                                  data_size,
1564b0563631STom Van Eyck                                                  data_length);
1565b0563631STom Van Eyck #else
1566b0563631STom Van Eyck         /* We don't know how to convert a private RSA key to public. */
1567b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
1568b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
1569b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
1570b0563631STom Van Eyck     } else if (PSA_KEY_TYPE_IS_ECC(type)) {
1571b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
1572b0563631STom Van Eyck         defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
1573b0563631STom Van Eyck         return mbedtls_psa_ecp_export_public_key(attributes,
1574b0563631STom Van Eyck                                                  key_buffer,
1575b0563631STom Van Eyck                                                  key_buffer_size,
1576b0563631STom Van Eyck                                                  data,
1577b0563631STom Van Eyck                                                  data_size,
1578b0563631STom Van Eyck                                                  data_length);
1579b0563631STom Van Eyck #else
1580b0563631STom Van Eyck         /* We don't know how to convert a private ECC key to public */
1581b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
1582b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
1583b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
1584b0563631STom Van Eyck     } else if (PSA_KEY_TYPE_IS_DH(type)) {
1585b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
1586b0563631STom Van Eyck         defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
1587b0563631STom Van Eyck         return mbedtls_psa_ffdh_export_public_key(attributes,
1588b0563631STom Van Eyck                                                   key_buffer,
1589b0563631STom Van Eyck                                                   key_buffer_size,
1590b0563631STom Van Eyck                                                   data, data_size,
1591b0563631STom Van Eyck                                                   data_length);
1592b0563631STom Van Eyck #else
1593b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
1594b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) ||
1595b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */
1596b0563631STom Van Eyck     } else {
1597b0563631STom Van Eyck         (void) key_buffer;
1598b0563631STom Van Eyck         (void) key_buffer_size;
1599b0563631STom Van Eyck         (void) data;
1600b0563631STom Van Eyck         (void) data_size;
1601b0563631STom Van Eyck         (void) data_length;
1602b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
1603b0563631STom Van Eyck     }
1604b0563631STom Van Eyck }
1605b0563631STom Van Eyck 
1606b0563631STom Van Eyck psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key,
1607b0563631STom Van Eyck                                    uint8_t *data_external,
1608b0563631STom Van Eyck                                    size_t data_size,
1609b0563631STom Van Eyck                                    size_t *data_length)
1610b0563631STom Van Eyck {
1611b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
1612b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
1613b0563631STom Van Eyck     psa_key_slot_t *slot;
1614b0563631STom Van Eyck 
1615b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(data_external, data);
1616b0563631STom Van Eyck 
1617b0563631STom Van Eyck     /* Reject a zero-length output buffer now, since this can never be a
1618b0563631STom Van Eyck      * valid key representation. This way we know that data must be a valid
1619b0563631STom Van Eyck      * pointer and we can do things like memset(data, ..., data_size). */
1620b0563631STom Van Eyck     if (data_size == 0) {
1621b0563631STom Van Eyck         return PSA_ERROR_BUFFER_TOO_SMALL;
1622b0563631STom Van Eyck     }
1623b0563631STom Van Eyck 
1624b0563631STom Van Eyck     /* Set the key to empty now, so that even when there are errors, we always
1625b0563631STom Van Eyck      * set data_length to a value between 0 and data_size. On error, setting
1626b0563631STom Van Eyck      * the key to empty is a good choice because an empty key representation is
1627b0563631STom Van Eyck      * unlikely to be accepted anywhere. */
1628b0563631STom Van Eyck     *data_length = 0;
1629b0563631STom Van Eyck 
1630b0563631STom Van Eyck     /* Exporting a public key doesn't require a usage flag. */
1631b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0);
1632b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1633b0563631STom Van Eyck         return status;
1634b0563631STom Van Eyck     }
1635b0563631STom Van Eyck 
1636b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(data_external, data_size, data);
1637b0563631STom Van Eyck 
1638b0563631STom Van Eyck     if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) {
1639b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
1640b0563631STom Van Eyck         goto exit;
1641b0563631STom Van Eyck     }
1642b0563631STom Van Eyck 
1643b0563631STom Van Eyck     status = psa_driver_wrapper_export_public_key(
1644b0563631STom Van Eyck         &slot->attr, slot->key.data, slot->key.bytes,
1645b0563631STom Van Eyck         data, data_size, data_length);
1646b0563631STom Van Eyck 
1647b0563631STom Van Eyck exit:
1648b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
1649b0563631STom Van Eyck 
1650b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(data_external, data);
1651b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
1652b0563631STom Van Eyck }
1653b0563631STom Van Eyck 
1654b0563631STom Van Eyck /** Validate that a key policy is internally well-formed.
1655b0563631STom Van Eyck  *
1656b0563631STom Van Eyck  * This function only rejects invalid policies. It does not validate the
1657b0563631STom Van Eyck  * consistency of the policy with respect to other attributes of the key
1658b0563631STom Van Eyck  * such as the key type.
1659b0563631STom Van Eyck  */
1660b0563631STom Van Eyck static psa_status_t psa_validate_key_policy(const psa_key_policy_t *policy)
1661b0563631STom Van Eyck {
1662b0563631STom Van Eyck     if ((policy->usage & ~(PSA_KEY_USAGE_EXPORT |
1663b0563631STom Van Eyck                            PSA_KEY_USAGE_COPY |
1664b0563631STom Van Eyck                            PSA_KEY_USAGE_ENCRYPT |
1665b0563631STom Van Eyck                            PSA_KEY_USAGE_DECRYPT |
1666b0563631STom Van Eyck                            PSA_KEY_USAGE_SIGN_MESSAGE |
1667b0563631STom Van Eyck                            PSA_KEY_USAGE_VERIFY_MESSAGE |
1668b0563631STom Van Eyck                            PSA_KEY_USAGE_SIGN_HASH |
1669b0563631STom Van Eyck                            PSA_KEY_USAGE_VERIFY_HASH |
1670b0563631STom Van Eyck                            PSA_KEY_USAGE_VERIFY_DERIVATION |
1671b0563631STom Van Eyck                            PSA_KEY_USAGE_DERIVE)) != 0) {
1672b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
1673b0563631STom Van Eyck     }
1674b0563631STom Van Eyck 
1675b0563631STom Van Eyck     return PSA_SUCCESS;
1676b0563631STom Van Eyck }
1677b0563631STom Van Eyck 
1678b0563631STom Van Eyck /** Validate the internal consistency of key attributes.
1679b0563631STom Van Eyck  *
1680b0563631STom Van Eyck  * This function only rejects invalid attribute values. If does not
1681b0563631STom Van Eyck  * validate the consistency of the attributes with any key data that may
1682b0563631STom Van Eyck  * be involved in the creation of the key.
1683b0563631STom Van Eyck  *
1684b0563631STom Van Eyck  * Call this function early in the key creation process.
1685b0563631STom Van Eyck  *
1686b0563631STom Van Eyck  * \param[in] attributes    Key attributes for the new key.
1687b0563631STom Van Eyck  * \param[out] p_drv        On any return, the driver for the key, if any.
1688b0563631STom Van Eyck  *                          NULL for a transparent key.
1689b0563631STom Van Eyck  *
1690b0563631STom Van Eyck  */
1691b0563631STom Van Eyck static psa_status_t psa_validate_key_attributes(
1692b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
1693b0563631STom Van Eyck     psa_se_drv_table_entry_t **p_drv)
1694b0563631STom Van Eyck {
1695b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
1696b0563631STom Van Eyck     psa_key_lifetime_t lifetime = psa_get_key_lifetime(attributes);
1697b0563631STom Van Eyck     mbedtls_svc_key_id_t key = psa_get_key_id(attributes);
1698b0563631STom Van Eyck 
1699b0563631STom Van Eyck     status = psa_validate_key_location(lifetime, p_drv);
1700b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1701b0563631STom Van Eyck         return status;
1702b0563631STom Van Eyck     }
1703b0563631STom Van Eyck 
1704b0563631STom Van Eyck     status = psa_validate_key_persistence(lifetime);
1705b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1706b0563631STom Van Eyck         return status;
1707b0563631STom Van Eyck     }
1708b0563631STom Van Eyck 
1709b0563631STom Van Eyck     if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
1710b0563631STom Van Eyck         if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key) != 0) {
1711b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
1712b0563631STom Van Eyck         }
1713b0563631STom Van Eyck     } else {
1714b0563631STom Van Eyck         if (!psa_is_valid_key_id(psa_get_key_id(attributes), 0)) {
1715b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
1716b0563631STom Van Eyck         }
1717b0563631STom Van Eyck     }
1718b0563631STom Van Eyck 
1719b0563631STom Van Eyck     status = psa_validate_key_policy(&attributes->policy);
1720b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1721b0563631STom Van Eyck         return status;
1722b0563631STom Van Eyck     }
1723b0563631STom Van Eyck 
1724b0563631STom Van Eyck     /* Refuse to create overly large keys.
1725b0563631STom Van Eyck      * Note that this doesn't trigger on import if the attributes don't
1726b0563631STom Van Eyck      * explicitly specify a size (so psa_get_key_bits returns 0), so
1727b0563631STom Van Eyck      * psa_import_key() needs its own checks. */
1728b0563631STom Van Eyck     if (psa_get_key_bits(attributes) > PSA_MAX_KEY_BITS) {
1729b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
1730b0563631STom Van Eyck     }
1731b0563631STom Van Eyck 
1732b0563631STom Van Eyck     return PSA_SUCCESS;
1733b0563631STom Van Eyck }
1734b0563631STom Van Eyck 
1735b0563631STom Van Eyck /** Prepare a key slot to receive key material.
1736b0563631STom Van Eyck  *
1737b0563631STom Van Eyck  * This function allocates a key slot and sets its metadata.
1738b0563631STom Van Eyck  *
1739b0563631STom Van Eyck  * If this function fails, call psa_fail_key_creation().
1740b0563631STom Van Eyck  *
1741b0563631STom Van Eyck  * This function is intended to be used as follows:
1742b0563631STom Van Eyck  * -# Call psa_start_key_creation() to allocate a key slot, prepare
1743b0563631STom Van Eyck  *    it with the specified attributes, and in case of a volatile key assign it
1744b0563631STom Van Eyck  *    a volatile key identifier.
1745b0563631STom Van Eyck  * -# Populate the slot with the key material.
1746b0563631STom Van Eyck  * -# Call psa_finish_key_creation() to finalize the creation of the slot.
1747b0563631STom Van Eyck  * In case of failure at any step, stop the sequence and call
1748b0563631STom Van Eyck  * psa_fail_key_creation().
1749b0563631STom Van Eyck  *
1750b0563631STom Van Eyck  * On success, the key slot's state is PSA_SLOT_FILLING.
1751b0563631STom Van Eyck  * It is the responsibility of the caller to change the slot's state to
1752b0563631STom Van Eyck  * PSA_SLOT_EMPTY/FULL once key creation has finished.
1753b0563631STom Van Eyck  *
1754b0563631STom Van Eyck  * \param method            An identification of the calling function.
1755b0563631STom Van Eyck  * \param[in] attributes    Key attributes for the new key.
1756b0563631STom Van Eyck  * \param[out] p_slot       On success, a pointer to the prepared slot.
1757b0563631STom Van Eyck  * \param[out] p_drv        On any return, the driver for the key, if any.
1758b0563631STom Van Eyck  *                          NULL for a transparent key.
1759b0563631STom Van Eyck  *
1760b0563631STom Van Eyck  * \retval #PSA_SUCCESS
1761b0563631STom Van Eyck  *         The key slot is ready to receive key material.
1762b0563631STom Van Eyck  * \return If this function fails, the key slot is an invalid state.
1763b0563631STom Van Eyck  *         You must call psa_fail_key_creation() to wipe and free the slot.
1764b0563631STom Van Eyck  */
1765b0563631STom Van Eyck static psa_status_t psa_start_key_creation(
1766b0563631STom Van Eyck     psa_key_creation_method_t method,
1767b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
1768b0563631STom Van Eyck     psa_key_slot_t **p_slot,
1769b0563631STom Van Eyck     psa_se_drv_table_entry_t **p_drv)
1770b0563631STom Van Eyck {
1771b0563631STom Van Eyck     psa_status_t status;
1772b0563631STom Van Eyck 
1773b0563631STom Van Eyck     (void) method;
1774b0563631STom Van Eyck     *p_drv = NULL;
1775b0563631STom Van Eyck 
1776b0563631STom Van Eyck     status = psa_validate_key_attributes(attributes, p_drv);
1777b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1778b0563631STom Van Eyck         return status;
1779b0563631STom Van Eyck     }
1780b0563631STom Van Eyck 
1781*cb034002SJerome Forissier     int key_is_volatile = PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime);
1782*cb034002SJerome Forissier     psa_key_id_t volatile_key_id;
1783*cb034002SJerome Forissier 
1784b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
1785b0563631STom Van Eyck     PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
1786b0563631STom Van Eyck                               &mbedtls_threading_key_slot_mutex));
1787b0563631STom Van Eyck #endif
1788*cb034002SJerome Forissier     status = psa_reserve_free_key_slot(
1789*cb034002SJerome Forissier         key_is_volatile ? &volatile_key_id : NULL,
1790*cb034002SJerome Forissier         p_slot);
1791b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
1792b0563631STom Van Eyck     PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
1793b0563631STom Van Eyck                               &mbedtls_threading_key_slot_mutex));
1794b0563631STom Van Eyck #endif
1795b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
1796b0563631STom Van Eyck         return status;
1797b0563631STom Van Eyck     }
1798*cb034002SJerome Forissier     psa_key_slot_t *slot = *p_slot;
1799b0563631STom Van Eyck 
1800b0563631STom Van Eyck     /* We're storing the declared bit-size of the key. It's up to each
1801b0563631STom Van Eyck      * creation mechanism to verify that this information is correct.
1802b0563631STom Van Eyck      * It's automatically correct for mechanisms that use the bit-size as
1803b0563631STom Van Eyck      * an input (generate, device) but not for those where the bit-size
1804b0563631STom Van Eyck      * is optional (import, copy). In case of a volatile key, assign it the
1805b0563631STom Van Eyck      * volatile key identifier associated to the slot returned to contain its
1806b0563631STom Van Eyck      * definition. */
1807b0563631STom Van Eyck 
1808b0563631STom Van Eyck     slot->attr = *attributes;
1809*cb034002SJerome Forissier     if (key_is_volatile) {
1810b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
1811b0563631STom Van Eyck         slot->attr.id = volatile_key_id;
1812b0563631STom Van Eyck #else
1813b0563631STom Van Eyck         slot->attr.id.key_id = volatile_key_id;
1814b0563631STom Van Eyck #endif
1815b0563631STom Van Eyck     }
1816b0563631STom Van Eyck 
1817b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1818b0563631STom Van Eyck     /* For a key in a secure element, we need to do three things
1819b0563631STom Van Eyck      * when creating or registering a persistent key:
1820b0563631STom Van Eyck      * create the key file in internal storage, create the
1821b0563631STom Van Eyck      * key inside the secure element, and update the driver's
1822b0563631STom Van Eyck      * persistent data. This is done by starting a transaction that will
1823b0563631STom Van Eyck      * encompass these three actions.
1824b0563631STom Van Eyck      * For registering a volatile key, we just need to find an appropriate
1825b0563631STom Van Eyck      * slot number inside the SE. Since the key is designated volatile, creating
1826b0563631STom Van Eyck      * a transaction is not required. */
1827b0563631STom Van Eyck     /* The first thing to do is to find a slot number for the new key.
1828b0563631STom Van Eyck      * We save the slot number in persistent storage as part of the
1829b0563631STom Van Eyck      * transaction data. It will be needed to recover if the power
1830b0563631STom Van Eyck      * fails during the key creation process, to clean up on the secure
1831b0563631STom Van Eyck      * element side after restarting. Obtaining a slot number from the
1832b0563631STom Van Eyck      * secure element driver updates its persistent state, but we do not yet
1833b0563631STom Van Eyck      * save the driver's persistent state, so that if the power fails,
1834b0563631STom Van Eyck      * we can roll back to a state where the key doesn't exist. */
1835b0563631STom Van Eyck     if (*p_drv != NULL) {
1836b0563631STom Van Eyck         psa_key_slot_number_t slot_number;
1837b0563631STom Van Eyck         status = psa_find_se_slot_for_key(attributes, method, *p_drv,
1838b0563631STom Van Eyck                                           &slot_number);
1839b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
1840b0563631STom Van Eyck             return status;
1841b0563631STom Van Eyck         }
1842b0563631STom Van Eyck 
1843b0563631STom Van Eyck         if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) {
1844b0563631STom Van Eyck             psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_CREATE_KEY);
1845b0563631STom Van Eyck             psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
1846b0563631STom Van Eyck             psa_crypto_transaction.key.slot = slot_number;
1847b0563631STom Van Eyck             psa_crypto_transaction.key.id = slot->attr.id;
1848b0563631STom Van Eyck             status = psa_crypto_save_transaction();
1849b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
1850b0563631STom Van Eyck                 (void) psa_crypto_stop_transaction();
1851b0563631STom Van Eyck                 return status;
1852b0563631STom Van Eyck             }
1853b0563631STom Van Eyck         }
1854b0563631STom Van Eyck 
1855b0563631STom Van Eyck         status = psa_copy_key_material_into_slot(
1856b0563631STom Van Eyck             slot, (uint8_t *) (&slot_number), sizeof(slot_number));
1857*cb034002SJerome Forissier         if (status != PSA_SUCCESS) {
1858*cb034002SJerome Forissier             return status;
1859*cb034002SJerome Forissier         }
1860b0563631STom Van Eyck     }
1861b0563631STom Van Eyck 
1862b0563631STom Van Eyck     if (*p_drv == NULL && method == PSA_KEY_CREATION_REGISTER) {
1863b0563631STom Van Eyck         /* Key registration only makes sense with a secure element. */
1864b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
1865b0563631STom Van Eyck     }
1866b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1867b0563631STom Van Eyck 
1868b0563631STom Van Eyck     return PSA_SUCCESS;
1869b0563631STom Van Eyck }
1870b0563631STom Van Eyck 
1871b0563631STom Van Eyck /** Finalize the creation of a key once its key material has been set.
1872b0563631STom Van Eyck  *
1873b0563631STom Van Eyck  * This entails writing the key to persistent storage.
1874b0563631STom Van Eyck  *
1875b0563631STom Van Eyck  * If this function fails, call psa_fail_key_creation().
1876b0563631STom Van Eyck  * See the documentation of psa_start_key_creation() for the intended use
1877b0563631STom Van Eyck  * of this function.
1878b0563631STom Van Eyck  *
1879b0563631STom Van Eyck  * If the finalization succeeds, the function sets the key slot's state to
1880b0563631STom Van Eyck  * PSA_SLOT_FULL, and the key slot can no longer be accessed as part of the
1881b0563631STom Van Eyck  * key creation process.
1882b0563631STom Van Eyck  *
1883b0563631STom Van Eyck  * \param[in,out] slot  Pointer to the slot with key material.
1884b0563631STom Van Eyck  * \param[in] driver    The secure element driver for the key,
1885b0563631STom Van Eyck  *                      or NULL for a transparent key.
1886b0563631STom Van Eyck  * \param[out] key      On success, identifier of the key. Note that the
1887b0563631STom Van Eyck  *                      key identifier is also stored in the key slot.
1888b0563631STom Van Eyck  *
1889b0563631STom Van Eyck  * \retval #PSA_SUCCESS
1890b0563631STom Van Eyck  *         The key was successfully created.
1891b0563631STom Van Eyck  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
1892b0563631STom Van Eyck  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
1893b0563631STom Van Eyck  * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
1894b0563631STom Van Eyck  * \retval #PSA_ERROR_DATA_INVALID \emptydescription
1895b0563631STom Van Eyck  * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
1896b0563631STom Van Eyck  * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
1897b0563631STom Van Eyck  *
1898b0563631STom Van Eyck  * \return If this function fails, the key slot is an invalid state.
1899b0563631STom Van Eyck  *         You must call psa_fail_key_creation() to wipe and free the slot.
1900b0563631STom Van Eyck  */
1901b0563631STom Van Eyck static psa_status_t psa_finish_key_creation(
1902b0563631STom Van Eyck     psa_key_slot_t *slot,
1903b0563631STom Van Eyck     psa_se_drv_table_entry_t *driver,
1904b0563631STom Van Eyck     mbedtls_svc_key_id_t *key)
1905b0563631STom Van Eyck {
1906b0563631STom Van Eyck     psa_status_t status = PSA_SUCCESS;
1907b0563631STom Van Eyck     (void) slot;
1908b0563631STom Van Eyck     (void) driver;
1909b0563631STom Van Eyck 
1910b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
1911b0563631STom Van Eyck     PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
1912b0563631STom Van Eyck                               &mbedtls_threading_key_slot_mutex));
1913b0563631STom Van Eyck #endif
1914b0563631STom Van Eyck 
1915b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
1916b0563631STom Van Eyck     if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
1917b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1918b0563631STom Van Eyck         if (driver != NULL) {
1919b0563631STom Van Eyck             psa_se_key_data_storage_t data;
1920b0563631STom Van Eyck             psa_key_slot_number_t slot_number =
1921b0563631STom Van Eyck                 psa_key_slot_get_slot_number(slot);
1922b0563631STom Van Eyck 
1923b0563631STom Van Eyck             MBEDTLS_STATIC_ASSERT(sizeof(slot_number) ==
1924b0563631STom Van Eyck                                   sizeof(data.slot_number),
1925b0563631STom Van Eyck                                   "Slot number size does not match psa_se_key_data_storage_t");
1926b0563631STom Van Eyck 
1927b0563631STom Van Eyck             memcpy(&data.slot_number, &slot_number, sizeof(slot_number));
1928b0563631STom Van Eyck             status = psa_save_persistent_key(&slot->attr,
1929b0563631STom Van Eyck                                              (uint8_t *) &data,
1930b0563631STom Van Eyck                                              sizeof(data));
1931b0563631STom Van Eyck         } else
1932b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1933b0563631STom Van Eyck         {
1934b0563631STom Van Eyck             /* Key material is saved in export representation in the slot, so
1935b0563631STom Van Eyck              * just pass the slot buffer for storage. */
1936b0563631STom Van Eyck             status = psa_save_persistent_key(&slot->attr,
1937b0563631STom Van Eyck                                              slot->key.data,
1938b0563631STom Van Eyck                                              slot->key.bytes);
1939b0563631STom Van Eyck         }
1940b0563631STom Van Eyck     }
1941b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
1942b0563631STom Van Eyck 
1943b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1944b0563631STom Van Eyck     /* Finish the transaction for a key creation. This does not
1945b0563631STom Van Eyck      * happen when registering an existing key. Detect this case
1946b0563631STom Van Eyck      * by checking whether a transaction is in progress (actual
1947b0563631STom Van Eyck      * creation of a persistent key in a secure element requires a transaction,
1948b0563631STom Van Eyck      * but registration or volatile key creation doesn't use one). */
1949b0563631STom Van Eyck     if (driver != NULL &&
1950b0563631STom Van Eyck         psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY) {
1951b0563631STom Van Eyck         status = psa_save_se_persistent_data(driver);
1952b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
1953b0563631STom Van Eyck             psa_destroy_persistent_key(slot->attr.id);
1954b0563631STom Van Eyck 
1955b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
1956b0563631STom Van Eyck             PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
1957b0563631STom Van Eyck                                       &mbedtls_threading_key_slot_mutex));
1958b0563631STom Van Eyck #endif
1959b0563631STom Van Eyck             return status;
1960b0563631STom Van Eyck         }
1961b0563631STom Van Eyck         status = psa_crypto_stop_transaction();
1962b0563631STom Van Eyck     }
1963b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1964b0563631STom Van Eyck 
1965b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
1966b0563631STom Van Eyck         *key = slot->attr.id;
1967b0563631STom Van Eyck         status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,
1968b0563631STom Van Eyck                                                PSA_SLOT_FULL);
1969b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
1970b0563631STom Van Eyck             *key = MBEDTLS_SVC_KEY_ID_INIT;
1971b0563631STom Van Eyck         }
1972b0563631STom Van Eyck     }
1973b0563631STom Van Eyck 
1974b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
1975b0563631STom Van Eyck     PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
1976b0563631STom Van Eyck                               &mbedtls_threading_key_slot_mutex));
1977b0563631STom Van Eyck #endif
1978b0563631STom Van Eyck     return status;
1979b0563631STom Van Eyck }
1980b0563631STom Van Eyck 
1981b0563631STom Van Eyck /** Abort the creation of a key.
1982b0563631STom Van Eyck  *
1983b0563631STom Van Eyck  * You may call this function after calling psa_start_key_creation(),
1984b0563631STom Van Eyck  * or after psa_finish_key_creation() fails. In other circumstances, this
1985b0563631STom Van Eyck  * function may not clean up persistent storage.
1986b0563631STom Van Eyck  * See the documentation of psa_start_key_creation() for the intended use
1987b0563631STom Van Eyck  * of this function. Sets the slot's state to PSA_SLOT_EMPTY.
1988b0563631STom Van Eyck  *
1989b0563631STom Van Eyck  * \param[in,out] slot  Pointer to the slot with key material.
1990b0563631STom Van Eyck  * \param[in] driver    The secure element driver for the key,
1991b0563631STom Van Eyck  *                      or NULL for a transparent key.
1992b0563631STom Van Eyck  */
1993b0563631STom Van Eyck static void psa_fail_key_creation(psa_key_slot_t *slot,
1994b0563631STom Van Eyck                                   psa_se_drv_table_entry_t *driver)
1995b0563631STom Van Eyck {
1996b0563631STom Van Eyck     (void) driver;
1997b0563631STom Van Eyck 
1998b0563631STom Van Eyck     if (slot == NULL) {
1999b0563631STom Van Eyck         return;
2000b0563631STom Van Eyck     }
2001b0563631STom Van Eyck 
2002b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
2003b0563631STom Van Eyck     /* If the lock operation fails we still wipe the slot.
2004b0563631STom Van Eyck      * Operations will no longer work after a failed lock,
2005b0563631STom Van Eyck      * but we still need to wipe the slot of confidential data. */
2006b0563631STom Van Eyck     mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex);
2007b0563631STom Van Eyck #endif
2008b0563631STom Van Eyck 
2009b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
2010b0563631STom Van Eyck     /* TODO: If the key has already been created in the secure
2011b0563631STom Van Eyck      * element, and the failure happened later (when saving metadata
2012b0563631STom Van Eyck      * to internal storage), we need to destroy the key in the secure
2013b0563631STom Van Eyck      * element.
2014b0563631STom Van Eyck      * https://github.com/ARMmbed/mbed-crypto/issues/217
2015b0563631STom Van Eyck      */
2016b0563631STom Van Eyck 
2017b0563631STom Van Eyck     /* Abort the ongoing transaction if any (there may not be one if
2018b0563631STom Van Eyck      * the creation process failed before starting one, or if the
2019b0563631STom Van Eyck      * key creation is a registration of a key in a secure element).
2020b0563631STom Van Eyck      * Earlier functions must already have done what it takes to undo any
2021b0563631STom Van Eyck      * partial creation. All that's left is to update the transaction data
2022b0563631STom Van Eyck      * itself. */
2023b0563631STom Van Eyck     (void) psa_crypto_stop_transaction();
2024b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
2025b0563631STom Van Eyck 
2026b0563631STom Van Eyck     psa_wipe_key_slot(slot);
2027b0563631STom Van Eyck 
2028b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
2029b0563631STom Van Eyck     mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex);
2030b0563631STom Van Eyck #endif
2031b0563631STom Van Eyck }
2032b0563631STom Van Eyck 
2033b0563631STom Van Eyck /** Validate optional attributes during key creation.
2034b0563631STom Van Eyck  *
2035b0563631STom Van Eyck  * Some key attributes are optional during key creation. If they are
2036b0563631STom Van Eyck  * specified in the attributes structure, check that they are consistent
2037b0563631STom Van Eyck  * with the data in the slot.
2038b0563631STom Van Eyck  *
2039b0563631STom Van Eyck  * This function should be called near the end of key creation, after
2040b0563631STom Van Eyck  * the slot in memory is fully populated but before saving persistent data.
2041b0563631STom Van Eyck  */
2042b0563631STom Van Eyck static psa_status_t psa_validate_optional_attributes(
2043b0563631STom Van Eyck     const psa_key_slot_t *slot,
2044b0563631STom Van Eyck     const psa_key_attributes_t *attributes)
2045b0563631STom Van Eyck {
2046b0563631STom Van Eyck     if (attributes->type != 0) {
2047b0563631STom Van Eyck         if (attributes->type != slot->attr.type) {
2048b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
2049b0563631STom Van Eyck         }
2050b0563631STom Van Eyck     }
2051b0563631STom Van Eyck 
2052b0563631STom Van Eyck     if (attributes->bits != 0) {
2053b0563631STom Van Eyck         if (attributes->bits != slot->attr.bits) {
2054b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
2055b0563631STom Van Eyck         }
2056b0563631STom Van Eyck     }
2057b0563631STom Van Eyck 
2058b0563631STom Van Eyck     return PSA_SUCCESS;
2059b0563631STom Van Eyck }
2060b0563631STom Van Eyck 
2061b0563631STom Van Eyck psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
2062b0563631STom Van Eyck                             const uint8_t *data_external,
2063b0563631STom Van Eyck                             size_t data_length,
2064b0563631STom Van Eyck                             mbedtls_svc_key_id_t *key)
2065b0563631STom Van Eyck {
2066b0563631STom Van Eyck     psa_status_t status;
2067b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(data_external, data);
2068b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
2069b0563631STom Van Eyck     psa_se_drv_table_entry_t *driver = NULL;
2070b0563631STom Van Eyck     size_t bits;
2071b0563631STom Van Eyck     size_t storage_size = data_length;
2072b0563631STom Van Eyck 
2073b0563631STom Van Eyck     *key = MBEDTLS_SVC_KEY_ID_INIT;
2074b0563631STom Van Eyck 
2075b0563631STom Van Eyck     /* Reject zero-length symmetric keys (including raw data key objects).
2076b0563631STom Van Eyck      * This also rejects any key which might be encoded as an empty string,
2077b0563631STom Van Eyck      * which is never valid. */
2078b0563631STom Van Eyck     if (data_length == 0) {
2079b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
2080b0563631STom Van Eyck     }
2081b0563631STom Van Eyck 
2082b0563631STom Van Eyck     /* Ensure that the bytes-to-bits conversion cannot overflow. */
2083b0563631STom Van Eyck     if (data_length > SIZE_MAX / 8) {
2084b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
2085b0563631STom Van Eyck     }
2086b0563631STom Van Eyck 
2087b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(data_external, data_length, data);
2088b0563631STom Van Eyck 
2089b0563631STom Van Eyck     status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes,
2090b0563631STom Van Eyck                                     &slot, &driver);
2091b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2092b0563631STom Van Eyck         goto exit;
2093b0563631STom Van Eyck     }
2094b0563631STom Van Eyck 
2095b0563631STom Van Eyck     /* In the case of a transparent key or an opaque key stored in local
2096b0563631STom Van Eyck      * storage ( thus not in the case of importing a key in a secure element
2097b0563631STom Van Eyck      * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a
2098b0563631STom Van Eyck      * buffer to hold the imported key material. */
2099b0563631STom Van Eyck     if (slot->key.data == NULL) {
2100b0563631STom Van Eyck         if (psa_key_lifetime_is_external(attributes->lifetime)) {
2101b0563631STom Van Eyck             status = psa_driver_wrapper_get_key_buffer_size_from_key_data(
2102b0563631STom Van Eyck                 attributes, data, data_length, &storage_size);
2103b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
2104b0563631STom Van Eyck                 goto exit;
2105b0563631STom Van Eyck             }
2106b0563631STom Van Eyck         }
2107b0563631STom Van Eyck         status = psa_allocate_buffer_to_slot(slot, storage_size);
2108b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
2109b0563631STom Van Eyck             goto exit;
2110b0563631STom Van Eyck         }
2111b0563631STom Van Eyck     }
2112b0563631STom Van Eyck 
2113b0563631STom Van Eyck     bits = slot->attr.bits;
2114b0563631STom Van Eyck     status = psa_driver_wrapper_import_key(attributes,
2115b0563631STom Van Eyck                                            data, data_length,
2116b0563631STom Van Eyck                                            slot->key.data,
2117b0563631STom Van Eyck                                            slot->key.bytes,
2118b0563631STom Van Eyck                                            &slot->key.bytes, &bits);
2119b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2120b0563631STom Van Eyck         goto exit;
2121b0563631STom Van Eyck     }
2122b0563631STom Van Eyck 
2123b0563631STom Van Eyck     if (slot->attr.bits == 0) {
2124b0563631STom Van Eyck         slot->attr.bits = (psa_key_bits_t) bits;
2125b0563631STom Van Eyck     } else if (bits != slot->attr.bits) {
2126b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
2127b0563631STom Van Eyck         goto exit;
2128b0563631STom Van Eyck     }
2129b0563631STom Van Eyck 
2130b0563631STom Van Eyck     /* Enforce a size limit, and in particular ensure that the bit
2131b0563631STom Van Eyck      * size fits in its representation type.*/
2132b0563631STom Van Eyck     if (bits > PSA_MAX_KEY_BITS) {
2133b0563631STom Van Eyck         status = PSA_ERROR_NOT_SUPPORTED;
2134b0563631STom Van Eyck         goto exit;
2135b0563631STom Van Eyck     }
2136b0563631STom Van Eyck     status = psa_validate_optional_attributes(slot, attributes);
2137b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2138b0563631STom Van Eyck         goto exit;
2139b0563631STom Van Eyck     }
2140b0563631STom Van Eyck 
2141b0563631STom Van Eyck     status = psa_finish_key_creation(slot, driver, key);
2142b0563631STom Van Eyck exit:
2143b0563631STom Van Eyck     LOCAL_INPUT_FREE(data_external, data);
2144b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2145b0563631STom Van Eyck         psa_fail_key_creation(slot, driver);
2146b0563631STom Van Eyck     }
2147b0563631STom Van Eyck 
2148b0563631STom Van Eyck     return status;
2149b0563631STom Van Eyck }
2150b0563631STom Van Eyck 
2151b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
2152b0563631STom Van Eyck psa_status_t mbedtls_psa_register_se_key(
2153b0563631STom Van Eyck     const psa_key_attributes_t *attributes)
2154b0563631STom Van Eyck {
2155b0563631STom Van Eyck     psa_status_t status;
2156b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
2157b0563631STom Van Eyck     psa_se_drv_table_entry_t *driver = NULL;
2158b0563631STom Van Eyck     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
2159b0563631STom Van Eyck 
2160b0563631STom Van Eyck     /* Leaving attributes unspecified is not currently supported.
2161b0563631STom Van Eyck      * It could make sense to query the key type and size from the
2162b0563631STom Van Eyck      * secure element, but not all secure elements support this
2163b0563631STom Van Eyck      * and the driver HAL doesn't currently support it. */
2164b0563631STom Van Eyck     if (psa_get_key_type(attributes) == PSA_KEY_TYPE_NONE) {
2165b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
2166b0563631STom Van Eyck     }
2167b0563631STom Van Eyck     if (psa_get_key_bits(attributes) == 0) {
2168b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
2169b0563631STom Van Eyck     }
2170b0563631STom Van Eyck 
2171*cb034002SJerome Forissier     /* Not usable with volatile keys, even with an appropriate location,
2172*cb034002SJerome Forissier      * due to the API design.
2173*cb034002SJerome Forissier      * https://github.com/Mbed-TLS/mbedtls/issues/9253
2174*cb034002SJerome Forissier      */
2175*cb034002SJerome Forissier     if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(attributes))) {
2176*cb034002SJerome Forissier         return PSA_ERROR_INVALID_ARGUMENT;
2177*cb034002SJerome Forissier     }
2178*cb034002SJerome Forissier 
2179b0563631STom Van Eyck     status = psa_start_key_creation(PSA_KEY_CREATION_REGISTER, attributes,
2180b0563631STom Van Eyck                                     &slot, &driver);
2181b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2182b0563631STom Van Eyck         goto exit;
2183b0563631STom Van Eyck     }
2184b0563631STom Van Eyck 
2185b0563631STom Van Eyck     status = psa_finish_key_creation(slot, driver, &key);
2186b0563631STom Van Eyck 
2187b0563631STom Van Eyck exit:
2188b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2189b0563631STom Van Eyck         psa_fail_key_creation(slot, driver);
2190b0563631STom Van Eyck     }
2191b0563631STom Van Eyck 
2192b0563631STom Van Eyck     /* Registration doesn't keep the key in RAM. */
2193b0563631STom Van Eyck     psa_close_key(key);
2194b0563631STom Van Eyck     return status;
2195b0563631STom Van Eyck }
2196b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
2197b0563631STom Van Eyck 
2198b0563631STom Van Eyck psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key,
2199b0563631STom Van Eyck                           const psa_key_attributes_t *specified_attributes,
2200b0563631STom Van Eyck                           mbedtls_svc_key_id_t *target_key)
2201b0563631STom Van Eyck {
2202b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2203b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
2204b0563631STom Van Eyck     psa_key_slot_t *source_slot = NULL;
2205b0563631STom Van Eyck     psa_key_slot_t *target_slot = NULL;
2206b0563631STom Van Eyck     psa_key_attributes_t actual_attributes = *specified_attributes;
2207b0563631STom Van Eyck     psa_se_drv_table_entry_t *driver = NULL;
2208b0563631STom Van Eyck     size_t storage_size = 0;
2209b0563631STom Van Eyck 
2210b0563631STom Van Eyck     *target_key = MBEDTLS_SVC_KEY_ID_INIT;
2211b0563631STom Van Eyck 
2212b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
2213b0563631STom Van Eyck         source_key, &source_slot, PSA_KEY_USAGE_COPY, 0);
2214b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2215b0563631STom Van Eyck         goto exit;
2216b0563631STom Van Eyck     }
2217b0563631STom Van Eyck 
2218b0563631STom Van Eyck     status = psa_validate_optional_attributes(source_slot,
2219b0563631STom Van Eyck                                               specified_attributes);
2220b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2221b0563631STom Van Eyck         goto exit;
2222b0563631STom Van Eyck     }
2223b0563631STom Van Eyck 
2224b0563631STom Van Eyck     /* The target key type and number of bits have been validated by
2225b0563631STom Van Eyck      * psa_validate_optional_attributes() to be either equal to zero or
2226b0563631STom Van Eyck      * equal to the ones of the source key. So it is safe to inherit
2227b0563631STom Van Eyck      * them from the source key now."
2228b0563631STom Van Eyck      * */
2229b0563631STom Van Eyck     actual_attributes.bits = source_slot->attr.bits;
2230b0563631STom Van Eyck     actual_attributes.type = source_slot->attr.type;
2231b0563631STom Van Eyck 
2232b0563631STom Van Eyck 
2233b0563631STom Van Eyck     status = psa_restrict_key_policy(source_slot->attr.type,
2234b0563631STom Van Eyck                                      &actual_attributes.policy,
2235b0563631STom Van Eyck                                      &source_slot->attr.policy);
2236b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2237b0563631STom Van Eyck         goto exit;
2238b0563631STom Van Eyck     }
2239b0563631STom Van Eyck 
2240b0563631STom Van Eyck     status = psa_start_key_creation(PSA_KEY_CREATION_COPY, &actual_attributes,
2241b0563631STom Van Eyck                                     &target_slot, &driver);
2242b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2243b0563631STom Van Eyck         goto exit;
2244b0563631STom Van Eyck     }
2245b0563631STom Van Eyck     if (PSA_KEY_LIFETIME_GET_LOCATION(target_slot->attr.lifetime) !=
2246b0563631STom Van Eyck         PSA_KEY_LIFETIME_GET_LOCATION(source_slot->attr.lifetime)) {
2247b0563631STom Van Eyck         /*
2248b0563631STom Van Eyck          * If the source and target keys are stored in different locations,
2249b0563631STom Van Eyck          * the source key would need to be exported as plaintext and re-imported
2250b0563631STom Van Eyck          * in the other location. This has security implications which have not
2251b0563631STom Van Eyck          * been fully mapped. For now, this can be achieved through
2252b0563631STom Van Eyck          * appropriate API invocations from the application, if needed.
2253b0563631STom Van Eyck          * */
2254b0563631STom Van Eyck         status = PSA_ERROR_NOT_SUPPORTED;
2255b0563631STom Van Eyck         goto exit;
2256b0563631STom Van Eyck     }
2257b0563631STom Van Eyck     /*
2258b0563631STom Van Eyck      * When the source and target keys are within the same location,
2259b0563631STom Van Eyck      * - For transparent keys it is a blind copy without any driver invocation,
2260b0563631STom Van Eyck      * - For opaque keys this translates to an invocation of the drivers'
2261b0563631STom Van Eyck      *   copy_key entry point through the dispatch layer.
2262b0563631STom Van Eyck      * */
2263b0563631STom Van Eyck     if (psa_key_lifetime_is_external(actual_attributes.lifetime)) {
2264b0563631STom Van Eyck         status = psa_driver_wrapper_get_key_buffer_size(&actual_attributes,
2265b0563631STom Van Eyck                                                         &storage_size);
2266b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
2267b0563631STom Van Eyck             goto exit;
2268b0563631STom Van Eyck         }
2269b0563631STom Van Eyck 
2270b0563631STom Van Eyck         status = psa_allocate_buffer_to_slot(target_slot, storage_size);
2271b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
2272b0563631STom Van Eyck             goto exit;
2273b0563631STom Van Eyck         }
2274b0563631STom Van Eyck 
2275b0563631STom Van Eyck         status = psa_driver_wrapper_copy_key(&actual_attributes,
2276b0563631STom Van Eyck                                              source_slot->key.data,
2277b0563631STom Van Eyck                                              source_slot->key.bytes,
2278b0563631STom Van Eyck                                              target_slot->key.data,
2279b0563631STom Van Eyck                                              target_slot->key.bytes,
2280b0563631STom Van Eyck                                              &target_slot->key.bytes);
2281b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
2282b0563631STom Van Eyck             goto exit;
2283b0563631STom Van Eyck         }
2284b0563631STom Van Eyck     } else {
2285b0563631STom Van Eyck         status = psa_copy_key_material_into_slot(target_slot,
2286b0563631STom Van Eyck                                                  source_slot->key.data,
2287b0563631STom Van Eyck                                                  source_slot->key.bytes);
2288b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
2289b0563631STom Van Eyck             goto exit;
2290b0563631STom Van Eyck         }
2291b0563631STom Van Eyck     }
2292b0563631STom Van Eyck     status = psa_finish_key_creation(target_slot, driver, target_key);
2293b0563631STom Van Eyck exit:
2294b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2295b0563631STom Van Eyck         psa_fail_key_creation(target_slot, driver);
2296b0563631STom Van Eyck     }
2297b0563631STom Van Eyck 
2298b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(source_slot);
2299b0563631STom Van Eyck 
2300b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
2301b0563631STom Van Eyck }
2302b0563631STom Van Eyck 
2303b0563631STom Van Eyck 
2304b0563631STom Van Eyck 
2305b0563631STom Van Eyck /****************************************************************/
2306b0563631STom Van Eyck /* Message digests */
2307b0563631STom Van Eyck /****************************************************************/
2308b0563631STom Van Eyck 
2309b0563631STom Van Eyck psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
2310b0563631STom Van Eyck {
2311b0563631STom Van Eyck     /* Aborting a non-active operation is allowed */
2312b0563631STom Van Eyck     if (operation->id == 0) {
2313b0563631STom Van Eyck         return PSA_SUCCESS;
2314b0563631STom Van Eyck     }
2315b0563631STom Van Eyck 
2316b0563631STom Van Eyck     psa_status_t status = psa_driver_wrapper_hash_abort(operation);
2317b0563631STom Van Eyck     operation->id = 0;
2318b0563631STom Van Eyck 
2319b0563631STom Van Eyck     return status;
2320b0563631STom Van Eyck }
2321b0563631STom Van Eyck 
2322b0563631STom Van Eyck psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
2323b0563631STom Van Eyck                             psa_algorithm_t alg)
2324b0563631STom Van Eyck {
2325b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2326b0563631STom Van Eyck 
2327b0563631STom Van Eyck     /* A context must be freshly initialized before it can be set up. */
2328b0563631STom Van Eyck     if (operation->id != 0) {
2329b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2330b0563631STom Van Eyck         goto exit;
2331b0563631STom Van Eyck     }
2332b0563631STom Van Eyck 
2333b0563631STom Van Eyck     if (!PSA_ALG_IS_HASH(alg)) {
2334b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
2335b0563631STom Van Eyck         goto exit;
2336b0563631STom Van Eyck     }
2337b0563631STom Van Eyck 
2338b0563631STom Van Eyck     /* Ensure all of the context is zeroized, since PSA_HASH_OPERATION_INIT only
2339b0563631STom Van Eyck      * directly zeroes the int-sized dummy member of the context union. */
2340b0563631STom Van Eyck     memset(&operation->ctx, 0, sizeof(operation->ctx));
2341b0563631STom Van Eyck 
2342b0563631STom Van Eyck     status = psa_driver_wrapper_hash_setup(operation, alg);
2343b0563631STom Van Eyck 
2344b0563631STom Van Eyck exit:
2345b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2346b0563631STom Van Eyck         psa_hash_abort(operation);
2347b0563631STom Van Eyck     }
2348b0563631STom Van Eyck 
2349b0563631STom Van Eyck     return status;
2350b0563631STom Van Eyck }
2351b0563631STom Van Eyck 
2352b0563631STom Van Eyck psa_status_t psa_hash_update(psa_hash_operation_t *operation,
2353b0563631STom Van Eyck                              const uint8_t *input_external,
2354b0563631STom Van Eyck                              size_t input_length)
2355b0563631STom Van Eyck {
2356b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2357b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
2358b0563631STom Van Eyck 
2359b0563631STom Van Eyck     if (operation->id == 0) {
2360b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2361b0563631STom Van Eyck         goto exit;
2362b0563631STom Van Eyck     }
2363b0563631STom Van Eyck 
2364b0563631STom Van Eyck     /* Don't require hash implementations to behave correctly on a
2365b0563631STom Van Eyck      * zero-length input, which may have an invalid pointer. */
2366b0563631STom Van Eyck     if (input_length == 0) {
2367b0563631STom Van Eyck         return PSA_SUCCESS;
2368b0563631STom Van Eyck     }
2369b0563631STom Van Eyck 
2370b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
2371b0563631STom Van Eyck     status = psa_driver_wrapper_hash_update(operation, input, input_length);
2372b0563631STom Van Eyck 
2373b0563631STom Van Eyck exit:
2374b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2375b0563631STom Van Eyck         psa_hash_abort(operation);
2376b0563631STom Van Eyck     }
2377b0563631STom Van Eyck 
2378b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
2379b0563631STom Van Eyck     return status;
2380b0563631STom Van Eyck }
2381b0563631STom Van Eyck 
2382b0563631STom Van Eyck static psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation,
2383b0563631STom Van Eyck                                              uint8_t *hash,
2384b0563631STom Van Eyck                                              size_t hash_size,
2385b0563631STom Van Eyck                                              size_t *hash_length)
2386b0563631STom Van Eyck {
2387b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2388b0563631STom Van Eyck 
2389b0563631STom Van Eyck     *hash_length = 0;
2390b0563631STom Van Eyck     if (operation->id == 0) {
2391b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
2392b0563631STom Van Eyck     }
2393b0563631STom Van Eyck 
2394b0563631STom Van Eyck     status = psa_driver_wrapper_hash_finish(
2395b0563631STom Van Eyck         operation, hash, hash_size, hash_length);
2396b0563631STom Van Eyck     psa_hash_abort(operation);
2397b0563631STom Van Eyck 
2398b0563631STom Van Eyck     return status;
2399b0563631STom Van Eyck }
2400b0563631STom Van Eyck 
2401b0563631STom Van Eyck psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
2402b0563631STom Van Eyck                              uint8_t *hash_external,
2403b0563631STom Van Eyck                              size_t hash_size,
2404b0563631STom Van Eyck                              size_t *hash_length)
2405b0563631STom Van Eyck {
2406b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2407b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(hash_external, hash);
2408b0563631STom Van Eyck 
2409b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash);
2410b0563631STom Van Eyck     status = psa_hash_finish_internal(operation, hash, hash_size, hash_length);
2411b0563631STom Van Eyck 
2412b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
2413b0563631STom Van Eyck exit:
2414b0563631STom Van Eyck #endif
2415b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(hash_external, hash);
2416b0563631STom Van Eyck     return status;
2417b0563631STom Van Eyck }
2418b0563631STom Van Eyck 
2419b0563631STom Van Eyck psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
2420b0563631STom Van Eyck                              const uint8_t *hash_external,
2421b0563631STom Van Eyck                              size_t hash_length)
2422b0563631STom Van Eyck {
2423b0563631STom Van Eyck     uint8_t actual_hash[PSA_HASH_MAX_SIZE];
2424b0563631STom Van Eyck     size_t actual_hash_length;
2425b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2426b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(hash_external, hash);
2427b0563631STom Van Eyck 
2428b0563631STom Van Eyck     status = psa_hash_finish_internal(
2429b0563631STom Van Eyck         operation,
2430b0563631STom Van Eyck         actual_hash, sizeof(actual_hash),
2431b0563631STom Van Eyck         &actual_hash_length);
2432b0563631STom Van Eyck 
2433b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2434b0563631STom Van Eyck         goto exit;
2435b0563631STom Van Eyck     }
2436b0563631STom Van Eyck 
2437b0563631STom Van Eyck     if (actual_hash_length != hash_length) {
2438b0563631STom Van Eyck         status = PSA_ERROR_INVALID_SIGNATURE;
2439b0563631STom Van Eyck         goto exit;
2440b0563631STom Van Eyck     }
2441b0563631STom Van Eyck 
2442b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
2443b0563631STom Van Eyck     if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) {
2444b0563631STom Van Eyck         status = PSA_ERROR_INVALID_SIGNATURE;
2445b0563631STom Van Eyck     }
2446b0563631STom Van Eyck 
2447b0563631STom Van Eyck exit:
2448b0563631STom Van Eyck     mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash));
2449b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2450b0563631STom Van Eyck         psa_hash_abort(operation);
2451b0563631STom Van Eyck     }
2452b0563631STom Van Eyck     LOCAL_INPUT_FREE(hash_external, hash);
2453b0563631STom Van Eyck     return status;
2454b0563631STom Van Eyck }
2455b0563631STom Van Eyck 
2456b0563631STom Van Eyck psa_status_t psa_hash_compute(psa_algorithm_t alg,
2457b0563631STom Van Eyck                               const uint8_t *input_external, size_t input_length,
2458b0563631STom Van Eyck                               uint8_t *hash_external, size_t hash_size,
2459b0563631STom Van Eyck                               size_t *hash_length)
2460b0563631STom Van Eyck {
2461b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2462b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
2463b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(hash_external, hash);
2464b0563631STom Van Eyck 
2465b0563631STom Van Eyck     *hash_length = 0;
2466b0563631STom Van Eyck     if (!PSA_ALG_IS_HASH(alg)) {
2467b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
2468b0563631STom Van Eyck     }
2469b0563631STom Van Eyck 
2470b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
2471b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash);
2472b0563631STom Van Eyck     status = psa_driver_wrapper_hash_compute(alg, input, input_length,
2473b0563631STom Van Eyck                                              hash, hash_size, hash_length);
2474b0563631STom Van Eyck 
2475b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
2476b0563631STom Van Eyck exit:
2477b0563631STom Van Eyck #endif
2478b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
2479b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(hash_external, hash);
2480b0563631STom Van Eyck     return status;
2481b0563631STom Van Eyck }
2482b0563631STom Van Eyck 
2483b0563631STom Van Eyck psa_status_t psa_hash_compare(psa_algorithm_t alg,
2484b0563631STom Van Eyck                               const uint8_t *input_external, size_t input_length,
2485b0563631STom Van Eyck                               const uint8_t *hash_external, size_t hash_length)
2486b0563631STom Van Eyck {
2487b0563631STom Van Eyck     uint8_t actual_hash[PSA_HASH_MAX_SIZE];
2488b0563631STom Van Eyck     size_t actual_hash_length;
2489b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2490b0563631STom Van Eyck 
2491b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
2492b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(hash_external, hash);
2493b0563631STom Van Eyck 
2494b0563631STom Van Eyck     if (!PSA_ALG_IS_HASH(alg)) {
2495b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
2496b0563631STom Van Eyck         return status;
2497b0563631STom Van Eyck     }
2498b0563631STom Van Eyck 
2499b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
2500b0563631STom Van Eyck     status = psa_driver_wrapper_hash_compute(
2501b0563631STom Van Eyck         alg, input, input_length,
2502b0563631STom Van Eyck         actual_hash, sizeof(actual_hash),
2503b0563631STom Van Eyck         &actual_hash_length);
2504b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2505b0563631STom Van Eyck         goto exit;
2506b0563631STom Van Eyck     }
2507b0563631STom Van Eyck     if (actual_hash_length != hash_length) {
2508b0563631STom Van Eyck         status = PSA_ERROR_INVALID_SIGNATURE;
2509b0563631STom Van Eyck         goto exit;
2510b0563631STom Van Eyck     }
2511b0563631STom Van Eyck 
2512b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
2513b0563631STom Van Eyck     if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) {
2514b0563631STom Van Eyck         status = PSA_ERROR_INVALID_SIGNATURE;
2515b0563631STom Van Eyck     }
2516b0563631STom Van Eyck 
2517b0563631STom Van Eyck exit:
2518b0563631STom Van Eyck     mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash));
2519b0563631STom Van Eyck 
2520b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
2521b0563631STom Van Eyck     LOCAL_INPUT_FREE(hash_external, hash);
2522b0563631STom Van Eyck 
2523b0563631STom Van Eyck     return status;
2524b0563631STom Van Eyck }
2525b0563631STom Van Eyck 
2526b0563631STom Van Eyck psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
2527b0563631STom Van Eyck                             psa_hash_operation_t *target_operation)
2528b0563631STom Van Eyck {
2529b0563631STom Van Eyck     if (source_operation->id == 0 ||
2530b0563631STom Van Eyck         target_operation->id != 0) {
2531b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
2532b0563631STom Van Eyck     }
2533b0563631STom Van Eyck 
2534b0563631STom Van Eyck     psa_status_t status = psa_driver_wrapper_hash_clone(source_operation,
2535b0563631STom Van Eyck                                                         target_operation);
2536b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2537b0563631STom Van Eyck         psa_hash_abort(target_operation);
2538b0563631STom Van Eyck     }
2539b0563631STom Van Eyck 
2540b0563631STom Van Eyck     return status;
2541b0563631STom Van Eyck }
2542b0563631STom Van Eyck 
2543b0563631STom Van Eyck 
2544b0563631STom Van Eyck /****************************************************************/
2545b0563631STom Van Eyck /* MAC */
2546b0563631STom Van Eyck /****************************************************************/
2547b0563631STom Van Eyck 
2548b0563631STom Van Eyck psa_status_t psa_mac_abort(psa_mac_operation_t *operation)
2549b0563631STom Van Eyck {
2550b0563631STom Van Eyck     /* Aborting a non-active operation is allowed */
2551b0563631STom Van Eyck     if (operation->id == 0) {
2552b0563631STom Van Eyck         return PSA_SUCCESS;
2553b0563631STom Van Eyck     }
2554b0563631STom Van Eyck 
2555b0563631STom Van Eyck     psa_status_t status = psa_driver_wrapper_mac_abort(operation);
2556b0563631STom Van Eyck     operation->mac_size = 0;
2557b0563631STom Van Eyck     operation->is_sign = 0;
2558b0563631STom Van Eyck     operation->id = 0;
2559b0563631STom Van Eyck 
2560b0563631STom Van Eyck     return status;
2561b0563631STom Van Eyck }
2562b0563631STom Van Eyck 
2563b0563631STom Van Eyck static psa_status_t psa_mac_finalize_alg_and_key_validation(
2564b0563631STom Van Eyck     psa_algorithm_t alg,
2565b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
2566b0563631STom Van Eyck     uint8_t *mac_size)
2567b0563631STom Van Eyck {
2568b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2569b0563631STom Van Eyck     psa_key_type_t key_type = psa_get_key_type(attributes);
2570b0563631STom Van Eyck     size_t key_bits = psa_get_key_bits(attributes);
2571b0563631STom Van Eyck 
2572b0563631STom Van Eyck     if (!PSA_ALG_IS_MAC(alg)) {
2573b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
2574b0563631STom Van Eyck     }
2575b0563631STom Van Eyck 
2576b0563631STom Van Eyck     /* Validate the combination of key type and algorithm */
2577b0563631STom Van Eyck     status = psa_mac_key_can_do(alg, key_type);
2578b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2579b0563631STom Van Eyck         return status;
2580b0563631STom Van Eyck     }
2581b0563631STom Van Eyck 
2582b0563631STom Van Eyck     /* Get the output length for the algorithm and key combination */
2583b0563631STom Van Eyck     *mac_size = PSA_MAC_LENGTH(key_type, key_bits, alg);
2584b0563631STom Van Eyck 
2585b0563631STom Van Eyck     if (*mac_size < 4) {
2586b0563631STom Van Eyck         /* A very short MAC is too short for security since it can be
2587b0563631STom Van Eyck          * brute-forced. Ancient protocols with 32-bit MACs do exist,
2588b0563631STom Van Eyck          * so we make this our minimum, even though 32 bits is still
2589b0563631STom Van Eyck          * too small for security. */
2590b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
2591b0563631STom Van Eyck     }
2592b0563631STom Van Eyck 
2593b0563631STom Van Eyck     if (*mac_size > PSA_MAC_LENGTH(key_type, key_bits,
2594b0563631STom Van Eyck                                    PSA_ALG_FULL_LENGTH_MAC(alg))) {
2595b0563631STom Van Eyck         /* It's impossible to "truncate" to a larger length than the full length
2596b0563631STom Van Eyck          * of the algorithm. */
2597b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
2598b0563631STom Van Eyck     }
2599b0563631STom Van Eyck 
2600b0563631STom Van Eyck     if (*mac_size > PSA_MAC_MAX_SIZE) {
2601b0563631STom Van Eyck         /* PSA_MAC_LENGTH returns the correct length even for a MAC algorithm
2602b0563631STom Van Eyck          * that is disabled in the compile-time configuration. The result can
2603b0563631STom Van Eyck          * therefore be larger than PSA_MAC_MAX_SIZE, which does take the
2604b0563631STom Van Eyck          * configuration into account. In this case, force a return of
2605b0563631STom Van Eyck          * PSA_ERROR_NOT_SUPPORTED here. Otherwise psa_mac_verify(), or
2606b0563631STom Van Eyck          * psa_mac_compute(mac_size=PSA_MAC_MAX_SIZE), would return
2607b0563631STom Van Eyck          * PSA_ERROR_BUFFER_TOO_SMALL for an unsupported algorithm whose MAC size
2608b0563631STom Van Eyck          * is larger than PSA_MAC_MAX_SIZE, which is misleading and which breaks
2609b0563631STom Van Eyck          * systematically generated tests. */
2610b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
2611b0563631STom Van Eyck     }
2612b0563631STom Van Eyck 
2613b0563631STom Van Eyck     return PSA_SUCCESS;
2614b0563631STom Van Eyck }
2615b0563631STom Van Eyck 
2616b0563631STom Van Eyck static psa_status_t psa_mac_setup(psa_mac_operation_t *operation,
2617b0563631STom Van Eyck                                   mbedtls_svc_key_id_t key,
2618b0563631STom Van Eyck                                   psa_algorithm_t alg,
2619b0563631STom Van Eyck                                   int is_sign)
2620b0563631STom Van Eyck {
2621b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2622b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
2623b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
2624b0563631STom Van Eyck 
2625b0563631STom Van Eyck     /* A context must be freshly initialized before it can be set up. */
2626b0563631STom Van Eyck     if (operation->id != 0) {
2627b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2628b0563631STom Van Eyck         goto exit;
2629b0563631STom Van Eyck     }
2630b0563631STom Van Eyck 
2631b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
2632b0563631STom Van Eyck         key,
2633b0563631STom Van Eyck         &slot,
2634b0563631STom Van Eyck         is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE,
2635b0563631STom Van Eyck         alg);
2636b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2637b0563631STom Van Eyck         goto exit;
2638b0563631STom Van Eyck     }
2639b0563631STom Van Eyck 
2640b0563631STom Van Eyck     status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr,
2641b0563631STom Van Eyck                                                      &operation->mac_size);
2642b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2643b0563631STom Van Eyck         goto exit;
2644b0563631STom Van Eyck     }
2645b0563631STom Van Eyck 
2646b0563631STom Van Eyck     operation->is_sign = is_sign;
2647b0563631STom Van Eyck     /* Dispatch the MAC setup call with validated input */
2648b0563631STom Van Eyck     if (is_sign) {
2649b0563631STom Van Eyck         status = psa_driver_wrapper_mac_sign_setup(operation,
2650b0563631STom Van Eyck                                                    &slot->attr,
2651b0563631STom Van Eyck                                                    slot->key.data,
2652b0563631STom Van Eyck                                                    slot->key.bytes,
2653b0563631STom Van Eyck                                                    alg);
2654b0563631STom Van Eyck     } else {
2655b0563631STom Van Eyck         status = psa_driver_wrapper_mac_verify_setup(operation,
2656b0563631STom Van Eyck                                                      &slot->attr,
2657b0563631STom Van Eyck                                                      slot->key.data,
2658b0563631STom Van Eyck                                                      slot->key.bytes,
2659b0563631STom Van Eyck                                                      alg);
2660b0563631STom Van Eyck     }
2661b0563631STom Van Eyck 
2662b0563631STom Van Eyck exit:
2663b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2664b0563631STom Van Eyck         psa_mac_abort(operation);
2665b0563631STom Van Eyck     }
2666b0563631STom Van Eyck 
2667b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
2668b0563631STom Van Eyck 
2669b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
2670b0563631STom Van Eyck }
2671b0563631STom Van Eyck 
2672b0563631STom Van Eyck psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
2673b0563631STom Van Eyck                                 mbedtls_svc_key_id_t key,
2674b0563631STom Van Eyck                                 psa_algorithm_t alg)
2675b0563631STom Van Eyck {
2676b0563631STom Van Eyck     return psa_mac_setup(operation, key, alg, 1);
2677b0563631STom Van Eyck }
2678b0563631STom Van Eyck 
2679b0563631STom Van Eyck psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
2680b0563631STom Van Eyck                                   mbedtls_svc_key_id_t key,
2681b0563631STom Van Eyck                                   psa_algorithm_t alg)
2682b0563631STom Van Eyck {
2683b0563631STom Van Eyck     return psa_mac_setup(operation, key, alg, 0);
2684b0563631STom Van Eyck }
2685b0563631STom Van Eyck 
2686b0563631STom Van Eyck psa_status_t psa_mac_update(psa_mac_operation_t *operation,
2687b0563631STom Van Eyck                             const uint8_t *input_external,
2688b0563631STom Van Eyck                             size_t input_length)
2689b0563631STom Van Eyck {
2690b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2691b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
2692b0563631STom Van Eyck 
2693b0563631STom Van Eyck     if (operation->id == 0) {
2694b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2695b0563631STom Van Eyck         return status;
2696b0563631STom Van Eyck     }
2697b0563631STom Van Eyck 
2698b0563631STom Van Eyck     /* Don't require hash implementations to behave correctly on a
2699b0563631STom Van Eyck      * zero-length input, which may have an invalid pointer. */
2700b0563631STom Van Eyck     if (input_length == 0) {
2701b0563631STom Van Eyck         status = PSA_SUCCESS;
2702b0563631STom Van Eyck         return status;
2703b0563631STom Van Eyck     }
2704b0563631STom Van Eyck 
2705b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
2706b0563631STom Van Eyck     status = psa_driver_wrapper_mac_update(operation, input, input_length);
2707b0563631STom Van Eyck 
2708b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2709b0563631STom Van Eyck         psa_mac_abort(operation);
2710b0563631STom Van Eyck     }
2711b0563631STom Van Eyck 
2712b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
2713b0563631STom Van Eyck exit:
2714b0563631STom Van Eyck #endif
2715b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
2716b0563631STom Van Eyck 
2717b0563631STom Van Eyck     return status;
2718b0563631STom Van Eyck }
2719b0563631STom Van Eyck 
2720b0563631STom Van Eyck psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
2721b0563631STom Van Eyck                                  uint8_t *mac_external,
2722b0563631STom Van Eyck                                  size_t mac_size,
2723b0563631STom Van Eyck                                  size_t *mac_length)
2724b0563631STom Van Eyck {
2725b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2726b0563631STom Van Eyck     psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
2727b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(mac_external, mac);
2728b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac);
2729b0563631STom Van Eyck 
2730b0563631STom Van Eyck     if (operation->id == 0) {
2731b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2732b0563631STom Van Eyck         goto exit;
2733b0563631STom Van Eyck     }
2734b0563631STom Van Eyck 
2735b0563631STom Van Eyck     if (!operation->is_sign) {
2736b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2737b0563631STom Van Eyck         goto exit;
2738b0563631STom Van Eyck     }
2739b0563631STom Van Eyck 
2740b0563631STom Van Eyck     /* Sanity check. This will guarantee that mac_size != 0 (and so mac != NULL)
2741b0563631STom Van Eyck      * once all the error checks are done. */
2742b0563631STom Van Eyck     if (operation->mac_size == 0) {
2743b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2744b0563631STom Van Eyck         goto exit;
2745b0563631STom Van Eyck     }
2746b0563631STom Van Eyck 
2747b0563631STom Van Eyck     if (mac_size < operation->mac_size) {
2748b0563631STom Van Eyck         status = PSA_ERROR_BUFFER_TOO_SMALL;
2749b0563631STom Van Eyck         goto exit;
2750b0563631STom Van Eyck     }
2751b0563631STom Van Eyck 
2752b0563631STom Van Eyck 
2753b0563631STom Van Eyck     status = psa_driver_wrapper_mac_sign_finish(operation,
2754b0563631STom Van Eyck                                                 mac, operation->mac_size,
2755b0563631STom Van Eyck                                                 mac_length);
2756b0563631STom Van Eyck 
2757b0563631STom Van Eyck exit:
2758b0563631STom Van Eyck     /* In case of success, set the potential excess room in the output buffer
2759b0563631STom Van Eyck      * to an invalid value, to avoid potentially leaking a longer MAC.
2760b0563631STom Van Eyck      * In case of error, set the output length and content to a safe default,
2761b0563631STom Van Eyck      * such that in case the caller misses an error check, the output would be
2762b0563631STom Van Eyck      * an unachievable MAC.
2763b0563631STom Van Eyck      */
2764b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2765b0563631STom Van Eyck         *mac_length = mac_size;
2766b0563631STom Van Eyck         operation->mac_size = 0;
2767b0563631STom Van Eyck     }
2768b0563631STom Van Eyck 
2769b0563631STom Van Eyck     if (mac != NULL) {
2770b0563631STom Van Eyck         psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);
2771b0563631STom Van Eyck     }
2772b0563631STom Van Eyck 
2773b0563631STom Van Eyck     abort_status = psa_mac_abort(operation);
2774b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(mac_external, mac);
2775b0563631STom Van Eyck 
2776b0563631STom Van Eyck     return status == PSA_SUCCESS ? abort_status : status;
2777b0563631STom Van Eyck }
2778b0563631STom Van Eyck 
2779b0563631STom Van Eyck psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
2780b0563631STom Van Eyck                                    const uint8_t *mac_external,
2781b0563631STom Van Eyck                                    size_t mac_length)
2782b0563631STom Van Eyck {
2783b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2784b0563631STom Van Eyck     psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
2785b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(mac_external, mac);
2786b0563631STom Van Eyck 
2787b0563631STom Van Eyck     if (operation->id == 0) {
2788b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2789b0563631STom Van Eyck         goto exit;
2790b0563631STom Van Eyck     }
2791b0563631STom Van Eyck 
2792b0563631STom Van Eyck     if (operation->is_sign) {
2793b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
2794b0563631STom Van Eyck         goto exit;
2795b0563631STom Van Eyck     }
2796b0563631STom Van Eyck 
2797b0563631STom Van Eyck     if (operation->mac_size != mac_length) {
2798b0563631STom Van Eyck         status = PSA_ERROR_INVALID_SIGNATURE;
2799b0563631STom Van Eyck         goto exit;
2800b0563631STom Van Eyck     }
2801b0563631STom Van Eyck 
2802b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(mac_external, mac_length, mac);
2803b0563631STom Van Eyck     status = psa_driver_wrapper_mac_verify_finish(operation,
2804b0563631STom Van Eyck                                                   mac, mac_length);
2805b0563631STom Van Eyck 
2806b0563631STom Van Eyck exit:
2807b0563631STom Van Eyck     abort_status = psa_mac_abort(operation);
2808b0563631STom Van Eyck     LOCAL_INPUT_FREE(mac_external, mac);
2809b0563631STom Van Eyck 
2810b0563631STom Van Eyck     return status == PSA_SUCCESS ? abort_status : status;
2811b0563631STom Van Eyck }
2812b0563631STom Van Eyck 
2813b0563631STom Van Eyck static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key,
2814b0563631STom Van Eyck                                              psa_algorithm_t alg,
2815b0563631STom Van Eyck                                              const uint8_t *input,
2816b0563631STom Van Eyck                                              size_t input_length,
2817b0563631STom Van Eyck                                              uint8_t *mac,
2818b0563631STom Van Eyck                                              size_t mac_size,
2819b0563631STom Van Eyck                                              size_t *mac_length,
2820b0563631STom Van Eyck                                              int is_sign)
2821b0563631STom Van Eyck {
2822b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2823b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
2824b0563631STom Van Eyck     psa_key_slot_t *slot;
2825b0563631STom Van Eyck     uint8_t operation_mac_size = 0;
2826b0563631STom Van Eyck 
2827b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
2828b0563631STom Van Eyck         key,
2829b0563631STom Van Eyck         &slot,
2830b0563631STom Van Eyck         is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE,
2831b0563631STom Van Eyck         alg);
2832b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2833b0563631STom Van Eyck         goto exit;
2834b0563631STom Van Eyck     }
2835b0563631STom Van Eyck 
2836b0563631STom Van Eyck     status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr,
2837b0563631STom Van Eyck                                                      &operation_mac_size);
2838b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2839b0563631STom Van Eyck         goto exit;
2840b0563631STom Van Eyck     }
2841b0563631STom Van Eyck 
2842b0563631STom Van Eyck     if (mac_size < operation_mac_size) {
2843b0563631STom Van Eyck         status = PSA_ERROR_BUFFER_TOO_SMALL;
2844b0563631STom Van Eyck         goto exit;
2845b0563631STom Van Eyck     }
2846b0563631STom Van Eyck 
2847b0563631STom Van Eyck     status = psa_driver_wrapper_mac_compute(
2848b0563631STom Van Eyck         &slot->attr,
2849b0563631STom Van Eyck         slot->key.data, slot->key.bytes,
2850b0563631STom Van Eyck         alg,
2851b0563631STom Van Eyck         input, input_length,
2852b0563631STom Van Eyck         mac, operation_mac_size, mac_length);
2853b0563631STom Van Eyck 
2854b0563631STom Van Eyck exit:
2855b0563631STom Van Eyck     /* In case of success, set the potential excess room in the output buffer
2856b0563631STom Van Eyck      * to an invalid value, to avoid potentially leaking a longer MAC.
2857b0563631STom Van Eyck      * In case of error, set the output length and content to a safe default,
2858b0563631STom Van Eyck      * such that in case the caller misses an error check, the output would be
2859b0563631STom Van Eyck      * an unachievable MAC.
2860b0563631STom Van Eyck      */
2861b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2862b0563631STom Van Eyck         *mac_length = mac_size;
2863b0563631STom Van Eyck         operation_mac_size = 0;
2864b0563631STom Van Eyck     }
2865b0563631STom Van Eyck 
2866b0563631STom Van Eyck     psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);
2867b0563631STom Van Eyck 
2868b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
2869b0563631STom Van Eyck 
2870b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
2871b0563631STom Van Eyck }
2872b0563631STom Van Eyck 
2873b0563631STom Van Eyck psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key,
2874b0563631STom Van Eyck                              psa_algorithm_t alg,
2875b0563631STom Van Eyck                              const uint8_t *input_external,
2876b0563631STom Van Eyck                              size_t input_length,
2877b0563631STom Van Eyck                              uint8_t *mac_external,
2878b0563631STom Van Eyck                              size_t mac_size,
2879b0563631STom Van Eyck                              size_t *mac_length)
2880b0563631STom Van Eyck {
2881b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2882b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
2883b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(mac_external, mac);
2884b0563631STom Van Eyck 
2885b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
2886b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac);
2887b0563631STom Van Eyck     status = psa_mac_compute_internal(key, alg,
2888b0563631STom Van Eyck                                       input, input_length,
2889b0563631STom Van Eyck                                       mac, mac_size, mac_length, 1);
2890b0563631STom Van Eyck 
2891b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
2892b0563631STom Van Eyck exit:
2893b0563631STom Van Eyck #endif
2894b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
2895b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(mac_external, mac);
2896b0563631STom Van Eyck 
2897b0563631STom Van Eyck     return status;
2898b0563631STom Van Eyck }
2899b0563631STom Van Eyck 
2900b0563631STom Van Eyck psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key,
2901b0563631STom Van Eyck                             psa_algorithm_t alg,
2902b0563631STom Van Eyck                             const uint8_t *input_external,
2903b0563631STom Van Eyck                             size_t input_length,
2904b0563631STom Van Eyck                             const uint8_t *mac_external,
2905b0563631STom Van Eyck                             size_t mac_length)
2906b0563631STom Van Eyck {
2907b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2908b0563631STom Van Eyck     uint8_t actual_mac[PSA_MAC_MAX_SIZE];
2909b0563631STom Van Eyck     size_t actual_mac_length;
2910b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
2911b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(mac_external, mac);
2912b0563631STom Van Eyck 
2913b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
2914b0563631STom Van Eyck     status = psa_mac_compute_internal(key, alg,
2915b0563631STom Van Eyck                                       input, input_length,
2916b0563631STom Van Eyck                                       actual_mac, sizeof(actual_mac),
2917b0563631STom Van Eyck                                       &actual_mac_length, 0);
2918b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2919b0563631STom Van Eyck         goto exit;
2920b0563631STom Van Eyck     }
2921b0563631STom Van Eyck 
2922b0563631STom Van Eyck     if (mac_length != actual_mac_length) {
2923b0563631STom Van Eyck         status = PSA_ERROR_INVALID_SIGNATURE;
2924b0563631STom Van Eyck         goto exit;
2925b0563631STom Van Eyck     }
2926b0563631STom Van Eyck 
2927b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(mac_external, mac_length, mac);
2928b0563631STom Van Eyck     if (mbedtls_ct_memcmp(mac, actual_mac, actual_mac_length) != 0) {
2929b0563631STom Van Eyck         status = PSA_ERROR_INVALID_SIGNATURE;
2930b0563631STom Van Eyck         goto exit;
2931b0563631STom Van Eyck     }
2932b0563631STom Van Eyck 
2933b0563631STom Van Eyck exit:
2934b0563631STom Van Eyck     mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));
2935b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
2936b0563631STom Van Eyck     LOCAL_INPUT_FREE(mac_external, mac);
2937b0563631STom Van Eyck 
2938b0563631STom Van Eyck     return status;
2939b0563631STom Van Eyck }
2940b0563631STom Van Eyck 
2941b0563631STom Van Eyck /****************************************************************/
2942b0563631STom Van Eyck /* Asymmetric cryptography */
2943b0563631STom Van Eyck /****************************************************************/
2944b0563631STom Van Eyck 
2945b0563631STom Van Eyck static psa_status_t psa_sign_verify_check_alg(int input_is_message,
2946b0563631STom Van Eyck                                               psa_algorithm_t alg)
2947b0563631STom Van Eyck {
2948b0563631STom Van Eyck     if (input_is_message) {
2949b0563631STom Van Eyck         if (!PSA_ALG_IS_SIGN_MESSAGE(alg)) {
2950b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
2951b0563631STom Van Eyck         }
2952b0563631STom Van Eyck 
2953b0563631STom Van Eyck         if (PSA_ALG_IS_SIGN_HASH(alg)) {
2954b0563631STom Van Eyck             if (!PSA_ALG_IS_HASH(PSA_ALG_SIGN_GET_HASH(alg))) {
2955b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
2956b0563631STom Van Eyck             }
2957b0563631STom Van Eyck         }
2958b0563631STom Van Eyck     } else {
2959b0563631STom Van Eyck         if (!PSA_ALG_IS_SIGN_HASH(alg)) {
2960b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
2961b0563631STom Van Eyck         }
2962b0563631STom Van Eyck     }
2963b0563631STom Van Eyck 
2964b0563631STom Van Eyck     return PSA_SUCCESS;
2965b0563631STom Van Eyck }
2966b0563631STom Van Eyck 
2967b0563631STom Van Eyck static psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key,
2968b0563631STom Van Eyck                                       int input_is_message,
2969b0563631STom Van Eyck                                       psa_algorithm_t alg,
2970b0563631STom Van Eyck                                       const uint8_t *input,
2971b0563631STom Van Eyck                                       size_t input_length,
2972b0563631STom Van Eyck                                       uint8_t *signature,
2973b0563631STom Van Eyck                                       size_t signature_size,
2974b0563631STom Van Eyck                                       size_t *signature_length)
2975b0563631STom Van Eyck {
2976b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2977b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
2978b0563631STom Van Eyck     psa_key_slot_t *slot;
2979b0563631STom Van Eyck 
2980b0563631STom Van Eyck     *signature_length = 0;
2981b0563631STom Van Eyck 
2982b0563631STom Van Eyck     status = psa_sign_verify_check_alg(input_is_message, alg);
2983b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
2984b0563631STom Van Eyck         return status;
2985b0563631STom Van Eyck     }
2986b0563631STom Van Eyck 
2987b0563631STom Van Eyck     /* Immediately reject a zero-length signature buffer. This guarantees
2988b0563631STom Van Eyck      * that signature must be a valid pointer. (On the other hand, the input
2989b0563631STom Van Eyck      * buffer can in principle be empty since it doesn't actually have
2990b0563631STom Van Eyck      * to be a hash.) */
2991b0563631STom Van Eyck     if (signature_size == 0) {
2992b0563631STom Van Eyck         return PSA_ERROR_BUFFER_TOO_SMALL;
2993b0563631STom Van Eyck     }
2994b0563631STom Van Eyck 
2995b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
2996b0563631STom Van Eyck         key, &slot,
2997b0563631STom Van Eyck         input_is_message ? PSA_KEY_USAGE_SIGN_MESSAGE :
2998b0563631STom Van Eyck         PSA_KEY_USAGE_SIGN_HASH,
2999b0563631STom Van Eyck         alg);
3000b0563631STom Van Eyck 
3001b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3002b0563631STom Van Eyck         goto exit;
3003b0563631STom Van Eyck     }
3004b0563631STom Van Eyck 
3005b0563631STom Van Eyck     if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
3006b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
3007b0563631STom Van Eyck         goto exit;
3008b0563631STom Van Eyck     }
3009b0563631STom Van Eyck 
3010b0563631STom Van Eyck     if (input_is_message) {
3011b0563631STom Van Eyck         status = psa_driver_wrapper_sign_message(
3012b0563631STom Van Eyck             &slot->attr, slot->key.data, slot->key.bytes,
3013b0563631STom Van Eyck             alg, input, input_length,
3014b0563631STom Van Eyck             signature, signature_size, signature_length);
3015b0563631STom Van Eyck     } else {
3016b0563631STom Van Eyck 
3017b0563631STom Van Eyck         status = psa_driver_wrapper_sign_hash(
3018b0563631STom Van Eyck             &slot->attr, slot->key.data, slot->key.bytes,
3019b0563631STom Van Eyck             alg, input, input_length,
3020b0563631STom Van Eyck             signature, signature_size, signature_length);
3021b0563631STom Van Eyck     }
3022b0563631STom Van Eyck 
3023b0563631STom Van Eyck 
3024b0563631STom Van Eyck exit:
3025b0563631STom Van Eyck     psa_wipe_tag_output_buffer(signature, status, signature_size,
3026b0563631STom Van Eyck                                *signature_length);
3027b0563631STom Van Eyck 
3028b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
3029b0563631STom Van Eyck 
3030b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
3031b0563631STom Van Eyck }
3032b0563631STom Van Eyck 
3033b0563631STom Van Eyck static psa_status_t psa_verify_internal(mbedtls_svc_key_id_t key,
3034b0563631STom Van Eyck                                         int input_is_message,
3035b0563631STom Van Eyck                                         psa_algorithm_t alg,
3036b0563631STom Van Eyck                                         const uint8_t *input,
3037b0563631STom Van Eyck                                         size_t input_length,
3038b0563631STom Van Eyck                                         const uint8_t *signature,
3039b0563631STom Van Eyck                                         size_t signature_length)
3040b0563631STom Van Eyck {
3041b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3042b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
3043b0563631STom Van Eyck     psa_key_slot_t *slot;
3044b0563631STom Van Eyck 
3045b0563631STom Van Eyck     status = psa_sign_verify_check_alg(input_is_message, alg);
3046b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3047b0563631STom Van Eyck         return status;
3048b0563631STom Van Eyck     }
3049b0563631STom Van Eyck 
3050b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
3051b0563631STom Van Eyck         key, &slot,
3052b0563631STom Van Eyck         input_is_message ? PSA_KEY_USAGE_VERIFY_MESSAGE :
3053b0563631STom Van Eyck         PSA_KEY_USAGE_VERIFY_HASH,
3054b0563631STom Van Eyck         alg);
3055b0563631STom Van Eyck 
3056b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3057b0563631STom Van Eyck         return status;
3058b0563631STom Van Eyck     }
3059b0563631STom Van Eyck 
3060b0563631STom Van Eyck     if (input_is_message) {
3061b0563631STom Van Eyck         status = psa_driver_wrapper_verify_message(
3062b0563631STom Van Eyck             &slot->attr, slot->key.data, slot->key.bytes,
3063b0563631STom Van Eyck             alg, input, input_length,
3064b0563631STom Van Eyck             signature, signature_length);
3065b0563631STom Van Eyck     } else {
3066b0563631STom Van Eyck         status = psa_driver_wrapper_verify_hash(
3067b0563631STom Van Eyck             &slot->attr, slot->key.data, slot->key.bytes,
3068b0563631STom Van Eyck             alg, input, input_length,
3069b0563631STom Van Eyck             signature, signature_length);
3070b0563631STom Van Eyck     }
3071b0563631STom Van Eyck 
3072b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
3073b0563631STom Van Eyck 
3074b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
3075b0563631STom Van Eyck 
3076b0563631STom Van Eyck }
3077b0563631STom Van Eyck 
3078b0563631STom Van Eyck psa_status_t psa_sign_message_builtin(
3079b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
3080b0563631STom Van Eyck     const uint8_t *key_buffer,
3081b0563631STom Van Eyck     size_t key_buffer_size,
3082b0563631STom Van Eyck     psa_algorithm_t alg,
3083b0563631STom Van Eyck     const uint8_t *input,
3084b0563631STom Van Eyck     size_t input_length,
3085b0563631STom Van Eyck     uint8_t *signature,
3086b0563631STom Van Eyck     size_t signature_size,
3087b0563631STom Van Eyck     size_t *signature_length)
3088b0563631STom Van Eyck {
3089b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3090b0563631STom Van Eyck 
3091b0563631STom Van Eyck     if (PSA_ALG_IS_SIGN_HASH(alg)) {
3092b0563631STom Van Eyck         size_t hash_length;
3093b0563631STom Van Eyck         uint8_t hash[PSA_HASH_MAX_SIZE];
3094b0563631STom Van Eyck 
3095b0563631STom Van Eyck         status = psa_driver_wrapper_hash_compute(
3096b0563631STom Van Eyck             PSA_ALG_SIGN_GET_HASH(alg),
3097b0563631STom Van Eyck             input, input_length,
3098b0563631STom Van Eyck             hash, sizeof(hash), &hash_length);
3099b0563631STom Van Eyck 
3100b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
3101b0563631STom Van Eyck             return status;
3102b0563631STom Van Eyck         }
3103b0563631STom Van Eyck 
3104b0563631STom Van Eyck         return psa_driver_wrapper_sign_hash(
3105b0563631STom Van Eyck             attributes, key_buffer, key_buffer_size,
3106b0563631STom Van Eyck             alg, hash, hash_length,
3107b0563631STom Van Eyck             signature, signature_size, signature_length);
3108b0563631STom Van Eyck     }
3109b0563631STom Van Eyck 
3110b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
3111b0563631STom Van Eyck }
3112b0563631STom Van Eyck 
3113b0563631STom Van Eyck psa_status_t psa_sign_message(mbedtls_svc_key_id_t key,
3114b0563631STom Van Eyck                               psa_algorithm_t alg,
3115b0563631STom Van Eyck                               const uint8_t *input_external,
3116b0563631STom Van Eyck                               size_t input_length,
3117b0563631STom Van Eyck                               uint8_t *signature_external,
3118b0563631STom Van Eyck                               size_t signature_size,
3119b0563631STom Van Eyck                               size_t *signature_length)
3120b0563631STom Van Eyck {
3121b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3122b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
3123b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(signature_external, signature);
3124b0563631STom Van Eyck 
3125b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
3126b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
3127b0563631STom Van Eyck     status = psa_sign_internal(key, 1, alg, input, input_length, signature,
3128b0563631STom Van Eyck                                signature_size, signature_length);
3129b0563631STom Van Eyck 
3130b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
3131b0563631STom Van Eyck exit:
3132b0563631STom Van Eyck #endif
3133b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
3134b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(signature_external, signature);
3135b0563631STom Van Eyck     return status;
3136b0563631STom Van Eyck }
3137b0563631STom Van Eyck 
3138b0563631STom Van Eyck psa_status_t psa_verify_message_builtin(
3139b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
3140b0563631STom Van Eyck     const uint8_t *key_buffer,
3141b0563631STom Van Eyck     size_t key_buffer_size,
3142b0563631STom Van Eyck     psa_algorithm_t alg,
3143b0563631STom Van Eyck     const uint8_t *input,
3144b0563631STom Van Eyck     size_t input_length,
3145b0563631STom Van Eyck     const uint8_t *signature,
3146b0563631STom Van Eyck     size_t signature_length)
3147b0563631STom Van Eyck {
3148b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3149b0563631STom Van Eyck 
3150b0563631STom Van Eyck     if (PSA_ALG_IS_SIGN_HASH(alg)) {
3151b0563631STom Van Eyck         size_t hash_length;
3152b0563631STom Van Eyck         uint8_t hash[PSA_HASH_MAX_SIZE];
3153b0563631STom Van Eyck 
3154b0563631STom Van Eyck         status = psa_driver_wrapper_hash_compute(
3155b0563631STom Van Eyck             PSA_ALG_SIGN_GET_HASH(alg),
3156b0563631STom Van Eyck             input, input_length,
3157b0563631STom Van Eyck             hash, sizeof(hash), &hash_length);
3158b0563631STom Van Eyck 
3159b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
3160b0563631STom Van Eyck             return status;
3161b0563631STom Van Eyck         }
3162b0563631STom Van Eyck 
3163b0563631STom Van Eyck         return psa_driver_wrapper_verify_hash(
3164b0563631STom Van Eyck             attributes, key_buffer, key_buffer_size,
3165b0563631STom Van Eyck             alg, hash, hash_length,
3166b0563631STom Van Eyck             signature, signature_length);
3167b0563631STom Van Eyck     }
3168b0563631STom Van Eyck 
3169b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
3170b0563631STom Van Eyck }
3171b0563631STom Van Eyck 
3172b0563631STom Van Eyck psa_status_t psa_verify_message(mbedtls_svc_key_id_t key,
3173b0563631STom Van Eyck                                 psa_algorithm_t alg,
3174b0563631STom Van Eyck                                 const uint8_t *input_external,
3175b0563631STom Van Eyck                                 size_t input_length,
3176b0563631STom Van Eyck                                 const uint8_t *signature_external,
3177b0563631STom Van Eyck                                 size_t signature_length)
3178b0563631STom Van Eyck {
3179b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3180b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
3181b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(signature_external, signature);
3182b0563631STom Van Eyck 
3183b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
3184b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
3185b0563631STom Van Eyck     status = psa_verify_internal(key, 1, alg, input, input_length, signature,
3186b0563631STom Van Eyck                                  signature_length);
3187b0563631STom Van Eyck 
3188b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
3189b0563631STom Van Eyck exit:
3190b0563631STom Van Eyck #endif
3191b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
3192b0563631STom Van Eyck     LOCAL_INPUT_FREE(signature_external, signature);
3193b0563631STom Van Eyck 
3194b0563631STom Van Eyck     return status;
3195b0563631STom Van Eyck }
3196b0563631STom Van Eyck 
3197b0563631STom Van Eyck psa_status_t psa_sign_hash_builtin(
3198b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
3199b0563631STom Van Eyck     const uint8_t *key_buffer, size_t key_buffer_size,
3200b0563631STom Van Eyck     psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
3201b0563631STom Van Eyck     uint8_t *signature, size_t signature_size, size_t *signature_length)
3202b0563631STom Van Eyck {
3203b0563631STom Van Eyck     if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
3204b0563631STom Van Eyck         if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
3205b0563631STom Van Eyck             PSA_ALG_IS_RSA_PSS(alg)) {
3206b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
3207b0563631STom Van Eyck             defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
3208b0563631STom Van Eyck             return mbedtls_psa_rsa_sign_hash(
3209b0563631STom Van Eyck                 attributes,
3210b0563631STom Van Eyck                 key_buffer, key_buffer_size,
3211b0563631STom Van Eyck                 alg, hash, hash_length,
3212b0563631STom Van Eyck                 signature, signature_size, signature_length);
3213b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
3214b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
3215b0563631STom Van Eyck         } else {
3216b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
3217b0563631STom Van Eyck         }
3218b0563631STom Van Eyck     } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {
3219b0563631STom Van Eyck         if (PSA_ALG_IS_ECDSA(alg)) {
3220b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
3221b0563631STom Van Eyck             defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
3222b0563631STom Van Eyck             return mbedtls_psa_ecdsa_sign_hash(
3223b0563631STom Van Eyck                 attributes,
3224b0563631STom Van Eyck                 key_buffer, key_buffer_size,
3225b0563631STom Van Eyck                 alg, hash, hash_length,
3226b0563631STom Van Eyck                 signature, signature_size, signature_length);
3227b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
3228b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
3229b0563631STom Van Eyck         } else {
3230b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
3231b0563631STom Van Eyck         }
3232b0563631STom Van Eyck     }
3233b0563631STom Van Eyck 
3234b0563631STom Van Eyck     (void) key_buffer;
3235b0563631STom Van Eyck     (void) key_buffer_size;
3236b0563631STom Van Eyck     (void) hash;
3237b0563631STom Van Eyck     (void) hash_length;
3238b0563631STom Van Eyck     (void) signature;
3239b0563631STom Van Eyck     (void) signature_size;
3240b0563631STom Van Eyck     (void) signature_length;
3241b0563631STom Van Eyck 
3242b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
3243b0563631STom Van Eyck }
3244b0563631STom Van Eyck 
3245b0563631STom Van Eyck psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key,
3246b0563631STom Van Eyck                            psa_algorithm_t alg,
3247b0563631STom Van Eyck                            const uint8_t *hash_external,
3248b0563631STom Van Eyck                            size_t hash_length,
3249b0563631STom Van Eyck                            uint8_t *signature_external,
3250b0563631STom Van Eyck                            size_t signature_size,
3251b0563631STom Van Eyck                            size_t *signature_length)
3252b0563631STom Van Eyck {
3253b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3254b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(hash_external, hash);
3255b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(signature_external, signature);
3256b0563631STom Van Eyck 
3257b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
3258b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
3259b0563631STom Van Eyck     status = psa_sign_internal(key, 0, alg, hash, hash_length, signature,
3260b0563631STom Van Eyck                                signature_size, signature_length);
3261b0563631STom Van Eyck 
3262b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
3263b0563631STom Van Eyck exit:
3264b0563631STom Van Eyck #endif
3265b0563631STom Van Eyck     LOCAL_INPUT_FREE(hash_external, hash);
3266b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(signature_external, signature);
3267b0563631STom Van Eyck 
3268b0563631STom Van Eyck     return status;
3269b0563631STom Van Eyck }
3270b0563631STom Van Eyck 
3271b0563631STom Van Eyck psa_status_t psa_verify_hash_builtin(
3272b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
3273b0563631STom Van Eyck     const uint8_t *key_buffer, size_t key_buffer_size,
3274b0563631STom Van Eyck     psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
3275b0563631STom Van Eyck     const uint8_t *signature, size_t signature_length)
3276b0563631STom Van Eyck {
3277b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {
3278b0563631STom Van Eyck         if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
3279b0563631STom Van Eyck             PSA_ALG_IS_RSA_PSS(alg)) {
3280b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
3281b0563631STom Van Eyck             defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
3282b0563631STom Van Eyck             return mbedtls_psa_rsa_verify_hash(
3283b0563631STom Van Eyck                 attributes,
3284b0563631STom Van Eyck                 key_buffer, key_buffer_size,
3285b0563631STom Van Eyck                 alg, hash, hash_length,
3286b0563631STom Van Eyck                 signature, signature_length);
3287b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
3288b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
3289b0563631STom Van Eyck         } else {
3290b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
3291b0563631STom Van Eyck         }
3292b0563631STom Van Eyck     } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {
3293b0563631STom Van Eyck         if (PSA_ALG_IS_ECDSA(alg)) {
3294b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
3295b0563631STom Van Eyck             defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
3296b0563631STom Van Eyck             return mbedtls_psa_ecdsa_verify_hash(
3297b0563631STom Van Eyck                 attributes,
3298b0563631STom Van Eyck                 key_buffer, key_buffer_size,
3299b0563631STom Van Eyck                 alg, hash, hash_length,
3300b0563631STom Van Eyck                 signature, signature_length);
3301b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
3302b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
3303b0563631STom Van Eyck         } else {
3304b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
3305b0563631STom Van Eyck         }
3306b0563631STom Van Eyck     }
3307b0563631STom Van Eyck 
3308b0563631STom Van Eyck     (void) key_buffer;
3309b0563631STom Van Eyck     (void) key_buffer_size;
3310b0563631STom Van Eyck     (void) hash;
3311b0563631STom Van Eyck     (void) hash_length;
3312b0563631STom Van Eyck     (void) signature;
3313b0563631STom Van Eyck     (void) signature_length;
3314b0563631STom Van Eyck 
3315b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
3316b0563631STom Van Eyck }
3317b0563631STom Van Eyck 
3318b0563631STom Van Eyck psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key,
3319b0563631STom Van Eyck                              psa_algorithm_t alg,
3320b0563631STom Van Eyck                              const uint8_t *hash_external,
3321b0563631STom Van Eyck                              size_t hash_length,
3322b0563631STom Van Eyck                              const uint8_t *signature_external,
3323b0563631STom Van Eyck                              size_t signature_length)
3324b0563631STom Van Eyck {
3325b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3326b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(hash_external, hash);
3327b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(signature_external, signature);
3328b0563631STom Van Eyck 
3329b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
3330b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
3331b0563631STom Van Eyck     status = psa_verify_internal(key, 0, alg, hash, hash_length, signature,
3332b0563631STom Van Eyck                                  signature_length);
3333b0563631STom Van Eyck 
3334b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
3335b0563631STom Van Eyck exit:
3336b0563631STom Van Eyck #endif
3337b0563631STom Van Eyck     LOCAL_INPUT_FREE(hash_external, hash);
3338b0563631STom Van Eyck     LOCAL_INPUT_FREE(signature_external, signature);
3339b0563631STom Van Eyck 
3340b0563631STom Van Eyck     return status;
3341b0563631STom Van Eyck }
3342b0563631STom Van Eyck 
3343b0563631STom Van Eyck psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key,
3344b0563631STom Van Eyck                                     psa_algorithm_t alg,
3345b0563631STom Van Eyck                                     const uint8_t *input_external,
3346b0563631STom Van Eyck                                     size_t input_length,
3347b0563631STom Van Eyck                                     const uint8_t *salt_external,
3348b0563631STom Van Eyck                                     size_t salt_length,
3349b0563631STom Van Eyck                                     uint8_t *output_external,
3350b0563631STom Van Eyck                                     size_t output_size,
3351b0563631STom Van Eyck                                     size_t *output_length)
3352b0563631STom Van Eyck {
3353b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3354b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
3355b0563631STom Van Eyck     psa_key_slot_t *slot;
3356b0563631STom Van Eyck 
3357b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
3358b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(salt_external, salt);
3359b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
3360b0563631STom Van Eyck 
3361b0563631STom Van Eyck     (void) input;
3362b0563631STom Van Eyck     (void) input_length;
3363b0563631STom Van Eyck     (void) salt;
3364b0563631STom Van Eyck     (void) output;
3365b0563631STom Van Eyck     (void) output_size;
3366b0563631STom Van Eyck 
3367b0563631STom Van Eyck     *output_length = 0;
3368b0563631STom Van Eyck 
3369b0563631STom Van Eyck     if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) {
3370b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
3371b0563631STom Van Eyck     }
3372b0563631STom Van Eyck 
3373b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
3374b0563631STom Van Eyck         key, &slot, PSA_KEY_USAGE_ENCRYPT, alg);
3375b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3376b0563631STom Van Eyck         return status;
3377b0563631STom Van Eyck     }
3378b0563631STom Van Eyck     if (!(PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type) ||
3379b0563631STom Van Eyck           PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type))) {
3380b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
3381b0563631STom Van Eyck         goto exit;
3382b0563631STom Van Eyck     }
3383b0563631STom Van Eyck 
3384b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
3385b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);
3386b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
3387b0563631STom Van Eyck 
3388b0563631STom Van Eyck     status = psa_driver_wrapper_asymmetric_encrypt(
3389b0563631STom Van Eyck         &slot->attr, slot->key.data, slot->key.bytes,
3390b0563631STom Van Eyck         alg, input, input_length, salt, salt_length,
3391b0563631STom Van Eyck         output, output_size, output_length);
3392b0563631STom Van Eyck exit:
3393b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
3394b0563631STom Van Eyck 
3395b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
3396b0563631STom Van Eyck     LOCAL_INPUT_FREE(salt_external, salt);
3397b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
3398b0563631STom Van Eyck 
3399b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
3400b0563631STom Van Eyck }
3401b0563631STom Van Eyck 
3402b0563631STom Van Eyck psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key,
3403b0563631STom Van Eyck                                     psa_algorithm_t alg,
3404b0563631STom Van Eyck                                     const uint8_t *input_external,
3405b0563631STom Van Eyck                                     size_t input_length,
3406b0563631STom Van Eyck                                     const uint8_t *salt_external,
3407b0563631STom Van Eyck                                     size_t salt_length,
3408b0563631STom Van Eyck                                     uint8_t *output_external,
3409b0563631STom Van Eyck                                     size_t output_size,
3410b0563631STom Van Eyck                                     size_t *output_length)
3411b0563631STom Van Eyck {
3412b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3413b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
3414b0563631STom Van Eyck     psa_key_slot_t *slot;
3415b0563631STom Van Eyck 
3416b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
3417b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(salt_external, salt);
3418b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
3419b0563631STom Van Eyck 
3420b0563631STom Van Eyck     (void) input;
3421b0563631STom Van Eyck     (void) input_length;
3422b0563631STom Van Eyck     (void) salt;
3423b0563631STom Van Eyck     (void) output;
3424b0563631STom Van Eyck     (void) output_size;
3425b0563631STom Van Eyck 
3426b0563631STom Van Eyck     *output_length = 0;
3427b0563631STom Van Eyck 
3428b0563631STom Van Eyck     if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) {
3429b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
3430b0563631STom Van Eyck     }
3431b0563631STom Van Eyck 
3432b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
3433b0563631STom Van Eyck         key, &slot, PSA_KEY_USAGE_DECRYPT, alg);
3434b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3435b0563631STom Van Eyck         return status;
3436b0563631STom Van Eyck     }
3437b0563631STom Van Eyck     if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
3438b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
3439b0563631STom Van Eyck         goto exit;
3440b0563631STom Van Eyck     }
3441b0563631STom Van Eyck 
3442b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
3443b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);
3444b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
3445b0563631STom Van Eyck 
3446b0563631STom Van Eyck     status = psa_driver_wrapper_asymmetric_decrypt(
3447b0563631STom Van Eyck         &slot->attr, slot->key.data, slot->key.bytes,
3448b0563631STom Van Eyck         alg, input, input_length, salt, salt_length,
3449b0563631STom Van Eyck         output, output_size, output_length);
3450b0563631STom Van Eyck 
3451b0563631STom Van Eyck exit:
3452b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
3453b0563631STom Van Eyck 
3454b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
3455b0563631STom Van Eyck     LOCAL_INPUT_FREE(salt_external, salt);
3456b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
3457b0563631STom Van Eyck 
3458b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
3459b0563631STom Van Eyck }
3460b0563631STom Van Eyck 
3461b0563631STom Van Eyck /****************************************************************/
3462b0563631STom Van Eyck /* Asymmetric interruptible cryptography                        */
3463b0563631STom Van Eyck /****************************************************************/
3464b0563631STom Van Eyck 
3465b0563631STom Van Eyck static uint32_t psa_interruptible_max_ops = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED;
3466b0563631STom Van Eyck 
3467b0563631STom Van Eyck void psa_interruptible_set_max_ops(uint32_t max_ops)
3468b0563631STom Van Eyck {
3469b0563631STom Van Eyck     psa_interruptible_max_ops = max_ops;
3470b0563631STom Van Eyck }
3471b0563631STom Van Eyck 
3472b0563631STom Van Eyck uint32_t psa_interruptible_get_max_ops(void)
3473b0563631STom Van Eyck {
3474b0563631STom Van Eyck     return psa_interruptible_max_ops;
3475b0563631STom Van Eyck }
3476b0563631STom Van Eyck 
3477b0563631STom Van Eyck uint32_t psa_sign_hash_get_num_ops(
3478b0563631STom Van Eyck     const psa_sign_hash_interruptible_operation_t *operation)
3479b0563631STom Van Eyck {
3480b0563631STom Van Eyck     return operation->num_ops;
3481b0563631STom Van Eyck }
3482b0563631STom Van Eyck 
3483b0563631STom Van Eyck uint32_t psa_verify_hash_get_num_ops(
3484b0563631STom Van Eyck     const psa_verify_hash_interruptible_operation_t *operation)
3485b0563631STom Van Eyck {
3486b0563631STom Van Eyck     return operation->num_ops;
3487b0563631STom Van Eyck }
3488b0563631STom Van Eyck 
3489b0563631STom Van Eyck static psa_status_t psa_sign_hash_abort_internal(
3490b0563631STom Van Eyck     psa_sign_hash_interruptible_operation_t *operation)
3491b0563631STom Van Eyck {
3492b0563631STom Van Eyck     if (operation->id == 0) {
3493b0563631STom Van Eyck         /* The object has (apparently) been initialized but it is not (yet)
3494b0563631STom Van Eyck          * in use. It's ok to call abort on such an object, and there's
3495b0563631STom Van Eyck          * nothing to do. */
3496b0563631STom Van Eyck         return PSA_SUCCESS;
3497b0563631STom Van Eyck     }
3498b0563631STom Van Eyck 
3499b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3500b0563631STom Van Eyck 
3501b0563631STom Van Eyck     status = psa_driver_wrapper_sign_hash_abort(operation);
3502b0563631STom Van Eyck 
3503b0563631STom Van Eyck     operation->id = 0;
3504b0563631STom Van Eyck 
3505b0563631STom Van Eyck     /* Do not clear either the error_occurred or num_ops elements here as they
3506b0563631STom Van Eyck      * only want to be cleared by the application calling abort, not by abort
3507b0563631STom Van Eyck      * being called at completion of an operation. */
3508b0563631STom Van Eyck 
3509b0563631STom Van Eyck     return status;
3510b0563631STom Van Eyck }
3511b0563631STom Van Eyck 
3512b0563631STom Van Eyck psa_status_t psa_sign_hash_start(
3513b0563631STom Van Eyck     psa_sign_hash_interruptible_operation_t *operation,
3514b0563631STom Van Eyck     mbedtls_svc_key_id_t key, psa_algorithm_t alg,
3515b0563631STom Van Eyck     const uint8_t *hash_external, size_t hash_length)
3516b0563631STom Van Eyck {
3517b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3518b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
3519b0563631STom Van Eyck     psa_key_slot_t *slot;
3520b0563631STom Van Eyck 
3521b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(hash_external, hash);
3522b0563631STom Van Eyck 
3523b0563631STom Van Eyck     /* Check that start has not been previously called, or operation has not
3524b0563631STom Van Eyck      * previously errored. */
3525b0563631STom Van Eyck     if (operation->id != 0 || operation->error_occurred) {
3526b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
3527b0563631STom Van Eyck     }
3528b0563631STom Van Eyck 
3529b0563631STom Van Eyck     status = psa_sign_verify_check_alg(0, alg);
3530b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3531b0563631STom Van Eyck         operation->error_occurred = 1;
3532b0563631STom Van Eyck         return status;
3533b0563631STom Van Eyck     }
3534b0563631STom Van Eyck 
3535b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot,
3536b0563631STom Van Eyck                                                    PSA_KEY_USAGE_SIGN_HASH,
3537b0563631STom Van Eyck                                                    alg);
3538b0563631STom Van Eyck 
3539b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3540b0563631STom Van Eyck         goto exit;
3541b0563631STom Van Eyck     }
3542b0563631STom Van Eyck 
3543b0563631STom Van Eyck     if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
3544b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
3545b0563631STom Van Eyck         goto exit;
3546b0563631STom Van Eyck     }
3547b0563631STom Van Eyck 
3548b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
3549b0563631STom Van Eyck 
3550b0563631STom Van Eyck     /* Ensure ops count gets reset, in case of operation re-use. */
3551b0563631STom Van Eyck     operation->num_ops = 0;
3552b0563631STom Van Eyck 
3553b0563631STom Van Eyck     status = psa_driver_wrapper_sign_hash_start(operation, &slot->attr,
3554b0563631STom Van Eyck                                                 slot->key.data,
3555b0563631STom Van Eyck                                                 slot->key.bytes, alg,
3556b0563631STom Van Eyck                                                 hash, hash_length);
3557b0563631STom Van Eyck exit:
3558b0563631STom Van Eyck 
3559b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3560b0563631STom Van Eyck         operation->error_occurred = 1;
3561b0563631STom Van Eyck         psa_sign_hash_abort_internal(operation);
3562b0563631STom Van Eyck     }
3563b0563631STom Van Eyck 
3564b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
3565b0563631STom Van Eyck 
3566b0563631STom Van Eyck     if (unlock_status != PSA_SUCCESS) {
3567b0563631STom Van Eyck         operation->error_occurred = 1;
3568b0563631STom Van Eyck     }
3569b0563631STom Van Eyck 
3570b0563631STom Van Eyck     LOCAL_INPUT_FREE(hash_external, hash);
3571b0563631STom Van Eyck 
3572b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
3573b0563631STom Van Eyck }
3574b0563631STom Van Eyck 
3575b0563631STom Van Eyck 
3576b0563631STom Van Eyck psa_status_t psa_sign_hash_complete(
3577b0563631STom Van Eyck     psa_sign_hash_interruptible_operation_t *operation,
3578b0563631STom Van Eyck     uint8_t *signature_external, size_t signature_size,
3579b0563631STom Van Eyck     size_t *signature_length)
3580b0563631STom Van Eyck {
3581b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3582b0563631STom Van Eyck 
3583b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(signature_external, signature);
3584b0563631STom Van Eyck 
3585b0563631STom Van Eyck     *signature_length = 0;
3586b0563631STom Van Eyck 
3587b0563631STom Van Eyck     /* Check that start has been called first, and that operation has not
3588b0563631STom Van Eyck      * previously errored. */
3589b0563631STom Van Eyck     if (operation->id == 0 || operation->error_occurred) {
3590b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
3591b0563631STom Van Eyck         goto exit;
3592b0563631STom Van Eyck     }
3593b0563631STom Van Eyck 
3594b0563631STom Van Eyck     /* Immediately reject a zero-length signature buffer. This guarantees that
3595b0563631STom Van Eyck      * signature must be a valid pointer. */
3596b0563631STom Van Eyck     if (signature_size == 0) {
3597b0563631STom Van Eyck         status = PSA_ERROR_BUFFER_TOO_SMALL;
3598b0563631STom Van Eyck         goto exit;
3599b0563631STom Van Eyck     }
3600b0563631STom Van Eyck 
3601b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
3602b0563631STom Van Eyck 
3603b0563631STom Van Eyck     status = psa_driver_wrapper_sign_hash_complete(operation, signature,
3604b0563631STom Van Eyck                                                    signature_size,
3605b0563631STom Van Eyck                                                    signature_length);
3606b0563631STom Van Eyck 
3607b0563631STom Van Eyck     /* Update ops count with work done. */
3608b0563631STom Van Eyck     operation->num_ops = psa_driver_wrapper_sign_hash_get_num_ops(operation);
3609b0563631STom Van Eyck 
3610b0563631STom Van Eyck exit:
3611b0563631STom Van Eyck 
3612b0563631STom Van Eyck     if (signature != NULL) {
3613b0563631STom Van Eyck         psa_wipe_tag_output_buffer(signature, status, signature_size,
3614b0563631STom Van Eyck                                    *signature_length);
3615b0563631STom Van Eyck     }
3616b0563631STom Van Eyck 
3617b0563631STom Van Eyck     if (status != PSA_OPERATION_INCOMPLETE) {
3618b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
3619b0563631STom Van Eyck             operation->error_occurred = 1;
3620b0563631STom Van Eyck         }
3621b0563631STom Van Eyck 
3622b0563631STom Van Eyck         psa_sign_hash_abort_internal(operation);
3623b0563631STom Van Eyck     }
3624b0563631STom Van Eyck 
3625b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(signature_external, signature);
3626b0563631STom Van Eyck 
3627b0563631STom Van Eyck     return status;
3628b0563631STom Van Eyck }
3629b0563631STom Van Eyck 
3630b0563631STom Van Eyck psa_status_t psa_sign_hash_abort(
3631b0563631STom Van Eyck     psa_sign_hash_interruptible_operation_t *operation)
3632b0563631STom Van Eyck {
3633b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3634b0563631STom Van Eyck 
3635b0563631STom Van Eyck     status = psa_sign_hash_abort_internal(operation);
3636b0563631STom Van Eyck 
3637b0563631STom Van Eyck     /* We clear the number of ops done here, so that it is not cleared when
3638b0563631STom Van Eyck      * the operation fails or succeeds, only on manual abort. */
3639b0563631STom Van Eyck     operation->num_ops = 0;
3640b0563631STom Van Eyck 
3641b0563631STom Van Eyck     /* Likewise, failure state. */
3642b0563631STom Van Eyck     operation->error_occurred = 0;
3643b0563631STom Van Eyck 
3644b0563631STom Van Eyck     return status;
3645b0563631STom Van Eyck }
3646b0563631STom Van Eyck 
3647b0563631STom Van Eyck static psa_status_t psa_verify_hash_abort_internal(
3648b0563631STom Van Eyck     psa_verify_hash_interruptible_operation_t *operation)
3649b0563631STom Van Eyck {
3650b0563631STom Van Eyck     if (operation->id == 0) {
3651b0563631STom Van Eyck         /* The object has (apparently) been initialized but it is not (yet)
3652b0563631STom Van Eyck          * in use. It's ok to call abort on such an object, and there's
3653b0563631STom Van Eyck          * nothing to do. */
3654b0563631STom Van Eyck         return PSA_SUCCESS;
3655b0563631STom Van Eyck     }
3656b0563631STom Van Eyck 
3657b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3658b0563631STom Van Eyck 
3659b0563631STom Van Eyck     status = psa_driver_wrapper_verify_hash_abort(operation);
3660b0563631STom Van Eyck 
3661b0563631STom Van Eyck     operation->id = 0;
3662b0563631STom Van Eyck 
3663b0563631STom Van Eyck     /* Do not clear either the error_occurred or num_ops elements here as they
3664b0563631STom Van Eyck      * only want to be cleared by the application calling abort, not by abort
3665b0563631STom Van Eyck      * being called at completion of an operation. */
3666b0563631STom Van Eyck 
3667b0563631STom Van Eyck     return status;
3668b0563631STom Van Eyck }
3669b0563631STom Van Eyck 
3670b0563631STom Van Eyck psa_status_t psa_verify_hash_start(
3671b0563631STom Van Eyck     psa_verify_hash_interruptible_operation_t *operation,
3672b0563631STom Van Eyck     mbedtls_svc_key_id_t key, psa_algorithm_t alg,
3673b0563631STom Van Eyck     const uint8_t *hash_external, size_t hash_length,
3674b0563631STom Van Eyck     const uint8_t *signature_external, size_t signature_length)
3675b0563631STom Van Eyck {
3676b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3677b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
3678b0563631STom Van Eyck     psa_key_slot_t *slot;
3679b0563631STom Van Eyck 
3680b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(hash_external, hash);
3681b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(signature_external, signature);
3682b0563631STom Van Eyck 
3683b0563631STom Van Eyck     /* Check that start has not been previously called, or operation has not
3684b0563631STom Van Eyck      * previously errored. */
3685b0563631STom Van Eyck     if (operation->id != 0 || operation->error_occurred) {
3686b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
3687b0563631STom Van Eyck     }
3688b0563631STom Van Eyck 
3689b0563631STom Van Eyck     status = psa_sign_verify_check_alg(0, alg);
3690b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3691b0563631STom Van Eyck         operation->error_occurred = 1;
3692b0563631STom Van Eyck         return status;
3693b0563631STom Van Eyck     }
3694b0563631STom Van Eyck 
3695b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot,
3696b0563631STom Van Eyck                                                    PSA_KEY_USAGE_VERIFY_HASH,
3697b0563631STom Van Eyck                                                    alg);
3698b0563631STom Van Eyck 
3699b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3700b0563631STom Van Eyck         operation->error_occurred = 1;
3701b0563631STom Van Eyck         return status;
3702b0563631STom Van Eyck     }
3703b0563631STom Van Eyck 
3704b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
3705b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
3706b0563631STom Van Eyck 
3707b0563631STom Van Eyck     /* Ensure ops count gets reset, in case of operation re-use. */
3708b0563631STom Van Eyck     operation->num_ops = 0;
3709b0563631STom Van Eyck 
3710b0563631STom Van Eyck     status = psa_driver_wrapper_verify_hash_start(operation, &slot->attr,
3711b0563631STom Van Eyck                                                   slot->key.data,
3712b0563631STom Van Eyck                                                   slot->key.bytes,
3713b0563631STom Van Eyck                                                   alg, hash, hash_length,
3714b0563631STom Van Eyck                                                   signature, signature_length);
3715b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
3716b0563631STom Van Eyck exit:
3717b0563631STom Van Eyck #endif
3718b0563631STom Van Eyck 
3719b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3720b0563631STom Van Eyck         operation->error_occurred = 1;
3721b0563631STom Van Eyck         psa_verify_hash_abort_internal(operation);
3722b0563631STom Van Eyck     }
3723b0563631STom Van Eyck 
3724b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
3725b0563631STom Van Eyck 
3726b0563631STom Van Eyck     if (unlock_status != PSA_SUCCESS) {
3727b0563631STom Van Eyck         operation->error_occurred = 1;
3728b0563631STom Van Eyck     }
3729b0563631STom Van Eyck 
3730b0563631STom Van Eyck     LOCAL_INPUT_FREE(hash_external, hash);
3731b0563631STom Van Eyck     LOCAL_INPUT_FREE(signature_external, signature);
3732b0563631STom Van Eyck 
3733b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
3734b0563631STom Van Eyck }
3735b0563631STom Van Eyck 
3736b0563631STom Van Eyck psa_status_t psa_verify_hash_complete(
3737b0563631STom Van Eyck     psa_verify_hash_interruptible_operation_t *operation)
3738b0563631STom Van Eyck {
3739b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3740b0563631STom Van Eyck 
3741b0563631STom Van Eyck     /* Check that start has been called first, and that operation has not
3742b0563631STom Van Eyck      * previously errored. */
3743b0563631STom Van Eyck     if (operation->id == 0 || operation->error_occurred) {
3744b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
3745b0563631STom Van Eyck         goto exit;
3746b0563631STom Van Eyck     }
3747b0563631STom Van Eyck 
3748b0563631STom Van Eyck     status = psa_driver_wrapper_verify_hash_complete(operation);
3749b0563631STom Van Eyck 
3750b0563631STom Van Eyck     /* Update ops count with work done. */
3751b0563631STom Van Eyck     operation->num_ops = psa_driver_wrapper_verify_hash_get_num_ops(
3752b0563631STom Van Eyck         operation);
3753b0563631STom Van Eyck 
3754b0563631STom Van Eyck exit:
3755b0563631STom Van Eyck 
3756b0563631STom Van Eyck     if (status != PSA_OPERATION_INCOMPLETE) {
3757b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
3758b0563631STom Van Eyck             operation->error_occurred = 1;
3759b0563631STom Van Eyck         }
3760b0563631STom Van Eyck 
3761b0563631STom Van Eyck         psa_verify_hash_abort_internal(operation);
3762b0563631STom Van Eyck     }
3763b0563631STom Van Eyck 
3764b0563631STom Van Eyck     return status;
3765b0563631STom Van Eyck }
3766b0563631STom Van Eyck 
3767b0563631STom Van Eyck psa_status_t psa_verify_hash_abort(
3768b0563631STom Van Eyck     psa_verify_hash_interruptible_operation_t *operation)
3769b0563631STom Van Eyck {
3770b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3771b0563631STom Van Eyck 
3772b0563631STom Van Eyck     status = psa_verify_hash_abort_internal(operation);
3773b0563631STom Van Eyck 
3774b0563631STom Van Eyck     /* We clear the number of ops done here, so that it is not cleared when
3775b0563631STom Van Eyck      * the operation fails or succeeds, only on manual abort. */
3776b0563631STom Van Eyck     operation->num_ops = 0;
3777b0563631STom Van Eyck 
3778b0563631STom Van Eyck     /* Likewise, failure state. */
3779b0563631STom Van Eyck     operation->error_occurred = 0;
3780b0563631STom Van Eyck 
3781b0563631STom Van Eyck     return status;
3782b0563631STom Van Eyck }
3783b0563631STom Van Eyck 
3784b0563631STom Van Eyck /****************************************************************/
3785b0563631STom Van Eyck /* Asymmetric interruptible cryptography internal               */
3786b0563631STom Van Eyck /* implementations                                              */
3787b0563631STom Van Eyck /****************************************************************/
3788b0563631STom Van Eyck 
3789b0563631STom Van Eyck void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops)
3790b0563631STom Van Eyck {
3791b0563631STom Van Eyck 
3792b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
3793b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
3794b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
3795b0563631STom Van Eyck 
3796b0563631STom Van Eyck     /* Internal implementation uses zero to indicate infinite number max ops,
3797b0563631STom Van Eyck      * therefore avoid this value, and set to minimum possible. */
3798b0563631STom Van Eyck     if (max_ops == 0) {
3799b0563631STom Van Eyck         max_ops = 1;
3800b0563631STom Van Eyck     }
3801b0563631STom Van Eyck 
3802b0563631STom Van Eyck     mbedtls_ecp_set_max_ops(max_ops);
3803b0563631STom Van Eyck #else
3804b0563631STom Van Eyck     (void) max_ops;
3805b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
3806b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
3807b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
3808b0563631STom Van Eyck }
3809b0563631STom Van Eyck 
3810b0563631STom Van Eyck uint32_t mbedtls_psa_sign_hash_get_num_ops(
3811b0563631STom Van Eyck     const mbedtls_psa_sign_hash_interruptible_operation_t *operation)
3812b0563631STom Van Eyck {
3813b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
3814b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
3815b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
3816b0563631STom Van Eyck 
3817b0563631STom Van Eyck     return operation->num_ops;
3818b0563631STom Van Eyck #else
3819b0563631STom Van Eyck     (void) operation;
3820b0563631STom Van Eyck     return 0;
3821b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
3822b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
3823b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
3824b0563631STom Van Eyck }
3825b0563631STom Van Eyck 
3826b0563631STom Van Eyck uint32_t mbedtls_psa_verify_hash_get_num_ops(
3827b0563631STom Van Eyck     const mbedtls_psa_verify_hash_interruptible_operation_t *operation)
3828b0563631STom Van Eyck {
3829b0563631STom Van Eyck     #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
3830b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
3831b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
3832b0563631STom Van Eyck 
3833b0563631STom Van Eyck     return operation->num_ops;
3834b0563631STom Van Eyck #else
3835b0563631STom Van Eyck     (void) operation;
3836b0563631STom Van Eyck     return 0;
3837b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
3838b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
3839b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
3840b0563631STom Van Eyck }
3841b0563631STom Van Eyck 
3842b0563631STom Van Eyck psa_status_t mbedtls_psa_sign_hash_start(
3843b0563631STom Van Eyck     mbedtls_psa_sign_hash_interruptible_operation_t *operation,
3844b0563631STom Van Eyck     const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
3845b0563631STom Van Eyck     size_t key_buffer_size, psa_algorithm_t alg,
3846b0563631STom Van Eyck     const uint8_t *hash, size_t hash_length)
3847b0563631STom Van Eyck {
3848b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3849b0563631STom Van Eyck     size_t required_hash_length;
3850b0563631STom Van Eyck 
3851b0563631STom Van Eyck     if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) {
3852b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
3853b0563631STom Van Eyck     }
3854b0563631STom Van Eyck 
3855b0563631STom Van Eyck     if (!PSA_ALG_IS_ECDSA(alg)) {
3856b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
3857b0563631STom Van Eyck     }
3858b0563631STom Van Eyck 
3859b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
3860b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
3861b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
3862b0563631STom Van Eyck 
3863b0563631STom Van Eyck     mbedtls_ecdsa_restart_init(&operation->restart_ctx);
3864b0563631STom Van Eyck 
3865b0563631STom Van Eyck     /* Ensure num_ops is zero'ed in case of context re-use. */
3866b0563631STom Van Eyck     operation->num_ops = 0;
3867b0563631STom Van Eyck 
3868b0563631STom Van Eyck     status = mbedtls_psa_ecp_load_representation(attributes->type,
3869b0563631STom Van Eyck                                                  attributes->bits,
3870b0563631STom Van Eyck                                                  key_buffer,
3871b0563631STom Van Eyck                                                  key_buffer_size,
3872b0563631STom Van Eyck                                                  &operation->ctx);
3873b0563631STom Van Eyck 
3874b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
3875b0563631STom Van Eyck         return status;
3876b0563631STom Van Eyck     }
3877b0563631STom Van Eyck 
3878b0563631STom Van Eyck     operation->coordinate_bytes = PSA_BITS_TO_BYTES(
3879b0563631STom Van Eyck         operation->ctx->grp.nbits);
3880b0563631STom Van Eyck 
3881b0563631STom Van Eyck     psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
3882b0563631STom Van Eyck     operation->md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
3883b0563631STom Van Eyck     operation->alg = alg;
3884b0563631STom Van Eyck 
3885b0563631STom Van Eyck     /* We only need to store the same length of hash as the private key size
3886b0563631STom Van Eyck      * here, it would be truncated by the internal implementation anyway. */
3887b0563631STom Van Eyck     required_hash_length = (hash_length < operation->coordinate_bytes ?
3888b0563631STom Van Eyck                             hash_length : operation->coordinate_bytes);
3889b0563631STom Van Eyck 
3890b0563631STom Van Eyck     if (required_hash_length > sizeof(operation->hash)) {
3891b0563631STom Van Eyck         /* Shouldn't happen, but better safe than sorry. */
3892b0563631STom Van Eyck         return PSA_ERROR_CORRUPTION_DETECTED;
3893b0563631STom Van Eyck     }
3894b0563631STom Van Eyck 
3895b0563631STom Van Eyck     memcpy(operation->hash, hash, required_hash_length);
3896b0563631STom Van Eyck     operation->hash_length = required_hash_length;
3897b0563631STom Van Eyck 
3898b0563631STom Van Eyck     return PSA_SUCCESS;
3899b0563631STom Van Eyck 
3900b0563631STom Van Eyck #else
3901b0563631STom Van Eyck     (void) operation;
3902b0563631STom Van Eyck     (void) key_buffer;
3903b0563631STom Van Eyck     (void) key_buffer_size;
3904b0563631STom Van Eyck     (void) alg;
3905b0563631STom Van Eyck     (void) hash;
3906b0563631STom Van Eyck     (void) hash_length;
3907b0563631STom Van Eyck     (void) status;
3908b0563631STom Van Eyck     (void) required_hash_length;
3909b0563631STom Van Eyck 
3910b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
3911b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
3912b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
3913b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
3914b0563631STom Van Eyck }
3915b0563631STom Van Eyck 
3916b0563631STom Van Eyck psa_status_t mbedtls_psa_sign_hash_complete(
3917b0563631STom Van Eyck     mbedtls_psa_sign_hash_interruptible_operation_t *operation,
3918b0563631STom Van Eyck     uint8_t *signature, size_t signature_size,
3919b0563631STom Van Eyck     size_t *signature_length)
3920b0563631STom Van Eyck {
3921b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
3922b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
3923b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
3924b0563631STom Van Eyck 
3925b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
3926b0563631STom Van Eyck     mbedtls_mpi r;
3927b0563631STom Van Eyck     mbedtls_mpi s;
3928b0563631STom Van Eyck 
3929b0563631STom Van Eyck     mbedtls_mpi_init(&r);
3930b0563631STom Van Eyck     mbedtls_mpi_init(&s);
3931b0563631STom Van Eyck 
3932b0563631STom Van Eyck     /* Ensure max_ops is set to the current value (or default). */
3933b0563631STom Van Eyck     mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops());
3934b0563631STom Van Eyck 
3935b0563631STom Van Eyck     if (signature_size < 2 * operation->coordinate_bytes) {
3936b0563631STom Van Eyck         status = PSA_ERROR_BUFFER_TOO_SMALL;
3937b0563631STom Van Eyck         goto exit;
3938b0563631STom Van Eyck     }
3939b0563631STom Van Eyck 
3940b0563631STom Van Eyck     if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) {
3941b0563631STom Van Eyck 
3942b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
3943b0563631STom Van Eyck         status = mbedtls_to_psa_error(
3944b0563631STom Van Eyck             mbedtls_ecdsa_sign_det_restartable(&operation->ctx->grp,
3945b0563631STom Van Eyck                                                &r,
3946b0563631STom Van Eyck                                                &s,
3947b0563631STom Van Eyck                                                &operation->ctx->d,
3948b0563631STom Van Eyck                                                operation->hash,
3949b0563631STom Van Eyck                                                operation->hash_length,
3950b0563631STom Van Eyck                                                operation->md_alg,
3951b0563631STom Van Eyck                                                mbedtls_psa_get_random,
3952b0563631STom Van Eyck                                                MBEDTLS_PSA_RANDOM_STATE,
3953b0563631STom Van Eyck                                                &operation->restart_ctx));
3954b0563631STom Van Eyck #else /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
3955b0563631STom Van Eyck         status = PSA_ERROR_NOT_SUPPORTED;
3956b0563631STom Van Eyck         goto exit;
3957b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
3958b0563631STom Van Eyck     } else {
3959b0563631STom Van Eyck         status = mbedtls_to_psa_error(
3960b0563631STom Van Eyck             mbedtls_ecdsa_sign_restartable(&operation->ctx->grp,
3961b0563631STom Van Eyck                                            &r,
3962b0563631STom Van Eyck                                            &s,
3963b0563631STom Van Eyck                                            &operation->ctx->d,
3964b0563631STom Van Eyck                                            operation->hash,
3965b0563631STom Van Eyck                                            operation->hash_length,
3966b0563631STom Van Eyck                                            mbedtls_psa_get_random,
3967b0563631STom Van Eyck                                            MBEDTLS_PSA_RANDOM_STATE,
3968b0563631STom Van Eyck                                            mbedtls_psa_get_random,
3969b0563631STom Van Eyck                                            MBEDTLS_PSA_RANDOM_STATE,
3970b0563631STom Van Eyck                                            &operation->restart_ctx));
3971b0563631STom Van Eyck     }
3972b0563631STom Van Eyck 
3973b0563631STom Van Eyck     /* Hide the fact that the restart context only holds a delta of number of
3974b0563631STom Van Eyck      * ops done during the last operation, not an absolute value. */
3975b0563631STom Van Eyck     operation->num_ops += operation->restart_ctx.ecp.ops_done;
3976b0563631STom Van Eyck 
3977b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
3978b0563631STom Van Eyck         status =  mbedtls_to_psa_error(
3979b0563631STom Van Eyck             mbedtls_mpi_write_binary(&r,
3980b0563631STom Van Eyck                                      signature,
3981b0563631STom Van Eyck                                      operation->coordinate_bytes)
3982b0563631STom Van Eyck             );
3983b0563631STom Van Eyck 
3984b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
3985b0563631STom Van Eyck             goto exit;
3986b0563631STom Van Eyck         }
3987b0563631STom Van Eyck 
3988b0563631STom Van Eyck         status =  mbedtls_to_psa_error(
3989b0563631STom Van Eyck             mbedtls_mpi_write_binary(&s,
3990b0563631STom Van Eyck                                      signature +
3991b0563631STom Van Eyck                                      operation->coordinate_bytes,
3992b0563631STom Van Eyck                                      operation->coordinate_bytes)
3993b0563631STom Van Eyck             );
3994b0563631STom Van Eyck 
3995b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
3996b0563631STom Van Eyck             goto exit;
3997b0563631STom Van Eyck         }
3998b0563631STom Van Eyck 
3999b0563631STom Van Eyck         *signature_length = operation->coordinate_bytes * 2;
4000b0563631STom Van Eyck 
4001b0563631STom Van Eyck         status = PSA_SUCCESS;
4002b0563631STom Van Eyck     }
4003b0563631STom Van Eyck 
4004b0563631STom Van Eyck exit:
4005b0563631STom Van Eyck 
4006b0563631STom Van Eyck     mbedtls_mpi_free(&r);
4007b0563631STom Van Eyck     mbedtls_mpi_free(&s);
4008b0563631STom Van Eyck     return status;
4009b0563631STom Van Eyck 
4010b0563631STom Van Eyck  #else
4011b0563631STom Van Eyck 
4012b0563631STom Van Eyck     (void) operation;
4013b0563631STom Van Eyck     (void) signature;
4014b0563631STom Van Eyck     (void) signature_size;
4015b0563631STom Van Eyck     (void) signature_length;
4016b0563631STom Van Eyck 
4017b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
4018b0563631STom Van Eyck 
4019b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
4020b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
4021b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
4022b0563631STom Van Eyck }
4023b0563631STom Van Eyck 
4024b0563631STom Van Eyck psa_status_t mbedtls_psa_sign_hash_abort(
4025b0563631STom Van Eyck     mbedtls_psa_sign_hash_interruptible_operation_t *operation)
4026b0563631STom Van Eyck {
4027b0563631STom Van Eyck 
4028b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
4029b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
4030b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
4031b0563631STom Van Eyck 
4032b0563631STom Van Eyck     if (operation->ctx) {
4033b0563631STom Van Eyck         mbedtls_ecdsa_free(operation->ctx);
4034b0563631STom Van Eyck         mbedtls_free(operation->ctx);
4035b0563631STom Van Eyck         operation->ctx = NULL;
4036b0563631STom Van Eyck     }
4037b0563631STom Van Eyck 
4038b0563631STom Van Eyck     mbedtls_ecdsa_restart_free(&operation->restart_ctx);
4039b0563631STom Van Eyck 
4040b0563631STom Van Eyck     operation->num_ops = 0;
4041b0563631STom Van Eyck 
4042b0563631STom Van Eyck     return PSA_SUCCESS;
4043b0563631STom Van Eyck 
4044b0563631STom Van Eyck #else
4045b0563631STom Van Eyck 
4046b0563631STom Van Eyck     (void) operation;
4047b0563631STom Van Eyck 
4048b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
4049b0563631STom Van Eyck 
4050b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
4051b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
4052b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
4053b0563631STom Van Eyck }
4054b0563631STom Van Eyck 
4055b0563631STom Van Eyck psa_status_t mbedtls_psa_verify_hash_start(
4056b0563631STom Van Eyck     mbedtls_psa_verify_hash_interruptible_operation_t *operation,
4057b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
4058b0563631STom Van Eyck     const uint8_t *key_buffer, size_t key_buffer_size,
4059b0563631STom Van Eyck     psa_algorithm_t alg,
4060b0563631STom Van Eyck     const uint8_t *hash, size_t hash_length,
4061b0563631STom Van Eyck     const uint8_t *signature, size_t signature_length)
4062b0563631STom Van Eyck {
4063b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4064b0563631STom Van Eyck     size_t coordinate_bytes = 0;
4065b0563631STom Van Eyck     size_t required_hash_length = 0;
4066b0563631STom Van Eyck 
4067b0563631STom Van Eyck     if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) {
4068b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
4069b0563631STom Van Eyck     }
4070b0563631STom Van Eyck 
4071b0563631STom Van Eyck     if (!PSA_ALG_IS_ECDSA(alg)) {
4072b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
4073b0563631STom Van Eyck     }
4074b0563631STom Van Eyck 
4075b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
4076b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
4077b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
4078b0563631STom Van Eyck 
4079b0563631STom Van Eyck     mbedtls_ecdsa_restart_init(&operation->restart_ctx);
4080b0563631STom Van Eyck     mbedtls_mpi_init(&operation->r);
4081b0563631STom Van Eyck     mbedtls_mpi_init(&operation->s);
4082b0563631STom Van Eyck 
4083b0563631STom Van Eyck     /* Ensure num_ops is zero'ed in case of context re-use. */
4084b0563631STom Van Eyck     operation->num_ops = 0;
4085b0563631STom Van Eyck 
4086b0563631STom Van Eyck     status = mbedtls_psa_ecp_load_representation(attributes->type,
4087b0563631STom Van Eyck                                                  attributes->bits,
4088b0563631STom Van Eyck                                                  key_buffer,
4089b0563631STom Van Eyck                                                  key_buffer_size,
4090b0563631STom Van Eyck                                                  &operation->ctx);
4091b0563631STom Van Eyck 
4092b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4093b0563631STom Van Eyck         return status;
4094b0563631STom Van Eyck     }
4095b0563631STom Van Eyck 
4096b0563631STom Van Eyck     coordinate_bytes = PSA_BITS_TO_BYTES(operation->ctx->grp.nbits);
4097b0563631STom Van Eyck 
4098b0563631STom Van Eyck     if (signature_length != 2 * coordinate_bytes) {
4099b0563631STom Van Eyck         return PSA_ERROR_INVALID_SIGNATURE;
4100b0563631STom Van Eyck     }
4101b0563631STom Van Eyck 
4102b0563631STom Van Eyck     status = mbedtls_to_psa_error(
4103b0563631STom Van Eyck         mbedtls_mpi_read_binary(&operation->r,
4104b0563631STom Van Eyck                                 signature,
4105b0563631STom Van Eyck                                 coordinate_bytes));
4106b0563631STom Van Eyck 
4107b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4108b0563631STom Van Eyck         return status;
4109b0563631STom Van Eyck     }
4110b0563631STom Van Eyck 
4111b0563631STom Van Eyck     status = mbedtls_to_psa_error(
4112b0563631STom Van Eyck         mbedtls_mpi_read_binary(&operation->s,
4113b0563631STom Van Eyck                                 signature +
4114b0563631STom Van Eyck                                 coordinate_bytes,
4115b0563631STom Van Eyck                                 coordinate_bytes));
4116b0563631STom Van Eyck 
4117b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4118b0563631STom Van Eyck         return status;
4119b0563631STom Van Eyck     }
4120b0563631STom Van Eyck 
4121b0563631STom Van Eyck     status = mbedtls_psa_ecp_load_public_part(operation->ctx);
4122b0563631STom Van Eyck 
4123b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4124b0563631STom Van Eyck         return status;
4125b0563631STom Van Eyck     }
4126b0563631STom Van Eyck 
4127b0563631STom Van Eyck     /* We only need to store the same length of hash as the private key size
4128b0563631STom Van Eyck      * here, it would be truncated by the internal implementation anyway. */
4129b0563631STom Van Eyck     required_hash_length = (hash_length < coordinate_bytes ? hash_length :
4130b0563631STom Van Eyck                             coordinate_bytes);
4131b0563631STom Van Eyck 
4132b0563631STom Van Eyck     if (required_hash_length > sizeof(operation->hash)) {
4133b0563631STom Van Eyck         /* Shouldn't happen, but better safe than sorry. */
4134b0563631STom Van Eyck         return PSA_ERROR_CORRUPTION_DETECTED;
4135b0563631STom Van Eyck     }
4136b0563631STom Van Eyck 
4137b0563631STom Van Eyck     memcpy(operation->hash, hash, required_hash_length);
4138b0563631STom Van Eyck     operation->hash_length = required_hash_length;
4139b0563631STom Van Eyck 
4140b0563631STom Van Eyck     return PSA_SUCCESS;
4141b0563631STom Van Eyck #else
4142b0563631STom Van Eyck     (void) operation;
4143b0563631STom Van Eyck     (void) key_buffer;
4144b0563631STom Van Eyck     (void) key_buffer_size;
4145b0563631STom Van Eyck     (void) alg;
4146b0563631STom Van Eyck     (void) hash;
4147b0563631STom Van Eyck     (void) hash_length;
4148b0563631STom Van Eyck     (void) signature;
4149b0563631STom Van Eyck     (void) signature_length;
4150b0563631STom Van Eyck     (void) status;
4151b0563631STom Van Eyck     (void) coordinate_bytes;
4152b0563631STom Van Eyck     (void) required_hash_length;
4153b0563631STom Van Eyck 
4154b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
4155b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
4156b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
4157b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
4158b0563631STom Van Eyck }
4159b0563631STom Van Eyck 
4160b0563631STom Van Eyck psa_status_t mbedtls_psa_verify_hash_complete(
4161b0563631STom Van Eyck     mbedtls_psa_verify_hash_interruptible_operation_t *operation)
4162b0563631STom Van Eyck {
4163b0563631STom Van Eyck 
4164b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
4165b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
4166b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
4167b0563631STom Van Eyck 
4168b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4169b0563631STom Van Eyck 
4170b0563631STom Van Eyck     /* Ensure max_ops is set to the current value (or default). */
4171b0563631STom Van Eyck     mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops());
4172b0563631STom Van Eyck 
4173b0563631STom Van Eyck     status = mbedtls_to_psa_error(
4174b0563631STom Van Eyck         mbedtls_ecdsa_verify_restartable(&operation->ctx->grp,
4175b0563631STom Van Eyck                                          operation->hash,
4176b0563631STom Van Eyck                                          operation->hash_length,
4177b0563631STom Van Eyck                                          &operation->ctx->Q,
4178b0563631STom Van Eyck                                          &operation->r,
4179b0563631STom Van Eyck                                          &operation->s,
4180b0563631STom Van Eyck                                          &operation->restart_ctx));
4181b0563631STom Van Eyck 
4182b0563631STom Van Eyck     /* Hide the fact that the restart context only holds a delta of number of
4183b0563631STom Van Eyck      * ops done during the last operation, not an absolute value. */
4184b0563631STom Van Eyck     operation->num_ops += operation->restart_ctx.ecp.ops_done;
4185b0563631STom Van Eyck 
4186b0563631STom Van Eyck     return status;
4187b0563631STom Van Eyck #else
4188b0563631STom Van Eyck     (void) operation;
4189b0563631STom Van Eyck 
4190b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
4191b0563631STom Van Eyck 
4192b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
4193b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
4194b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
4195b0563631STom Van Eyck }
4196b0563631STom Van Eyck 
4197b0563631STom Van Eyck psa_status_t mbedtls_psa_verify_hash_abort(
4198b0563631STom Van Eyck     mbedtls_psa_verify_hash_interruptible_operation_t *operation)
4199b0563631STom Van Eyck {
4200b0563631STom Van Eyck 
4201b0563631STom Van Eyck #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
4202b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
4203b0563631STom Van Eyck     defined(MBEDTLS_ECP_RESTARTABLE)
4204b0563631STom Van Eyck 
4205b0563631STom Van Eyck     if (operation->ctx) {
4206b0563631STom Van Eyck         mbedtls_ecdsa_free(operation->ctx);
4207b0563631STom Van Eyck         mbedtls_free(operation->ctx);
4208b0563631STom Van Eyck         operation->ctx = NULL;
4209b0563631STom Van Eyck     }
4210b0563631STom Van Eyck 
4211b0563631STom Van Eyck     mbedtls_ecdsa_restart_free(&operation->restart_ctx);
4212b0563631STom Van Eyck 
4213b0563631STom Van Eyck     operation->num_ops = 0;
4214b0563631STom Van Eyck 
4215b0563631STom Van Eyck     mbedtls_mpi_free(&operation->r);
4216b0563631STom Van Eyck     mbedtls_mpi_free(&operation->s);
4217b0563631STom Van Eyck 
4218b0563631STom Van Eyck     return PSA_SUCCESS;
4219b0563631STom Van Eyck 
4220b0563631STom Van Eyck #else
4221b0563631STom Van Eyck     (void) operation;
4222b0563631STom Van Eyck 
4223b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
4224b0563631STom Van Eyck 
4225b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
4226b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
4227b0563631STom Van Eyck         * defined( MBEDTLS_ECP_RESTARTABLE ) */
4228b0563631STom Van Eyck }
4229b0563631STom Van Eyck 
4230b0563631STom Van Eyck static psa_status_t psa_generate_random_internal(uint8_t *output,
4231b0563631STom Van Eyck                                                  size_t output_size)
4232b0563631STom Van Eyck {
4233b0563631STom Van Eyck     GUARD_MODULE_INITIALIZED;
4234b0563631STom Van Eyck 
4235b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
4236b0563631STom Van Eyck 
4237b0563631STom Van Eyck     psa_status_t status;
4238b0563631STom Van Eyck     size_t output_length = 0;
4239b0563631STom Van Eyck     status = mbedtls_psa_external_get_random(&global_data.rng,
4240b0563631STom Van Eyck                                              output, output_size,
4241b0563631STom Van Eyck                                              &output_length);
4242b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4243b0563631STom Van Eyck         return status;
4244b0563631STom Van Eyck     }
4245b0563631STom Van Eyck     /* Breaking up a request into smaller chunks is currently not supported
4246b0563631STom Van Eyck      * for the external RNG interface. */
4247b0563631STom Van Eyck     if (output_length != output_size) {
4248b0563631STom Van Eyck         return PSA_ERROR_INSUFFICIENT_ENTROPY;
4249b0563631STom Van Eyck     }
4250b0563631STom Van Eyck     return PSA_SUCCESS;
4251b0563631STom Van Eyck 
4252b0563631STom Van Eyck #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
4253b0563631STom Van Eyck 
4254b0563631STom Van Eyck     while (output_size > 0) {
4255b0563631STom Van Eyck         int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
4256b0563631STom Van Eyck         size_t request_size =
4257b0563631STom Van Eyck             (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?
4258b0563631STom Van Eyck              MBEDTLS_PSA_RANDOM_MAX_REQUEST :
4259b0563631STom Van Eyck              output_size);
4260b0563631STom Van Eyck #if defined(MBEDTLS_CTR_DRBG_C)
4261b0563631STom Van Eyck         ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size);
4262b0563631STom Van Eyck #elif defined(MBEDTLS_HMAC_DRBG_C)
4263b0563631STom Van Eyck         ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size);
4264b0563631STom Van Eyck #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
4265b0563631STom Van Eyck         if (ret != 0) {
4266b0563631STom Van Eyck             return mbedtls_to_psa_error(ret);
4267b0563631STom Van Eyck         }
4268b0563631STom Van Eyck         output_size -= request_size;
4269b0563631STom Van Eyck         output += request_size;
4270b0563631STom Van Eyck     }
4271b0563631STom Van Eyck     return PSA_SUCCESS;
4272b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
4273b0563631STom Van Eyck }
4274b0563631STom Van Eyck 
4275b0563631STom Van Eyck 
4276b0563631STom Van Eyck /****************************************************************/
4277b0563631STom Van Eyck /* Symmetric cryptography */
4278b0563631STom Van Eyck /****************************************************************/
4279b0563631STom Van Eyck 
4280b0563631STom Van Eyck static psa_status_t psa_cipher_setup(psa_cipher_operation_t *operation,
4281b0563631STom Van Eyck                                      mbedtls_svc_key_id_t key,
4282b0563631STom Van Eyck                                      psa_algorithm_t alg,
4283b0563631STom Van Eyck                                      mbedtls_operation_t cipher_operation)
4284b0563631STom Van Eyck {
4285b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4286b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
4287b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
4288b0563631STom Van Eyck     psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ?
4289b0563631STom Van Eyck                              PSA_KEY_USAGE_ENCRYPT :
4290b0563631STom Van Eyck                              PSA_KEY_USAGE_DECRYPT);
4291b0563631STom Van Eyck 
4292b0563631STom Van Eyck     /* A context must be freshly initialized before it can be set up. */
4293b0563631STom Van Eyck     if (operation->id != 0) {
4294b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4295b0563631STom Van Eyck         goto exit;
4296b0563631STom Van Eyck     }
4297b0563631STom Van Eyck 
4298b0563631STom Van Eyck     if (!PSA_ALG_IS_CIPHER(alg)) {
4299b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
4300b0563631STom Van Eyck         goto exit;
4301b0563631STom Van Eyck     }
4302b0563631STom Van Eyck 
4303b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg);
4304b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4305b0563631STom Van Eyck         goto exit;
4306b0563631STom Van Eyck     }
4307b0563631STom Van Eyck 
4308b0563631STom Van Eyck     /* Initialize the operation struct members, except for id. The id member
4309b0563631STom Van Eyck      * is used to indicate to psa_cipher_abort that there are resources to free,
4310b0563631STom Van Eyck      * so we only set it (in the driver wrapper) after resources have been
4311b0563631STom Van Eyck      * allocated/initialized. */
4312b0563631STom Van Eyck     operation->iv_set = 0;
4313b0563631STom Van Eyck     if (alg == PSA_ALG_ECB_NO_PADDING) {
4314b0563631STom Van Eyck         operation->iv_required = 0;
4315b0563631STom Van Eyck     } else {
4316b0563631STom Van Eyck         operation->iv_required = 1;
4317b0563631STom Van Eyck     }
4318b0563631STom Van Eyck     operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg);
4319b0563631STom Van Eyck 
4320b0563631STom Van Eyck     /* Try doing the operation through a driver before using software fallback. */
4321b0563631STom Van Eyck     if (cipher_operation == MBEDTLS_ENCRYPT) {
4322b0563631STom Van Eyck         status = psa_driver_wrapper_cipher_encrypt_setup(operation,
4323b0563631STom Van Eyck                                                          &slot->attr,
4324b0563631STom Van Eyck                                                          slot->key.data,
4325b0563631STom Van Eyck                                                          slot->key.bytes,
4326b0563631STom Van Eyck                                                          alg);
4327b0563631STom Van Eyck     } else {
4328b0563631STom Van Eyck         status = psa_driver_wrapper_cipher_decrypt_setup(operation,
4329b0563631STom Van Eyck                                                          &slot->attr,
4330b0563631STom Van Eyck                                                          slot->key.data,
4331b0563631STom Van Eyck                                                          slot->key.bytes,
4332b0563631STom Van Eyck                                                          alg);
4333b0563631STom Van Eyck     }
4334b0563631STom Van Eyck 
4335b0563631STom Van Eyck exit:
4336b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4337b0563631STom Van Eyck         psa_cipher_abort(operation);
4338b0563631STom Van Eyck     }
4339b0563631STom Van Eyck 
4340b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
4341b0563631STom Van Eyck 
4342b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
4343b0563631STom Van Eyck }
4344b0563631STom Van Eyck 
4345b0563631STom Van Eyck psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
4346b0563631STom Van Eyck                                       mbedtls_svc_key_id_t key,
4347b0563631STom Van Eyck                                       psa_algorithm_t alg)
4348b0563631STom Van Eyck {
4349b0563631STom Van Eyck     return psa_cipher_setup(operation, key, alg, MBEDTLS_ENCRYPT);
4350b0563631STom Van Eyck }
4351b0563631STom Van Eyck 
4352b0563631STom Van Eyck psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
4353b0563631STom Van Eyck                                       mbedtls_svc_key_id_t key,
4354b0563631STom Van Eyck                                       psa_algorithm_t alg)
4355b0563631STom Van Eyck {
4356b0563631STom Van Eyck     return psa_cipher_setup(operation, key, alg, MBEDTLS_DECRYPT);
4357b0563631STom Van Eyck }
4358b0563631STom Van Eyck 
4359b0563631STom Van Eyck psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
4360b0563631STom Van Eyck                                     uint8_t *iv_external,
4361b0563631STom Van Eyck                                     size_t iv_size,
4362b0563631STom Van Eyck                                     size_t *iv_length)
4363b0563631STom Van Eyck {
4364b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4365b0563631STom Van Eyck     size_t default_iv_length = 0;
4366b0563631STom Van Eyck 
4367b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(iv_external, iv);
4368b0563631STom Van Eyck 
4369b0563631STom Van Eyck     if (operation->id == 0) {
4370b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4371b0563631STom Van Eyck         goto exit;
4372b0563631STom Van Eyck     }
4373b0563631STom Van Eyck 
4374b0563631STom Van Eyck     if (operation->iv_set || !operation->iv_required) {
4375b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4376b0563631STom Van Eyck         goto exit;
4377b0563631STom Van Eyck     }
4378b0563631STom Van Eyck 
4379b0563631STom Van Eyck     default_iv_length = operation->default_iv_length;
4380b0563631STom Van Eyck     if (iv_size < default_iv_length) {
4381b0563631STom Van Eyck         status = PSA_ERROR_BUFFER_TOO_SMALL;
4382b0563631STom Van Eyck         goto exit;
4383b0563631STom Van Eyck     }
4384b0563631STom Van Eyck 
4385b0563631STom Van Eyck     if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) {
4386b0563631STom Van Eyck         status = PSA_ERROR_GENERIC_ERROR;
4387b0563631STom Van Eyck         goto exit;
4388b0563631STom Van Eyck     }
4389b0563631STom Van Eyck 
4390b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv);
4391b0563631STom Van Eyck 
4392b0563631STom Van Eyck     status = psa_generate_random_internal(iv, default_iv_length);
4393b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4394b0563631STom Van Eyck         goto exit;
4395b0563631STom Van Eyck     }
4396b0563631STom Van Eyck 
4397b0563631STom Van Eyck     status = psa_driver_wrapper_cipher_set_iv(operation,
4398b0563631STom Van Eyck                                               iv, default_iv_length);
4399b0563631STom Van Eyck 
4400b0563631STom Van Eyck exit:
4401b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
4402b0563631STom Van Eyck         *iv_length = default_iv_length;
4403b0563631STom Van Eyck         operation->iv_set = 1;
4404b0563631STom Van Eyck     } else {
4405b0563631STom Van Eyck         *iv_length = 0;
4406b0563631STom Van Eyck         psa_cipher_abort(operation);
4407b0563631STom Van Eyck         if (iv != NULL) {
4408b0563631STom Van Eyck             mbedtls_platform_zeroize(iv, default_iv_length);
4409b0563631STom Van Eyck         }
4410b0563631STom Van Eyck     }
4411b0563631STom Van Eyck 
4412b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(iv_external, iv);
4413b0563631STom Van Eyck     return status;
4414b0563631STom Van Eyck }
4415b0563631STom Van Eyck 
4416b0563631STom Van Eyck psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
4417b0563631STom Van Eyck                                const uint8_t *iv_external,
4418b0563631STom Van Eyck                                size_t iv_length)
4419b0563631STom Van Eyck {
4420b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4421b0563631STom Van Eyck 
4422b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(iv_external, iv);
4423b0563631STom Van Eyck 
4424b0563631STom Van Eyck     if (operation->id == 0) {
4425b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4426b0563631STom Van Eyck         goto exit;
4427b0563631STom Van Eyck     }
4428b0563631STom Van Eyck 
4429b0563631STom Van Eyck     if (operation->iv_set || !operation->iv_required) {
4430b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4431b0563631STom Van Eyck         goto exit;
4432b0563631STom Van Eyck     }
4433b0563631STom Van Eyck 
4434b0563631STom Van Eyck     if (iv_length > PSA_CIPHER_IV_MAX_SIZE) {
4435b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
4436b0563631STom Van Eyck         goto exit;
4437b0563631STom Van Eyck     }
4438b0563631STom Van Eyck 
4439b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(iv_external, iv_length, iv);
4440b0563631STom Van Eyck 
4441b0563631STom Van Eyck     status = psa_driver_wrapper_cipher_set_iv(operation,
4442b0563631STom Van Eyck                                               iv,
4443b0563631STom Van Eyck                                               iv_length);
4444b0563631STom Van Eyck 
4445b0563631STom Van Eyck exit:
4446b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
4447b0563631STom Van Eyck         operation->iv_set = 1;
4448b0563631STom Van Eyck     } else {
4449b0563631STom Van Eyck         psa_cipher_abort(operation);
4450b0563631STom Van Eyck     }
4451b0563631STom Van Eyck 
4452b0563631STom Van Eyck     LOCAL_INPUT_FREE(iv_external, iv);
4453b0563631STom Van Eyck 
4454b0563631STom Van Eyck     return status;
4455b0563631STom Van Eyck }
4456b0563631STom Van Eyck 
4457b0563631STom Van Eyck psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
4458b0563631STom Van Eyck                                const uint8_t *input_external,
4459b0563631STom Van Eyck                                size_t input_length,
4460b0563631STom Van Eyck                                uint8_t *output_external,
4461b0563631STom Van Eyck                                size_t output_size,
4462b0563631STom Van Eyck                                size_t *output_length)
4463b0563631STom Van Eyck {
4464b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4465b0563631STom Van Eyck 
4466b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
4467b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
4468b0563631STom Van Eyck 
4469b0563631STom Van Eyck     if (operation->id == 0) {
4470b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4471b0563631STom Van Eyck         goto exit;
4472b0563631STom Van Eyck     }
4473b0563631STom Van Eyck 
4474b0563631STom Van Eyck     if (operation->iv_required && !operation->iv_set) {
4475b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4476b0563631STom Van Eyck         goto exit;
4477b0563631STom Van Eyck     }
4478b0563631STom Van Eyck 
4479b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
4480b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
4481b0563631STom Van Eyck 
4482b0563631STom Van Eyck     status = psa_driver_wrapper_cipher_update(operation,
4483b0563631STom Van Eyck                                               input,
4484b0563631STom Van Eyck                                               input_length,
4485b0563631STom Van Eyck                                               output,
4486b0563631STom Van Eyck                                               output_size,
4487b0563631STom Van Eyck                                               output_length);
4488b0563631STom Van Eyck 
4489b0563631STom Van Eyck exit:
4490b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4491b0563631STom Van Eyck         psa_cipher_abort(operation);
4492b0563631STom Van Eyck     }
4493b0563631STom Van Eyck 
4494b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
4495b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
4496b0563631STom Van Eyck 
4497b0563631STom Van Eyck     return status;
4498b0563631STom Van Eyck }
4499b0563631STom Van Eyck 
4500b0563631STom Van Eyck psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
4501b0563631STom Van Eyck                                uint8_t *output_external,
4502b0563631STom Van Eyck                                size_t output_size,
4503b0563631STom Van Eyck                                size_t *output_length)
4504b0563631STom Van Eyck {
4505b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
4506b0563631STom Van Eyck 
4507b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
4508b0563631STom Van Eyck 
4509b0563631STom Van Eyck     if (operation->id == 0) {
4510b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4511b0563631STom Van Eyck         goto exit;
4512b0563631STom Van Eyck     }
4513b0563631STom Van Eyck 
4514b0563631STom Van Eyck     if (operation->iv_required && !operation->iv_set) {
4515b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4516b0563631STom Van Eyck         goto exit;
4517b0563631STom Van Eyck     }
4518b0563631STom Van Eyck 
4519b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
4520b0563631STom Van Eyck 
4521b0563631STom Van Eyck     status = psa_driver_wrapper_cipher_finish(operation,
4522b0563631STom Van Eyck                                               output,
4523b0563631STom Van Eyck                                               output_size,
4524b0563631STom Van Eyck                                               output_length);
4525b0563631STom Van Eyck 
4526b0563631STom Van Eyck exit:
4527b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
4528b0563631STom Van Eyck         status = psa_cipher_abort(operation);
4529b0563631STom Van Eyck     } else {
4530b0563631STom Van Eyck         *output_length = 0;
4531b0563631STom Van Eyck         (void) psa_cipher_abort(operation);
4532b0563631STom Van Eyck     }
4533b0563631STom Van Eyck 
4534b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
4535b0563631STom Van Eyck 
4536b0563631STom Van Eyck     return status;
4537b0563631STom Van Eyck }
4538b0563631STom Van Eyck 
4539b0563631STom Van Eyck psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
4540b0563631STom Van Eyck {
4541b0563631STom Van Eyck     if (operation->id == 0) {
4542b0563631STom Van Eyck         /* The object has (apparently) been initialized but it is not (yet)
4543b0563631STom Van Eyck          * in use. It's ok to call abort on such an object, and there's
4544b0563631STom Van Eyck          * nothing to do. */
4545b0563631STom Van Eyck         return PSA_SUCCESS;
4546b0563631STom Van Eyck     }
4547b0563631STom Van Eyck 
4548b0563631STom Van Eyck     psa_driver_wrapper_cipher_abort(operation);
4549b0563631STom Van Eyck 
4550b0563631STom Van Eyck     operation->id = 0;
4551b0563631STom Van Eyck     operation->iv_set = 0;
4552b0563631STom Van Eyck     operation->iv_required = 0;
4553b0563631STom Van Eyck 
4554b0563631STom Van Eyck     return PSA_SUCCESS;
4555b0563631STom Van Eyck }
4556b0563631STom Van Eyck 
4557b0563631STom Van Eyck psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key,
4558b0563631STom Van Eyck                                 psa_algorithm_t alg,
4559b0563631STom Van Eyck                                 const uint8_t *input_external,
4560b0563631STom Van Eyck                                 size_t input_length,
4561b0563631STom Van Eyck                                 uint8_t *output_external,
4562b0563631STom Van Eyck                                 size_t output_size,
4563b0563631STom Van Eyck                                 size_t *output_length)
4564b0563631STom Van Eyck {
4565b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4566b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
4567b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
4568b0563631STom Van Eyck     uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE];
4569b0563631STom Van Eyck     size_t default_iv_length = 0;
4570b0563631STom Van Eyck 
4571b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
4572b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
4573b0563631STom Van Eyck 
4574b0563631STom Van Eyck     if (!PSA_ALG_IS_CIPHER(alg)) {
4575b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
4576b0563631STom Van Eyck         goto exit;
4577b0563631STom Van Eyck     }
4578b0563631STom Van Eyck 
4579b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot,
4580b0563631STom Van Eyck                                                    PSA_KEY_USAGE_ENCRYPT,
4581b0563631STom Van Eyck                                                    alg);
4582b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4583b0563631STom Van Eyck         goto exit;
4584b0563631STom Van Eyck     }
4585b0563631STom Van Eyck 
4586b0563631STom Van Eyck     default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg);
4587b0563631STom Van Eyck     if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) {
4588b0563631STom Van Eyck         status = PSA_ERROR_GENERIC_ERROR;
4589b0563631STom Van Eyck         goto exit;
4590b0563631STom Van Eyck     }
4591b0563631STom Van Eyck 
4592b0563631STom Van Eyck     if (default_iv_length > 0) {
4593b0563631STom Van Eyck         if (output_size < default_iv_length) {
4594b0563631STom Van Eyck             status = PSA_ERROR_BUFFER_TOO_SMALL;
4595b0563631STom Van Eyck             goto exit;
4596b0563631STom Van Eyck         }
4597b0563631STom Van Eyck 
4598b0563631STom Van Eyck         status = psa_generate_random_internal(local_iv, default_iv_length);
4599b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
4600b0563631STom Van Eyck             goto exit;
4601b0563631STom Van Eyck         }
4602b0563631STom Van Eyck     }
4603b0563631STom Van Eyck 
4604b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
4605b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
4606b0563631STom Van Eyck 
4607b0563631STom Van Eyck     status = psa_driver_wrapper_cipher_encrypt(
4608b0563631STom Van Eyck         &slot->attr, slot->key.data, slot->key.bytes,
4609b0563631STom Van Eyck         alg, local_iv, default_iv_length, input, input_length,
4610b0563631STom Van Eyck         psa_crypto_buffer_offset(output, default_iv_length),
4611b0563631STom Van Eyck         output_size - default_iv_length, output_length);
4612b0563631STom Van Eyck 
4613b0563631STom Van Eyck exit:
4614b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
4615b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
4616b0563631STom Van Eyck         status = unlock_status;
4617b0563631STom Van Eyck     }
4618b0563631STom Van Eyck 
4619b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
4620b0563631STom Van Eyck         if (default_iv_length > 0) {
4621b0563631STom Van Eyck             memcpy(output, local_iv, default_iv_length);
4622b0563631STom Van Eyck         }
4623b0563631STom Van Eyck         *output_length += default_iv_length;
4624b0563631STom Van Eyck     } else {
4625b0563631STom Van Eyck         *output_length = 0;
4626b0563631STom Van Eyck     }
4627b0563631STom Van Eyck 
4628b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
4629b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
4630b0563631STom Van Eyck 
4631b0563631STom Van Eyck     return status;
4632b0563631STom Van Eyck }
4633b0563631STom Van Eyck 
4634b0563631STom Van Eyck psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key,
4635b0563631STom Van Eyck                                 psa_algorithm_t alg,
4636b0563631STom Van Eyck                                 const uint8_t *input_external,
4637b0563631STom Van Eyck                                 size_t input_length,
4638b0563631STom Van Eyck                                 uint8_t *output_external,
4639b0563631STom Van Eyck                                 size_t output_size,
4640b0563631STom Van Eyck                                 size_t *output_length)
4641b0563631STom Van Eyck {
4642b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4643b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
4644b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
4645b0563631STom Van Eyck 
4646b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
4647b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
4648b0563631STom Van Eyck 
4649b0563631STom Van Eyck     if (!PSA_ALG_IS_CIPHER(alg)) {
4650b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
4651b0563631STom Van Eyck         goto exit;
4652b0563631STom Van Eyck     }
4653b0563631STom Van Eyck 
4654b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot,
4655b0563631STom Van Eyck                                                    PSA_KEY_USAGE_DECRYPT,
4656b0563631STom Van Eyck                                                    alg);
4657b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4658b0563631STom Van Eyck         goto exit;
4659b0563631STom Van Eyck     }
4660b0563631STom Van Eyck 
4661*cb034002SJerome Forissier     if (input_length < PSA_CIPHER_IV_LENGTH(slot->attr.type, alg)) {
4662b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
4663b0563631STom Van Eyck         goto exit;
4664b0563631STom Van Eyck     }
4665b0563631STom Van Eyck 
4666b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
4667b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
4668b0563631STom Van Eyck 
4669b0563631STom Van Eyck     status = psa_driver_wrapper_cipher_decrypt(
4670b0563631STom Van Eyck         &slot->attr, slot->key.data, slot->key.bytes,
4671b0563631STom Van Eyck         alg, input, input_length,
4672b0563631STom Van Eyck         output, output_size, output_length);
4673b0563631STom Van Eyck 
4674b0563631STom Van Eyck exit:
4675b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
4676b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
4677b0563631STom Van Eyck         status = unlock_status;
4678b0563631STom Van Eyck     }
4679b0563631STom Van Eyck 
4680b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4681b0563631STom Van Eyck         *output_length = 0;
4682b0563631STom Van Eyck     }
4683b0563631STom Van Eyck 
4684b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
4685b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
4686b0563631STom Van Eyck 
4687b0563631STom Van Eyck     return status;
4688b0563631STom Van Eyck }
4689b0563631STom Van Eyck 
4690b0563631STom Van Eyck 
4691b0563631STom Van Eyck /****************************************************************/
4692b0563631STom Van Eyck /* AEAD */
4693b0563631STom Van Eyck /****************************************************************/
4694b0563631STom Van Eyck 
4695b0563631STom Van Eyck /* Helper function to get the base algorithm from its variants. */
4696b0563631STom Van Eyck static psa_algorithm_t psa_aead_get_base_algorithm(psa_algorithm_t alg)
4697b0563631STom Van Eyck {
4698b0563631STom Van Eyck     return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg);
4699b0563631STom Van Eyck }
4700b0563631STom Van Eyck 
4701b0563631STom Van Eyck /* Helper function to perform common nonce length checks. */
4702b0563631STom Van Eyck static psa_status_t psa_aead_check_nonce_length(psa_algorithm_t alg,
4703b0563631STom Van Eyck                                                 size_t nonce_length)
4704b0563631STom Van Eyck {
4705b0563631STom Van Eyck     psa_algorithm_t base_alg = psa_aead_get_base_algorithm(alg);
4706b0563631STom Van Eyck 
4707b0563631STom Van Eyck     switch (base_alg) {
4708b0563631STom Van Eyck #if defined(PSA_WANT_ALG_GCM)
4709b0563631STom Van Eyck         case PSA_ALG_GCM:
4710b0563631STom Van Eyck             /* Not checking max nonce size here as GCM spec allows almost
4711b0563631STom Van Eyck              * arbitrarily large nonces. Please note that we do not generally
4712b0563631STom Van Eyck              * recommend the usage of nonces of greater length than
4713b0563631STom Van Eyck              * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter
4714b0563631STom Van Eyck              * size, which can then lead to collisions if you encrypt a very
4715b0563631STom Van Eyck              * large number of messages.*/
4716b0563631STom Van Eyck             if (nonce_length != 0) {
4717b0563631STom Van Eyck                 return PSA_SUCCESS;
4718b0563631STom Van Eyck             }
4719b0563631STom Van Eyck             break;
4720b0563631STom Van Eyck #endif /* PSA_WANT_ALG_GCM */
4721b0563631STom Van Eyck #if defined(PSA_WANT_ALG_CCM)
4722b0563631STom Van Eyck         case PSA_ALG_CCM:
4723b0563631STom Van Eyck             if (nonce_length >= 7 && nonce_length <= 13) {
4724b0563631STom Van Eyck                 return PSA_SUCCESS;
4725b0563631STom Van Eyck             }
4726b0563631STom Van Eyck             break;
4727b0563631STom Van Eyck #endif /* PSA_WANT_ALG_CCM */
4728b0563631STom Van Eyck #if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
4729b0563631STom Van Eyck         case PSA_ALG_CHACHA20_POLY1305:
4730b0563631STom Van Eyck             if (nonce_length == 12) {
4731b0563631STom Van Eyck                 return PSA_SUCCESS;
4732b0563631STom Van Eyck             } else if (nonce_length == 8) {
4733b0563631STom Van Eyck                 return PSA_ERROR_NOT_SUPPORTED;
4734b0563631STom Van Eyck             }
4735b0563631STom Van Eyck             break;
4736b0563631STom Van Eyck #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
4737b0563631STom Van Eyck         default:
4738b0563631STom Van Eyck             (void) nonce_length;
4739b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
4740b0563631STom Van Eyck     }
4741b0563631STom Van Eyck 
4742b0563631STom Van Eyck     return PSA_ERROR_INVALID_ARGUMENT;
4743b0563631STom Van Eyck }
4744b0563631STom Van Eyck 
4745b0563631STom Van Eyck static psa_status_t psa_aead_check_algorithm(psa_algorithm_t alg)
4746b0563631STom Van Eyck {
4747b0563631STom Van Eyck     if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) {
4748b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
4749b0563631STom Van Eyck     }
4750b0563631STom Van Eyck 
4751b0563631STom Van Eyck     return PSA_SUCCESS;
4752b0563631STom Van Eyck }
4753b0563631STom Van Eyck 
4754b0563631STom Van Eyck psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key,
4755b0563631STom Van Eyck                               psa_algorithm_t alg,
4756b0563631STom Van Eyck                               const uint8_t *nonce_external,
4757b0563631STom Van Eyck                               size_t nonce_length,
4758b0563631STom Van Eyck                               const uint8_t *additional_data_external,
4759b0563631STom Van Eyck                               size_t additional_data_length,
4760b0563631STom Van Eyck                               const uint8_t *plaintext_external,
4761b0563631STom Van Eyck                               size_t plaintext_length,
4762b0563631STom Van Eyck                               uint8_t *ciphertext_external,
4763b0563631STom Van Eyck                               size_t ciphertext_size,
4764b0563631STom Van Eyck                               size_t *ciphertext_length)
4765b0563631STom Van Eyck {
4766b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4767b0563631STom Van Eyck     psa_key_slot_t *slot;
4768b0563631STom Van Eyck 
4769b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(nonce_external, nonce);
4770b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(additional_data_external, additional_data);
4771b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(plaintext_external, plaintext);
4772b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext);
4773b0563631STom Van Eyck 
4774b0563631STom Van Eyck     *ciphertext_length = 0;
4775b0563631STom Van Eyck 
4776b0563631STom Van Eyck     status = psa_aead_check_algorithm(alg);
4777b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4778b0563631STom Van Eyck         return status;
4779b0563631STom Van Eyck     }
4780b0563631STom Van Eyck 
4781b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
4782b0563631STom Van Eyck         key, &slot, PSA_KEY_USAGE_ENCRYPT, alg);
4783b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4784b0563631STom Van Eyck         return status;
4785b0563631STom Van Eyck     }
4786b0563631STom Van Eyck 
4787b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
4788b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data);
4789b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext);
4790b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext);
4791b0563631STom Van Eyck 
4792b0563631STom Van Eyck     status = psa_aead_check_nonce_length(alg, nonce_length);
4793b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4794b0563631STom Van Eyck         goto exit;
4795b0563631STom Van Eyck     }
4796b0563631STom Van Eyck 
4797b0563631STom Van Eyck     status = psa_driver_wrapper_aead_encrypt(
4798b0563631STom Van Eyck         &slot->attr, slot->key.data, slot->key.bytes,
4799b0563631STom Van Eyck         alg,
4800b0563631STom Van Eyck         nonce, nonce_length,
4801b0563631STom Van Eyck         additional_data, additional_data_length,
4802b0563631STom Van Eyck         plaintext, plaintext_length,
4803b0563631STom Van Eyck         ciphertext, ciphertext_size, ciphertext_length);
4804b0563631STom Van Eyck 
4805b0563631STom Van Eyck     if (status != PSA_SUCCESS && ciphertext_size != 0) {
4806b0563631STom Van Eyck         memset(ciphertext, 0, ciphertext_size);
4807b0563631STom Van Eyck     }
4808b0563631STom Van Eyck 
4809b0563631STom Van Eyck exit:
4810b0563631STom Van Eyck     LOCAL_INPUT_FREE(nonce_external, nonce);
4811b0563631STom Van Eyck     LOCAL_INPUT_FREE(additional_data_external, additional_data);
4812b0563631STom Van Eyck     LOCAL_INPUT_FREE(plaintext_external, plaintext);
4813b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);
4814b0563631STom Van Eyck 
4815b0563631STom Van Eyck     psa_unregister_read_under_mutex(slot);
4816b0563631STom Van Eyck 
4817b0563631STom Van Eyck     return status;
4818b0563631STom Van Eyck }
4819b0563631STom Van Eyck 
4820b0563631STom Van Eyck psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key,
4821b0563631STom Van Eyck                               psa_algorithm_t alg,
4822b0563631STom Van Eyck                               const uint8_t *nonce_external,
4823b0563631STom Van Eyck                               size_t nonce_length,
4824b0563631STom Van Eyck                               const uint8_t *additional_data_external,
4825b0563631STom Van Eyck                               size_t additional_data_length,
4826b0563631STom Van Eyck                               const uint8_t *ciphertext_external,
4827b0563631STom Van Eyck                               size_t ciphertext_length,
4828b0563631STom Van Eyck                               uint8_t *plaintext_external,
4829b0563631STom Van Eyck                               size_t plaintext_size,
4830b0563631STom Van Eyck                               size_t *plaintext_length)
4831b0563631STom Van Eyck {
4832b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4833b0563631STom Van Eyck     psa_key_slot_t *slot;
4834b0563631STom Van Eyck 
4835b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(nonce_external, nonce);
4836b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(additional_data_external, additional_data);
4837b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext);
4838b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext);
4839b0563631STom Van Eyck 
4840b0563631STom Van Eyck     *plaintext_length = 0;
4841b0563631STom Van Eyck 
4842b0563631STom Van Eyck     status = psa_aead_check_algorithm(alg);
4843b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4844b0563631STom Van Eyck         return status;
4845b0563631STom Van Eyck     }
4846b0563631STom Van Eyck 
4847b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(
4848b0563631STom Van Eyck         key, &slot, PSA_KEY_USAGE_DECRYPT, alg);
4849b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4850b0563631STom Van Eyck         return status;
4851b0563631STom Van Eyck     }
4852b0563631STom Van Eyck 
4853b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
4854b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length,
4855b0563631STom Van Eyck                       additional_data);
4856b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext);
4857b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext);
4858b0563631STom Van Eyck 
4859b0563631STom Van Eyck     status = psa_aead_check_nonce_length(alg, nonce_length);
4860b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4861b0563631STom Van Eyck         goto exit;
4862b0563631STom Van Eyck     }
4863b0563631STom Van Eyck 
4864b0563631STom Van Eyck     status = psa_driver_wrapper_aead_decrypt(
4865b0563631STom Van Eyck         &slot->attr, slot->key.data, slot->key.bytes,
4866b0563631STom Van Eyck         alg,
4867b0563631STom Van Eyck         nonce, nonce_length,
4868b0563631STom Van Eyck         additional_data, additional_data_length,
4869b0563631STom Van Eyck         ciphertext, ciphertext_length,
4870b0563631STom Van Eyck         plaintext, plaintext_size, plaintext_length);
4871b0563631STom Van Eyck 
4872b0563631STom Van Eyck     if (status != PSA_SUCCESS && plaintext_size != 0) {
4873b0563631STom Van Eyck         memset(plaintext, 0, plaintext_size);
4874b0563631STom Van Eyck     }
4875b0563631STom Van Eyck 
4876b0563631STom Van Eyck exit:
4877b0563631STom Van Eyck     LOCAL_INPUT_FREE(nonce_external, nonce);
4878b0563631STom Van Eyck     LOCAL_INPUT_FREE(additional_data_external, additional_data);
4879b0563631STom Van Eyck     LOCAL_INPUT_FREE(ciphertext_external, ciphertext);
4880b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(plaintext_external, plaintext);
4881b0563631STom Van Eyck 
4882b0563631STom Van Eyck     psa_unregister_read_under_mutex(slot);
4883b0563631STom Van Eyck 
4884b0563631STom Van Eyck     return status;
4885b0563631STom Van Eyck }
4886b0563631STom Van Eyck 
4887b0563631STom Van Eyck static psa_status_t psa_validate_tag_length(psa_algorithm_t alg)
4888b0563631STom Van Eyck {
4889b0563631STom Van Eyck     const uint8_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
4890b0563631STom Van Eyck 
4891b0563631STom Van Eyck     switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {
4892b0563631STom Van Eyck #if defined(PSA_WANT_ALG_CCM)
4893b0563631STom Van Eyck         case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
4894b0563631STom Van Eyck             /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.*/
4895b0563631STom Van Eyck             if (tag_len < 4 || tag_len > 16 || tag_len % 2) {
4896b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
4897b0563631STom Van Eyck             }
4898b0563631STom Van Eyck             break;
4899b0563631STom Van Eyck #endif /* PSA_WANT_ALG_CCM */
4900b0563631STom Van Eyck 
4901b0563631STom Van Eyck #if defined(PSA_WANT_ALG_GCM)
4902b0563631STom Van Eyck         case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
4903b0563631STom Van Eyck             /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. */
4904b0563631STom Van Eyck             if (tag_len != 4 && tag_len != 8 && (tag_len < 12 || tag_len > 16)) {
4905b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
4906b0563631STom Van Eyck             }
4907b0563631STom Van Eyck             break;
4908b0563631STom Van Eyck #endif /* PSA_WANT_ALG_GCM */
4909b0563631STom Van Eyck 
4910b0563631STom Van Eyck #if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
4911b0563631STom Van Eyck         case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
4912b0563631STom Van Eyck             /* We only support the default tag length. */
4913b0563631STom Van Eyck             if (tag_len != 16) {
4914b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
4915b0563631STom Van Eyck             }
4916b0563631STom Van Eyck             break;
4917b0563631STom Van Eyck #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
4918b0563631STom Van Eyck 
4919b0563631STom Van Eyck         default:
4920b0563631STom Van Eyck             (void) tag_len;
4921b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
4922b0563631STom Van Eyck     }
4923b0563631STom Van Eyck     return PSA_SUCCESS;
4924b0563631STom Van Eyck }
4925b0563631STom Van Eyck 
4926b0563631STom Van Eyck /* Set the key for a multipart authenticated operation. */
4927b0563631STom Van Eyck static psa_status_t psa_aead_setup(psa_aead_operation_t *operation,
4928b0563631STom Van Eyck                                    int is_encrypt,
4929b0563631STom Van Eyck                                    mbedtls_svc_key_id_t key,
4930b0563631STom Van Eyck                                    psa_algorithm_t alg)
4931b0563631STom Van Eyck {
4932b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
4933b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
4934b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
4935b0563631STom Van Eyck     psa_key_usage_t key_usage = 0;
4936b0563631STom Van Eyck 
4937b0563631STom Van Eyck     status = psa_aead_check_algorithm(alg);
4938b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4939b0563631STom Van Eyck         goto exit;
4940b0563631STom Van Eyck     }
4941b0563631STom Van Eyck 
4942b0563631STom Van Eyck     if (operation->id != 0) {
4943b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4944b0563631STom Van Eyck         goto exit;
4945b0563631STom Van Eyck     }
4946b0563631STom Van Eyck 
4947b0563631STom Van Eyck     if (operation->nonce_set || operation->lengths_set ||
4948b0563631STom Van Eyck         operation->ad_started || operation->body_started) {
4949b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
4950b0563631STom Van Eyck         goto exit;
4951b0563631STom Van Eyck     }
4952b0563631STom Van Eyck 
4953b0563631STom Van Eyck     if (is_encrypt) {
4954b0563631STom Van Eyck         key_usage = PSA_KEY_USAGE_ENCRYPT;
4955b0563631STom Van Eyck     } else {
4956b0563631STom Van Eyck         key_usage = PSA_KEY_USAGE_DECRYPT;
4957b0563631STom Van Eyck     }
4958b0563631STom Van Eyck 
4959b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(key, &slot, key_usage,
4960b0563631STom Van Eyck                                                    alg);
4961b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4962b0563631STom Van Eyck         goto exit;
4963b0563631STom Van Eyck     }
4964b0563631STom Van Eyck 
4965b0563631STom Van Eyck     if ((status = psa_validate_tag_length(alg)) != PSA_SUCCESS) {
4966b0563631STom Van Eyck         goto exit;
4967b0563631STom Van Eyck     }
4968b0563631STom Van Eyck 
4969b0563631STom Van Eyck     if (is_encrypt) {
4970b0563631STom Van Eyck         status = psa_driver_wrapper_aead_encrypt_setup(operation,
4971b0563631STom Van Eyck                                                        &slot->attr,
4972b0563631STom Van Eyck                                                        slot->key.data,
4973b0563631STom Van Eyck                                                        slot->key.bytes,
4974b0563631STom Van Eyck                                                        alg);
4975b0563631STom Van Eyck     } else {
4976b0563631STom Van Eyck         status = psa_driver_wrapper_aead_decrypt_setup(operation,
4977b0563631STom Van Eyck                                                        &slot->attr,
4978b0563631STom Van Eyck                                                        slot->key.data,
4979b0563631STom Van Eyck                                                        slot->key.bytes,
4980b0563631STom Van Eyck                                                        alg);
4981b0563631STom Van Eyck     }
4982b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
4983b0563631STom Van Eyck         goto exit;
4984b0563631STom Van Eyck     }
4985b0563631STom Van Eyck 
4986b0563631STom Van Eyck     operation->key_type = psa_get_key_type(&slot->attr);
4987b0563631STom Van Eyck 
4988b0563631STom Van Eyck exit:
4989b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
4990b0563631STom Van Eyck 
4991b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
4992b0563631STom Van Eyck         status = unlock_status;
4993b0563631STom Van Eyck         operation->alg = psa_aead_get_base_algorithm(alg);
4994b0563631STom Van Eyck         operation->is_encrypt = is_encrypt;
4995b0563631STom Van Eyck     } else {
4996b0563631STom Van Eyck         psa_aead_abort(operation);
4997b0563631STom Van Eyck     }
4998b0563631STom Van Eyck 
4999b0563631STom Van Eyck     return status;
5000b0563631STom Van Eyck }
5001b0563631STom Van Eyck 
5002b0563631STom Van Eyck /* Set the key for a multipart authenticated encryption operation. */
5003b0563631STom Van Eyck psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,
5004b0563631STom Van Eyck                                     mbedtls_svc_key_id_t key,
5005b0563631STom Van Eyck                                     psa_algorithm_t alg)
5006b0563631STom Van Eyck {
5007b0563631STom Van Eyck     return psa_aead_setup(operation, 1, key, alg);
5008b0563631STom Van Eyck }
5009b0563631STom Van Eyck 
5010b0563631STom Van Eyck /* Set the key for a multipart authenticated decryption operation. */
5011b0563631STom Van Eyck psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation,
5012b0563631STom Van Eyck                                     mbedtls_svc_key_id_t key,
5013b0563631STom Van Eyck                                     psa_algorithm_t alg)
5014b0563631STom Van Eyck {
5015b0563631STom Van Eyck     return psa_aead_setup(operation, 0, key, alg);
5016b0563631STom Van Eyck }
5017b0563631STom Van Eyck 
5018b0563631STom Van Eyck static psa_status_t psa_aead_set_nonce_internal(psa_aead_operation_t *operation,
5019b0563631STom Van Eyck                                                 const uint8_t *nonce,
5020b0563631STom Van Eyck                                                 size_t nonce_length)
5021b0563631STom Van Eyck {
5022b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5023b0563631STom Van Eyck 
5024b0563631STom Van Eyck     if (operation->id == 0) {
5025b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5026b0563631STom Van Eyck         goto exit;
5027b0563631STom Van Eyck     }
5028b0563631STom Van Eyck 
5029b0563631STom Van Eyck     if (operation->nonce_set) {
5030b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5031b0563631STom Van Eyck         goto exit;
5032b0563631STom Van Eyck     }
5033b0563631STom Van Eyck 
5034b0563631STom Van Eyck     status = psa_aead_check_nonce_length(operation->alg, nonce_length);
5035b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5036b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
5037b0563631STom Van Eyck         goto exit;
5038b0563631STom Van Eyck     }
5039b0563631STom Van Eyck 
5040b0563631STom Van Eyck     status = psa_driver_wrapper_aead_set_nonce(operation, nonce,
5041b0563631STom Van Eyck                                                nonce_length);
5042b0563631STom Van Eyck 
5043b0563631STom Van Eyck exit:
5044b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
5045b0563631STom Van Eyck         operation->nonce_set = 1;
5046b0563631STom Van Eyck     } else {
5047b0563631STom Van Eyck         psa_aead_abort(operation);
5048b0563631STom Van Eyck     }
5049b0563631STom Van Eyck 
5050b0563631STom Van Eyck     return status;
5051b0563631STom Van Eyck }
5052b0563631STom Van Eyck 
5053b0563631STom Van Eyck /* Generate a random nonce / IV for multipart AEAD operation */
5054b0563631STom Van Eyck psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,
5055b0563631STom Van Eyck                                      uint8_t *nonce_external,
5056b0563631STom Van Eyck                                      size_t nonce_size,
5057b0563631STom Van Eyck                                      size_t *nonce_length)
5058b0563631STom Van Eyck {
5059b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5060b0563631STom Van Eyck     uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE];
5061b0563631STom Van Eyck     size_t required_nonce_size = 0;
5062b0563631STom Van Eyck 
5063b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(nonce_external, nonce);
5064b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(nonce_external, nonce_size, nonce);
5065b0563631STom Van Eyck 
5066b0563631STom Van Eyck     *nonce_length = 0;
5067b0563631STom Van Eyck 
5068b0563631STom Van Eyck     if (operation->id == 0) {
5069b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5070b0563631STom Van Eyck         goto exit;
5071b0563631STom Van Eyck     }
5072b0563631STom Van Eyck 
5073b0563631STom Van Eyck     if (operation->nonce_set || !operation->is_encrypt) {
5074b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5075b0563631STom Van Eyck         goto exit;
5076b0563631STom Van Eyck     }
5077b0563631STom Van Eyck 
5078b0563631STom Van Eyck     /* For CCM, this size may not be correct according to the PSA
5079b0563631STom Van Eyck      * specification. The PSA Crypto 1.0.1 specification states:
5080b0563631STom Van Eyck      *
5081b0563631STom Van Eyck      * CCM encodes the plaintext length pLen in L octets, with L the smallest
5082b0563631STom Van Eyck      * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes.
5083b0563631STom Van Eyck      *
5084b0563631STom Van Eyck      * However this restriction that L has to be the smallest integer is not
5085b0563631STom Van Eyck      * applied in practice, and it is not implementable here since the
5086b0563631STom Van Eyck      * plaintext length may or may not be known at this time. */
5087b0563631STom Van Eyck     required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type,
5088b0563631STom Van Eyck                                                 operation->alg);
5089b0563631STom Van Eyck     if (nonce_size < required_nonce_size) {
5090b0563631STom Van Eyck         status = PSA_ERROR_BUFFER_TOO_SMALL;
5091b0563631STom Van Eyck         goto exit;
5092b0563631STom Van Eyck     }
5093b0563631STom Van Eyck 
5094b0563631STom Van Eyck     status = psa_generate_random_internal(local_nonce, required_nonce_size);
5095b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5096b0563631STom Van Eyck         goto exit;
5097b0563631STom Van Eyck     }
5098b0563631STom Van Eyck 
5099b0563631STom Van Eyck     status = psa_aead_set_nonce_internal(operation, local_nonce,
5100b0563631STom Van Eyck                                          required_nonce_size);
5101b0563631STom Van Eyck 
5102b0563631STom Van Eyck exit:
5103b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
5104b0563631STom Van Eyck         memcpy(nonce, local_nonce, required_nonce_size);
5105b0563631STom Van Eyck         *nonce_length = required_nonce_size;
5106b0563631STom Van Eyck     } else {
5107b0563631STom Van Eyck         psa_aead_abort(operation);
5108b0563631STom Van Eyck     }
5109b0563631STom Van Eyck 
5110b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(nonce_external, nonce);
5111b0563631STom Van Eyck 
5112b0563631STom Van Eyck     return status;
5113b0563631STom Van Eyck }
5114b0563631STom Van Eyck 
5115b0563631STom Van Eyck /* Set the nonce for a multipart authenticated encryption or decryption
5116b0563631STom Van Eyck    operation.*/
5117b0563631STom Van Eyck psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,
5118b0563631STom Van Eyck                                 const uint8_t *nonce_external,
5119b0563631STom Van Eyck                                 size_t nonce_length)
5120b0563631STom Van Eyck {
5121b0563631STom Van Eyck     psa_status_t status;
5122b0563631STom Van Eyck 
5123b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(nonce_external, nonce);
5124b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
5125b0563631STom Van Eyck 
5126b0563631STom Van Eyck     status = psa_aead_set_nonce_internal(operation, nonce, nonce_length);
5127b0563631STom Van Eyck 
5128b0563631STom Van Eyck /* Exit label is only needed for buffer copying, prevent unused warnings. */
5129b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
5130b0563631STom Van Eyck exit:
5131b0563631STom Van Eyck #endif
5132b0563631STom Van Eyck 
5133b0563631STom Van Eyck     LOCAL_INPUT_FREE(nonce_external, nonce);
5134b0563631STom Van Eyck 
5135b0563631STom Van Eyck     return status;
5136b0563631STom Van Eyck }
5137b0563631STom Van Eyck 
5138b0563631STom Van Eyck /* Declare the lengths of the message and additional data for multipart AEAD. */
5139b0563631STom Van Eyck psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,
5140b0563631STom Van Eyck                                   size_t ad_length,
5141b0563631STom Van Eyck                                   size_t plaintext_length)
5142b0563631STom Van Eyck {
5143b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5144b0563631STom Van Eyck 
5145b0563631STom Van Eyck     if (operation->id == 0) {
5146b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5147b0563631STom Van Eyck         goto exit;
5148b0563631STom Van Eyck     }
5149b0563631STom Van Eyck 
5150b0563631STom Van Eyck     if (operation->lengths_set || operation->ad_started ||
5151b0563631STom Van Eyck         operation->body_started) {
5152b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5153b0563631STom Van Eyck         goto exit;
5154b0563631STom Van Eyck     }
5155b0563631STom Van Eyck 
5156b0563631STom Van Eyck     switch (operation->alg) {
5157b0563631STom Van Eyck #if defined(PSA_WANT_ALG_GCM)
5158b0563631STom Van Eyck         case PSA_ALG_GCM:
5159b0563631STom Van Eyck             /* Lengths can only be too large for GCM if size_t is bigger than 32
5160b0563631STom Van Eyck              * bits. Without the guard this code will generate warnings on 32bit
5161b0563631STom Van Eyck              * builds. */
5162b0563631STom Van Eyck #if SIZE_MAX > UINT32_MAX
5163b0563631STom Van Eyck             if (((uint64_t) ad_length) >> 61 != 0 ||
5164b0563631STom Van Eyck                 ((uint64_t) plaintext_length) > 0xFFFFFFFE0ull) {
5165b0563631STom Van Eyck                 status = PSA_ERROR_INVALID_ARGUMENT;
5166b0563631STom Van Eyck                 goto exit;
5167b0563631STom Van Eyck             }
5168b0563631STom Van Eyck #endif
5169b0563631STom Van Eyck             break;
5170b0563631STom Van Eyck #endif /* PSA_WANT_ALG_GCM */
5171b0563631STom Van Eyck #if defined(PSA_WANT_ALG_CCM)
5172b0563631STom Van Eyck         case PSA_ALG_CCM:
5173b0563631STom Van Eyck             if (ad_length > 0xFF00) {
5174b0563631STom Van Eyck                 status = PSA_ERROR_INVALID_ARGUMENT;
5175b0563631STom Van Eyck                 goto exit;
5176b0563631STom Van Eyck             }
5177b0563631STom Van Eyck             break;
5178b0563631STom Van Eyck #endif /* PSA_WANT_ALG_CCM */
5179b0563631STom Van Eyck #if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
5180b0563631STom Van Eyck         case PSA_ALG_CHACHA20_POLY1305:
5181b0563631STom Van Eyck             /* No length restrictions for ChaChaPoly. */
5182b0563631STom Van Eyck             break;
5183b0563631STom Van Eyck #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
5184b0563631STom Van Eyck         default:
5185b0563631STom Van Eyck             break;
5186b0563631STom Van Eyck     }
5187b0563631STom Van Eyck 
5188b0563631STom Van Eyck     status = psa_driver_wrapper_aead_set_lengths(operation, ad_length,
5189b0563631STom Van Eyck                                                  plaintext_length);
5190b0563631STom Van Eyck 
5191b0563631STom Van Eyck exit:
5192b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
5193b0563631STom Van Eyck         operation->ad_remaining = ad_length;
5194b0563631STom Van Eyck         operation->body_remaining = plaintext_length;
5195b0563631STom Van Eyck         operation->lengths_set = 1;
5196b0563631STom Van Eyck     } else {
5197b0563631STom Van Eyck         psa_aead_abort(operation);
5198b0563631STom Van Eyck     }
5199b0563631STom Van Eyck 
5200b0563631STom Van Eyck     return status;
5201b0563631STom Van Eyck }
5202b0563631STom Van Eyck 
5203b0563631STom Van Eyck /* Pass additional data to an active multipart AEAD operation. */
5204b0563631STom Van Eyck psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,
5205b0563631STom Van Eyck                                 const uint8_t *input_external,
5206b0563631STom Van Eyck                                 size_t input_length)
5207b0563631STom Van Eyck {
5208b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5209b0563631STom Van Eyck 
5210b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
5211b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
5212b0563631STom Van Eyck 
5213b0563631STom Van Eyck     if (operation->id == 0) {
5214b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5215b0563631STom Van Eyck         goto exit;
5216b0563631STom Van Eyck     }
5217b0563631STom Van Eyck 
5218b0563631STom Van Eyck     if (!operation->nonce_set || operation->body_started) {
5219b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5220b0563631STom Van Eyck         goto exit;
5221b0563631STom Van Eyck     }
5222b0563631STom Van Eyck 
5223*cb034002SJerome Forissier     /* No input to add (zero length), nothing to do. */
5224*cb034002SJerome Forissier     if (input_length == 0) {
5225*cb034002SJerome Forissier         status = PSA_SUCCESS;
5226*cb034002SJerome Forissier         goto exit;
5227*cb034002SJerome Forissier     }
5228*cb034002SJerome Forissier 
5229b0563631STom Van Eyck     if (operation->lengths_set) {
5230b0563631STom Van Eyck         if (operation->ad_remaining < input_length) {
5231b0563631STom Van Eyck             status = PSA_ERROR_INVALID_ARGUMENT;
5232b0563631STom Van Eyck             goto exit;
5233b0563631STom Van Eyck         }
5234b0563631STom Van Eyck 
5235b0563631STom Van Eyck         operation->ad_remaining -= input_length;
5236b0563631STom Van Eyck     }
5237b0563631STom Van Eyck #if defined(PSA_WANT_ALG_CCM)
5238b0563631STom Van Eyck     else if (operation->alg == PSA_ALG_CCM) {
5239b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5240b0563631STom Van Eyck         goto exit;
5241b0563631STom Van Eyck     }
5242b0563631STom Van Eyck #endif /* PSA_WANT_ALG_CCM */
5243b0563631STom Van Eyck 
5244b0563631STom Van Eyck     status = psa_driver_wrapper_aead_update_ad(operation, input,
5245b0563631STom Van Eyck                                                input_length);
5246b0563631STom Van Eyck 
5247b0563631STom Van Eyck exit:
5248b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
5249b0563631STom Van Eyck         operation->ad_started = 1;
5250b0563631STom Van Eyck     } else {
5251b0563631STom Van Eyck         psa_aead_abort(operation);
5252b0563631STom Van Eyck     }
5253b0563631STom Van Eyck 
5254b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
5255b0563631STom Van Eyck 
5256b0563631STom Van Eyck     return status;
5257b0563631STom Van Eyck }
5258b0563631STom Van Eyck 
5259b0563631STom Van Eyck /* Encrypt or decrypt a message fragment in an active multipart AEAD
5260b0563631STom Van Eyck    operation.*/
5261b0563631STom Van Eyck psa_status_t psa_aead_update(psa_aead_operation_t *operation,
5262b0563631STom Van Eyck                              const uint8_t *input_external,
5263b0563631STom Van Eyck                              size_t input_length,
5264b0563631STom Van Eyck                              uint8_t *output_external,
5265b0563631STom Van Eyck                              size_t output_size,
5266b0563631STom Van Eyck                              size_t *output_length)
5267b0563631STom Van Eyck {
5268b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5269b0563631STom Van Eyck 
5270b0563631STom Van Eyck 
5271b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
5272b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
5273b0563631STom Van Eyck 
5274b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
5275b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
5276b0563631STom Van Eyck 
5277b0563631STom Van Eyck     *output_length = 0;
5278b0563631STom Van Eyck 
5279b0563631STom Van Eyck     if (operation->id == 0) {
5280b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5281b0563631STom Van Eyck         goto exit;
5282b0563631STom Van Eyck     }
5283b0563631STom Van Eyck 
5284b0563631STom Van Eyck     if (!operation->nonce_set) {
5285b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5286b0563631STom Van Eyck         goto exit;
5287b0563631STom Van Eyck     }
5288b0563631STom Van Eyck 
5289b0563631STom Van Eyck     if (operation->lengths_set) {
5290b0563631STom Van Eyck         /* Additional data length was supplied, but not all the additional
5291b0563631STom Van Eyck            data was supplied.*/
5292b0563631STom Van Eyck         if (operation->ad_remaining != 0) {
5293b0563631STom Van Eyck             status = PSA_ERROR_INVALID_ARGUMENT;
5294b0563631STom Van Eyck             goto exit;
5295b0563631STom Van Eyck         }
5296b0563631STom Van Eyck 
5297b0563631STom Van Eyck         /* Too much data provided. */
5298b0563631STom Van Eyck         if (operation->body_remaining < input_length) {
5299b0563631STom Van Eyck             status = PSA_ERROR_INVALID_ARGUMENT;
5300b0563631STom Van Eyck             goto exit;
5301b0563631STom Van Eyck         }
5302b0563631STom Van Eyck 
5303b0563631STom Van Eyck         operation->body_remaining -= input_length;
5304b0563631STom Van Eyck     }
5305b0563631STom Van Eyck #if defined(PSA_WANT_ALG_CCM)
5306b0563631STom Van Eyck     else if (operation->alg == PSA_ALG_CCM) {
5307b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5308b0563631STom Van Eyck         goto exit;
5309b0563631STom Van Eyck     }
5310b0563631STom Van Eyck #endif /* PSA_WANT_ALG_CCM */
5311b0563631STom Van Eyck 
5312b0563631STom Van Eyck     status = psa_driver_wrapper_aead_update(operation, input, input_length,
5313b0563631STom Van Eyck                                             output, output_size,
5314b0563631STom Van Eyck                                             output_length);
5315b0563631STom Van Eyck 
5316b0563631STom Van Eyck exit:
5317b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
5318b0563631STom Van Eyck         operation->body_started = 1;
5319b0563631STom Van Eyck     } else {
5320b0563631STom Van Eyck         psa_aead_abort(operation);
5321b0563631STom Van Eyck     }
5322b0563631STom Van Eyck 
5323b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
5324b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
5325b0563631STom Van Eyck 
5326b0563631STom Van Eyck     return status;
5327b0563631STom Van Eyck }
5328b0563631STom Van Eyck 
5329b0563631STom Van Eyck static psa_status_t psa_aead_final_checks(const psa_aead_operation_t *operation)
5330b0563631STom Van Eyck {
5331b0563631STom Van Eyck     if (operation->id == 0 || !operation->nonce_set) {
5332b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
5333b0563631STom Van Eyck     }
5334b0563631STom Van Eyck 
5335b0563631STom Van Eyck     if (operation->lengths_set && (operation->ad_remaining != 0 ||
5336b0563631STom Van Eyck                                    operation->body_remaining != 0)) {
5337b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
5338b0563631STom Van Eyck     }
5339b0563631STom Van Eyck 
5340b0563631STom Van Eyck     return PSA_SUCCESS;
5341b0563631STom Van Eyck }
5342b0563631STom Van Eyck 
5343b0563631STom Van Eyck /* Finish encrypting a message in a multipart AEAD operation. */
5344b0563631STom Van Eyck psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
5345b0563631STom Van Eyck                              uint8_t *ciphertext_external,
5346b0563631STom Van Eyck                              size_t ciphertext_size,
5347b0563631STom Van Eyck                              size_t *ciphertext_length,
5348b0563631STom Van Eyck                              uint8_t *tag_external,
5349b0563631STom Van Eyck                              size_t tag_size,
5350b0563631STom Van Eyck                              size_t *tag_length)
5351b0563631STom Van Eyck {
5352b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5353b0563631STom Van Eyck 
5354b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext);
5355b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(tag_external, tag);
5356b0563631STom Van Eyck 
5357b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext);
5358b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(tag_external, tag_size, tag);
5359b0563631STom Van Eyck 
5360b0563631STom Van Eyck     *ciphertext_length = 0;
5361b0563631STom Van Eyck     *tag_length = tag_size;
5362b0563631STom Van Eyck 
5363b0563631STom Van Eyck     status = psa_aead_final_checks(operation);
5364b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5365b0563631STom Van Eyck         goto exit;
5366b0563631STom Van Eyck     }
5367b0563631STom Van Eyck 
5368b0563631STom Van Eyck     if (!operation->is_encrypt) {
5369b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5370b0563631STom Van Eyck         goto exit;
5371b0563631STom Van Eyck     }
5372b0563631STom Van Eyck 
5373b0563631STom Van Eyck     status = psa_driver_wrapper_aead_finish(operation, ciphertext,
5374b0563631STom Van Eyck                                             ciphertext_size,
5375b0563631STom Van Eyck                                             ciphertext_length,
5376b0563631STom Van Eyck                                             tag, tag_size, tag_length);
5377b0563631STom Van Eyck 
5378b0563631STom Van Eyck exit:
5379b0563631STom Van Eyck 
5380b0563631STom Van Eyck 
5381b0563631STom Van Eyck     /* In case the operation fails and the user fails to check for failure or
5382b0563631STom Van Eyck      * the zero tag size, make sure the tag is set to something implausible.
5383b0563631STom Van Eyck      * Even if the operation succeeds, make sure we clear the rest of the
5384b0563631STom Van Eyck      * buffer to prevent potential leakage of anything previously placed in
5385b0563631STom Van Eyck      * the same buffer.*/
5386b0563631STom Van Eyck     psa_wipe_tag_output_buffer(tag, status, tag_size, *tag_length);
5387b0563631STom Van Eyck 
5388b0563631STom Van Eyck     psa_aead_abort(operation);
5389b0563631STom Van Eyck 
5390b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);
5391b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(tag_external, tag);
5392b0563631STom Van Eyck 
5393b0563631STom Van Eyck     return status;
5394b0563631STom Van Eyck }
5395b0563631STom Van Eyck 
5396b0563631STom Van Eyck /* Finish authenticating and decrypting a message in a multipart AEAD
5397b0563631STom Van Eyck    operation.*/
5398b0563631STom Van Eyck psa_status_t psa_aead_verify(psa_aead_operation_t *operation,
5399b0563631STom Van Eyck                              uint8_t *plaintext_external,
5400b0563631STom Van Eyck                              size_t plaintext_size,
5401b0563631STom Van Eyck                              size_t *plaintext_length,
5402b0563631STom Van Eyck                              const uint8_t *tag_external,
5403b0563631STom Van Eyck                              size_t tag_length)
5404b0563631STom Van Eyck {
5405b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5406b0563631STom Van Eyck 
5407b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext);
5408b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(tag_external, tag);
5409b0563631STom Van Eyck 
5410b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext);
5411b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(tag_external, tag_length, tag);
5412b0563631STom Van Eyck 
5413b0563631STom Van Eyck     *plaintext_length = 0;
5414b0563631STom Van Eyck 
5415b0563631STom Van Eyck     status = psa_aead_final_checks(operation);
5416b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5417b0563631STom Van Eyck         goto exit;
5418b0563631STom Van Eyck     }
5419b0563631STom Van Eyck 
5420b0563631STom Van Eyck     if (operation->is_encrypt) {
5421b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5422b0563631STom Van Eyck         goto exit;
5423b0563631STom Van Eyck     }
5424b0563631STom Van Eyck 
5425b0563631STom Van Eyck     status = psa_driver_wrapper_aead_verify(operation, plaintext,
5426b0563631STom Van Eyck                                             plaintext_size,
5427b0563631STom Van Eyck                                             plaintext_length,
5428b0563631STom Van Eyck                                             tag, tag_length);
5429b0563631STom Van Eyck 
5430b0563631STom Van Eyck exit:
5431b0563631STom Van Eyck     psa_aead_abort(operation);
5432b0563631STom Van Eyck 
5433b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(plaintext_external, plaintext);
5434b0563631STom Van Eyck     LOCAL_INPUT_FREE(tag_external, tag);
5435b0563631STom Van Eyck 
5436b0563631STom Van Eyck     return status;
5437b0563631STom Van Eyck }
5438b0563631STom Van Eyck 
5439b0563631STom Van Eyck /* Abort an AEAD operation. */
5440b0563631STom Van Eyck psa_status_t psa_aead_abort(psa_aead_operation_t *operation)
5441b0563631STom Van Eyck {
5442b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5443b0563631STom Van Eyck 
5444b0563631STom Van Eyck     if (operation->id == 0) {
5445b0563631STom Van Eyck         /* The object has (apparently) been initialized but it is not (yet)
5446b0563631STom Van Eyck          * in use. It's ok to call abort on such an object, and there's
5447b0563631STom Van Eyck          * nothing to do. */
5448b0563631STom Van Eyck         return PSA_SUCCESS;
5449b0563631STom Van Eyck     }
5450b0563631STom Van Eyck 
5451b0563631STom Van Eyck     status = psa_driver_wrapper_aead_abort(operation);
5452b0563631STom Van Eyck 
5453b0563631STom Van Eyck     memset(operation, 0, sizeof(*operation));
5454b0563631STom Van Eyck 
5455b0563631STom Van Eyck     return status;
5456b0563631STom Van Eyck }
5457b0563631STom Van Eyck 
5458b0563631STom Van Eyck /****************************************************************/
5459b0563631STom Van Eyck /* Generators */
5460b0563631STom Van Eyck /****************************************************************/
5461b0563631STom Van Eyck 
5462b0563631STom Van Eyck #if defined(BUILTIN_ALG_ANY_HKDF) || \
5463b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
5464b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \
5465b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \
5466b0563631STom Van Eyck     defined(PSA_HAVE_SOFT_PBKDF2)
5467b0563631STom Van Eyck #define AT_LEAST_ONE_BUILTIN_KDF
5468b0563631STom Van Eyck #endif /* At least one builtin KDF */
5469b0563631STom Van Eyck 
5470b0563631STom Van Eyck #if defined(BUILTIN_ALG_ANY_HKDF) || \
5471b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
5472b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
5473b0563631STom Van Eyck static psa_status_t psa_key_derivation_start_hmac(
5474b0563631STom Van Eyck     psa_mac_operation_t *operation,
5475b0563631STom Van Eyck     psa_algorithm_t hash_alg,
5476b0563631STom Van Eyck     const uint8_t *hmac_key,
5477b0563631STom Van Eyck     size_t hmac_key_length)
5478b0563631STom Van Eyck {
5479b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5480b0563631STom Van Eyck     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
5481b0563631STom Van Eyck     psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
5482b0563631STom Van Eyck     psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(hmac_key_length));
5483b0563631STom Van Eyck     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
5484b0563631STom Van Eyck 
5485b0563631STom Van Eyck     operation->is_sign = 1;
5486b0563631STom Van Eyck     operation->mac_size = PSA_HASH_LENGTH(hash_alg);
5487b0563631STom Van Eyck 
5488b0563631STom Van Eyck     status = psa_driver_wrapper_mac_sign_setup(operation,
5489b0563631STom Van Eyck                                                &attributes,
5490b0563631STom Van Eyck                                                hmac_key, hmac_key_length,
5491b0563631STom Van Eyck                                                PSA_ALG_HMAC(hash_alg));
5492b0563631STom Van Eyck 
5493b0563631STom Van Eyck     psa_reset_key_attributes(&attributes);
5494b0563631STom Van Eyck     return status;
5495b0563631STom Van Eyck }
5496b0563631STom Van Eyck #endif /* KDF algorithms reliant on HMAC */
5497b0563631STom Van Eyck 
5498b0563631STom Van Eyck #define HKDF_STATE_INIT 0 /* no input yet */
5499b0563631STom Van Eyck #define HKDF_STATE_STARTED 1 /* got salt */
5500b0563631STom Van Eyck #define HKDF_STATE_KEYED 2 /* got key */
5501b0563631STom Van Eyck #define HKDF_STATE_OUTPUT 3 /* output started */
5502b0563631STom Van Eyck 
5503b0563631STom Van Eyck static psa_algorithm_t psa_key_derivation_get_kdf_alg(
5504b0563631STom Van Eyck     const psa_key_derivation_operation_t *operation)
5505b0563631STom Van Eyck {
5506b0563631STom Van Eyck     if (PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) {
5507b0563631STom Van Eyck         return PSA_ALG_KEY_AGREEMENT_GET_KDF(operation->alg);
5508b0563631STom Van Eyck     } else {
5509b0563631STom Van Eyck         return operation->alg;
5510b0563631STom Van Eyck     }
5511b0563631STom Van Eyck }
5512b0563631STom Van Eyck 
5513b0563631STom Van Eyck psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation)
5514b0563631STom Van Eyck {
5515b0563631STom Van Eyck     psa_status_t status = PSA_SUCCESS;
5516b0563631STom Van Eyck     psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
5517b0563631STom Van Eyck     if (kdf_alg == 0) {
5518b0563631STom Van Eyck         /* The object has (apparently) been initialized but it is not
5519b0563631STom Van Eyck          * in use. It's ok to call abort on such an object, and there's
5520b0563631STom Van Eyck          * nothing to do. */
5521b0563631STom Van Eyck     } else
5522b0563631STom Van Eyck #if defined(BUILTIN_ALG_ANY_HKDF)
5523b0563631STom Van Eyck     if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {
5524b0563631STom Van Eyck         mbedtls_free(operation->ctx.hkdf.info);
5525b0563631STom Van Eyck         status = psa_mac_abort(&operation->ctx.hkdf.hmac);
5526b0563631STom Van Eyck     } else
5527b0563631STom Van Eyck #endif /* BUILTIN_ALG_ANY_HKDF */
5528b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
5529b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
5530b0563631STom Van Eyck     if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
5531b0563631STom Van Eyck         /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */
5532b0563631STom Van Eyck         PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
5533b0563631STom Van Eyck         if (operation->ctx.tls12_prf.secret != NULL) {
5534b0563631STom Van Eyck             mbedtls_zeroize_and_free(operation->ctx.tls12_prf.secret,
5535b0563631STom Van Eyck                                      operation->ctx.tls12_prf.secret_length);
5536b0563631STom Van Eyck         }
5537b0563631STom Van Eyck 
5538b0563631STom Van Eyck         if (operation->ctx.tls12_prf.seed != NULL) {
5539b0563631STom Van Eyck             mbedtls_zeroize_and_free(operation->ctx.tls12_prf.seed,
5540b0563631STom Van Eyck                                      operation->ctx.tls12_prf.seed_length);
5541b0563631STom Van Eyck         }
5542b0563631STom Van Eyck 
5543b0563631STom Van Eyck         if (operation->ctx.tls12_prf.label != NULL) {
5544b0563631STom Van Eyck             mbedtls_zeroize_and_free(operation->ctx.tls12_prf.label,
5545b0563631STom Van Eyck                                      operation->ctx.tls12_prf.label_length);
5546b0563631STom Van Eyck         }
5547b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
5548b0563631STom Van Eyck         if (operation->ctx.tls12_prf.other_secret != NULL) {
5549b0563631STom Van Eyck             mbedtls_zeroize_and_free(operation->ctx.tls12_prf.other_secret,
5550b0563631STom Van Eyck                                      operation->ctx.tls12_prf.other_secret_length);
5551b0563631STom Van Eyck         }
5552b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
5553b0563631STom Van Eyck         status = PSA_SUCCESS;
5554b0563631STom Van Eyck 
5555b0563631STom Van Eyck         /* We leave the fields Ai and output_block to be erased safely by the
5556b0563631STom Van Eyck          * mbedtls_platform_zeroize() in the end of this function. */
5557b0563631STom Van Eyck     } else
5558b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
5559b0563631STom Van Eyck         * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */
5560b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
5561b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
5562b0563631STom Van Eyck         mbedtls_platform_zeroize(operation->ctx.tls12_ecjpake_to_pms.data,
5563b0563631STom Van Eyck                                  sizeof(operation->ctx.tls12_ecjpake_to_pms.data));
5564b0563631STom Van Eyck     } else
5565b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */
5566b0563631STom Van Eyck #if defined(PSA_HAVE_SOFT_PBKDF2)
5567b0563631STom Van Eyck     if (PSA_ALG_IS_PBKDF2(kdf_alg)) {
5568b0563631STom Van Eyck         if (operation->ctx.pbkdf2.salt != NULL) {
5569b0563631STom Van Eyck             mbedtls_zeroize_and_free(operation->ctx.pbkdf2.salt,
5570b0563631STom Van Eyck                                      operation->ctx.pbkdf2.salt_length);
5571b0563631STom Van Eyck         }
5572b0563631STom Van Eyck 
5573b0563631STom Van Eyck         status = PSA_SUCCESS;
5574b0563631STom Van Eyck     } else
5575b0563631STom Van Eyck #endif /* defined(PSA_HAVE_SOFT_PBKDF2) */
5576b0563631STom Van Eyck     {
5577b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
5578b0563631STom Van Eyck     }
5579b0563631STom Van Eyck     mbedtls_platform_zeroize(operation, sizeof(*operation));
5580b0563631STom Van Eyck     return status;
5581b0563631STom Van Eyck }
5582b0563631STom Van Eyck 
5583b0563631STom Van Eyck psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation,
5584b0563631STom Van Eyck                                              size_t *capacity)
5585b0563631STom Van Eyck {
5586b0563631STom Van Eyck     if (operation->alg == 0) {
5587b0563631STom Van Eyck         /* This is a blank key derivation operation. */
5588b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
5589b0563631STom Van Eyck     }
5590b0563631STom Van Eyck 
5591b0563631STom Van Eyck     *capacity = operation->capacity;
5592b0563631STom Van Eyck     return PSA_SUCCESS;
5593b0563631STom Van Eyck }
5594b0563631STom Van Eyck 
5595b0563631STom Van Eyck psa_status_t psa_key_derivation_set_capacity(psa_key_derivation_operation_t *operation,
5596b0563631STom Van Eyck                                              size_t capacity)
5597b0563631STom Van Eyck {
5598b0563631STom Van Eyck     if (operation->alg == 0) {
5599b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
5600b0563631STom Van Eyck     }
5601b0563631STom Van Eyck     if (capacity > operation->capacity) {
5602b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
5603b0563631STom Van Eyck     }
5604b0563631STom Van Eyck     operation->capacity = capacity;
5605b0563631STom Van Eyck     return PSA_SUCCESS;
5606b0563631STom Van Eyck }
5607b0563631STom Van Eyck 
5608b0563631STom Van Eyck #if defined(BUILTIN_ALG_ANY_HKDF)
5609b0563631STom Van Eyck /* Read some bytes from an HKDF-based operation. */
5610b0563631STom Van Eyck static psa_status_t psa_key_derivation_hkdf_read(psa_hkdf_key_derivation_t *hkdf,
5611b0563631STom Van Eyck                                                  psa_algorithm_t kdf_alg,
5612b0563631STom Van Eyck                                                  uint8_t *output,
5613b0563631STom Van Eyck                                                  size_t output_length)
5614b0563631STom Van Eyck {
5615b0563631STom Van Eyck     psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);
5616b0563631STom Van Eyck     uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);
5617b0563631STom Van Eyck     size_t hmac_output_length;
5618b0563631STom Van Eyck     psa_status_t status;
5619b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
5620b0563631STom Van Eyck     const uint8_t last_block = PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) ? 0 : 0xff;
5621b0563631STom Van Eyck #else
5622b0563631STom Van Eyck     const uint8_t last_block = 0xff;
5623b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
5624b0563631STom Van Eyck 
5625b0563631STom Van Eyck     if (hkdf->state < HKDF_STATE_KEYED ||
5626b0563631STom Van Eyck         (!hkdf->info_set
5627b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
5628b0563631STom Van Eyck          && !PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)
5629b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
5630b0563631STom Van Eyck         )) {
5631b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
5632b0563631STom Van Eyck     }
5633b0563631STom Van Eyck     hkdf->state = HKDF_STATE_OUTPUT;
5634b0563631STom Van Eyck 
5635b0563631STom Van Eyck     while (output_length != 0) {
5636b0563631STom Van Eyck         /* Copy what remains of the current block */
5637b0563631STom Van Eyck         uint8_t n = hash_length - hkdf->offset_in_block;
5638b0563631STom Van Eyck         if (n > output_length) {
5639b0563631STom Van Eyck             n = (uint8_t) output_length;
5640b0563631STom Van Eyck         }
5641b0563631STom Van Eyck         memcpy(output, hkdf->output_block + hkdf->offset_in_block, n);
5642b0563631STom Van Eyck         output += n;
5643b0563631STom Van Eyck         output_length -= n;
5644b0563631STom Van Eyck         hkdf->offset_in_block += n;
5645b0563631STom Van Eyck         if (output_length == 0) {
5646b0563631STom Van Eyck             break;
5647b0563631STom Van Eyck         }
5648b0563631STom Van Eyck         /* We can't be wanting more output after the last block, otherwise
5649b0563631STom Van Eyck          * the capacity check in psa_key_derivation_output_bytes() would have
5650b0563631STom Van Eyck          * prevented this call. It could happen only if the operation
5651b0563631STom Van Eyck          * object was corrupted or if this function is called directly
5652b0563631STom Van Eyck          * inside the library. */
5653b0563631STom Van Eyck         if (hkdf->block_number == last_block) {
5654b0563631STom Van Eyck             return PSA_ERROR_BAD_STATE;
5655b0563631STom Van Eyck         }
5656b0563631STom Van Eyck 
5657b0563631STom Van Eyck         /* We need a new block */
5658b0563631STom Van Eyck         ++hkdf->block_number;
5659b0563631STom Van Eyck         hkdf->offset_in_block = 0;
5660b0563631STom Van Eyck 
5661b0563631STom Van Eyck         status = psa_key_derivation_start_hmac(&hkdf->hmac,
5662b0563631STom Van Eyck                                                hash_alg,
5663b0563631STom Van Eyck                                                hkdf->prk,
5664b0563631STom Van Eyck                                                hash_length);
5665b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
5666b0563631STom Van Eyck             return status;
5667b0563631STom Van Eyck         }
5668b0563631STom Van Eyck 
5669b0563631STom Van Eyck         if (hkdf->block_number != 1) {
5670b0563631STom Van Eyck             status = psa_mac_update(&hkdf->hmac,
5671b0563631STom Van Eyck                                     hkdf->output_block,
5672b0563631STom Van Eyck                                     hash_length);
5673b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
5674b0563631STom Van Eyck                 return status;
5675b0563631STom Van Eyck             }
5676b0563631STom Van Eyck         }
5677b0563631STom Van Eyck         status = psa_mac_update(&hkdf->hmac,
5678b0563631STom Van Eyck                                 hkdf->info,
5679b0563631STom Van Eyck                                 hkdf->info_length);
5680b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
5681b0563631STom Van Eyck             return status;
5682b0563631STom Van Eyck         }
5683b0563631STom Van Eyck         status = psa_mac_update(&hkdf->hmac,
5684b0563631STom Van Eyck                                 &hkdf->block_number, 1);
5685b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
5686b0563631STom Van Eyck             return status;
5687b0563631STom Van Eyck         }
5688b0563631STom Van Eyck         status = psa_mac_sign_finish(&hkdf->hmac,
5689b0563631STom Van Eyck                                      hkdf->output_block,
5690b0563631STom Van Eyck                                      sizeof(hkdf->output_block),
5691b0563631STom Van Eyck                                      &hmac_output_length);
5692b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
5693b0563631STom Van Eyck             return status;
5694b0563631STom Van Eyck         }
5695b0563631STom Van Eyck     }
5696b0563631STom Van Eyck 
5697b0563631STom Van Eyck     return PSA_SUCCESS;
5698b0563631STom Van Eyck }
5699b0563631STom Van Eyck #endif /* BUILTIN_ALG_ANY_HKDF */
5700b0563631STom Van Eyck 
5701b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
5702b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
5703b0563631STom Van Eyck static psa_status_t psa_key_derivation_tls12_prf_generate_next_block(
5704b0563631STom Van Eyck     psa_tls12_prf_key_derivation_t *tls12_prf,
5705b0563631STom Van Eyck     psa_algorithm_t alg)
5706b0563631STom Van Eyck {
5707b0563631STom Van Eyck     psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(alg);
5708b0563631STom Van Eyck     uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);
5709b0563631STom Van Eyck     psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT;
5710b0563631STom Van Eyck     size_t hmac_output_length;
5711b0563631STom Van Eyck     psa_status_t status, cleanup_status;
5712b0563631STom Van Eyck 
5713b0563631STom Van Eyck     /* We can't be wanting more output after block 0xff, otherwise
5714b0563631STom Van Eyck      * the capacity check in psa_key_derivation_output_bytes() would have
5715b0563631STom Van Eyck      * prevented this call. It could happen only if the operation
5716b0563631STom Van Eyck      * object was corrupted or if this function is called directly
5717b0563631STom Van Eyck      * inside the library. */
5718b0563631STom Van Eyck     if (tls12_prf->block_number == 0xff) {
5719b0563631STom Van Eyck         return PSA_ERROR_CORRUPTION_DETECTED;
5720b0563631STom Van Eyck     }
5721b0563631STom Van Eyck 
5722b0563631STom Van Eyck     /* We need a new block */
5723b0563631STom Van Eyck     ++tls12_prf->block_number;
5724b0563631STom Van Eyck     tls12_prf->left_in_block = hash_length;
5725b0563631STom Van Eyck 
5726b0563631STom Van Eyck     /* Recall the definition of the TLS-1.2-PRF from RFC 5246:
5727b0563631STom Van Eyck      *
5728b0563631STom Van Eyck      * PRF(secret, label, seed) = P_<hash>(secret, label + seed)
5729b0563631STom Van Eyck      *
5730b0563631STom Van Eyck      * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
5731b0563631STom Van Eyck      *                        HMAC_hash(secret, A(2) + seed) +
5732b0563631STom Van Eyck      *                        HMAC_hash(secret, A(3) + seed) + ...
5733b0563631STom Van Eyck      *
5734b0563631STom Van Eyck      * A(0) = seed
5735b0563631STom Van Eyck      * A(i) = HMAC_hash(secret, A(i-1))
5736b0563631STom Van Eyck      *
5737b0563631STom Van Eyck      * The `psa_tls12_prf_key_derivation` structure saves the block
5738b0563631STom Van Eyck      * `HMAC_hash(secret, A(i) + seed)` from which the output
5739b0563631STom Van Eyck      * is currently extracted as `output_block` and where i is
5740b0563631STom Van Eyck      * `block_number`.
5741b0563631STom Van Eyck      */
5742b0563631STom Van Eyck 
5743b0563631STom Van Eyck     status = psa_key_derivation_start_hmac(&hmac,
5744b0563631STom Van Eyck                                            hash_alg,
5745b0563631STom Van Eyck                                            tls12_prf->secret,
5746b0563631STom Van Eyck                                            tls12_prf->secret_length);
5747b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5748b0563631STom Van Eyck         goto cleanup;
5749b0563631STom Van Eyck     }
5750b0563631STom Van Eyck 
5751b0563631STom Van Eyck     /* Calculate A(i) where i = tls12_prf->block_number. */
5752b0563631STom Van Eyck     if (tls12_prf->block_number == 1) {
5753b0563631STom Van Eyck         /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads
5754b0563631STom Van Eyck          * the variable seed and in this instance means it in the context of the
5755b0563631STom Van Eyck          * P_hash function, where seed = label + seed.) */
5756b0563631STom Van Eyck         status = psa_mac_update(&hmac,
5757b0563631STom Van Eyck                                 tls12_prf->label,
5758b0563631STom Van Eyck                                 tls12_prf->label_length);
5759b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
5760b0563631STom Van Eyck             goto cleanup;
5761b0563631STom Van Eyck         }
5762b0563631STom Van Eyck         status = psa_mac_update(&hmac,
5763b0563631STom Van Eyck                                 tls12_prf->seed,
5764b0563631STom Van Eyck                                 tls12_prf->seed_length);
5765b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
5766b0563631STom Van Eyck             goto cleanup;
5767b0563631STom Van Eyck         }
5768b0563631STom Van Eyck     } else {
5769b0563631STom Van Eyck         /* A(i) = HMAC_hash(secret, A(i-1)) */
5770b0563631STom Van Eyck         status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length);
5771b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
5772b0563631STom Van Eyck             goto cleanup;
5773b0563631STom Van Eyck         }
5774b0563631STom Van Eyck     }
5775b0563631STom Van Eyck 
5776b0563631STom Van Eyck     status = psa_mac_sign_finish(&hmac,
5777b0563631STom Van Eyck                                  tls12_prf->Ai, hash_length,
5778b0563631STom Van Eyck                                  &hmac_output_length);
5779b0563631STom Van Eyck     if (hmac_output_length != hash_length) {
5780b0563631STom Van Eyck         status = PSA_ERROR_CORRUPTION_DETECTED;
5781b0563631STom Van Eyck     }
5782b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5783b0563631STom Van Eyck         goto cleanup;
5784b0563631STom Van Eyck     }
5785b0563631STom Van Eyck 
5786b0563631STom Van Eyck     /* Calculate HMAC_hash(secret, A(i) + label + seed). */
5787b0563631STom Van Eyck     status = psa_key_derivation_start_hmac(&hmac,
5788b0563631STom Van Eyck                                            hash_alg,
5789b0563631STom Van Eyck                                            tls12_prf->secret,
5790b0563631STom Van Eyck                                            tls12_prf->secret_length);
5791b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5792b0563631STom Van Eyck         goto cleanup;
5793b0563631STom Van Eyck     }
5794b0563631STom Van Eyck     status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length);
5795b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5796b0563631STom Van Eyck         goto cleanup;
5797b0563631STom Van Eyck     }
5798b0563631STom Van Eyck     status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length);
5799b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5800b0563631STom Van Eyck         goto cleanup;
5801b0563631STom Van Eyck     }
5802b0563631STom Van Eyck     status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length);
5803b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5804b0563631STom Van Eyck         goto cleanup;
5805b0563631STom Van Eyck     }
5806b0563631STom Van Eyck     status = psa_mac_sign_finish(&hmac,
5807b0563631STom Van Eyck                                  tls12_prf->output_block, hash_length,
5808b0563631STom Van Eyck                                  &hmac_output_length);
5809b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5810b0563631STom Van Eyck         goto cleanup;
5811b0563631STom Van Eyck     }
5812b0563631STom Van Eyck 
5813b0563631STom Van Eyck 
5814b0563631STom Van Eyck cleanup:
5815b0563631STom Van Eyck     cleanup_status = psa_mac_abort(&hmac);
5816b0563631STom Van Eyck     if (status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS) {
5817b0563631STom Van Eyck         status = cleanup_status;
5818b0563631STom Van Eyck     }
5819b0563631STom Van Eyck 
5820b0563631STom Van Eyck     return status;
5821b0563631STom Van Eyck }
5822b0563631STom Van Eyck 
5823b0563631STom Van Eyck static psa_status_t psa_key_derivation_tls12_prf_read(
5824b0563631STom Van Eyck     psa_tls12_prf_key_derivation_t *tls12_prf,
5825b0563631STom Van Eyck     psa_algorithm_t alg,
5826b0563631STom Van Eyck     uint8_t *output,
5827b0563631STom Van Eyck     size_t output_length)
5828b0563631STom Van Eyck {
5829b0563631STom Van Eyck     psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH(alg);
5830b0563631STom Van Eyck     uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);
5831b0563631STom Van Eyck     psa_status_t status;
5832b0563631STom Van Eyck     uint8_t offset, length;
5833b0563631STom Van Eyck 
5834b0563631STom Van Eyck     switch (tls12_prf->state) {
5835b0563631STom Van Eyck         case PSA_TLS12_PRF_STATE_LABEL_SET:
5836b0563631STom Van Eyck             tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT;
5837b0563631STom Van Eyck             break;
5838b0563631STom Van Eyck         case PSA_TLS12_PRF_STATE_OUTPUT:
5839b0563631STom Van Eyck             break;
5840b0563631STom Van Eyck         default:
5841b0563631STom Van Eyck             return PSA_ERROR_BAD_STATE;
5842b0563631STom Van Eyck     }
5843b0563631STom Van Eyck 
5844b0563631STom Van Eyck     while (output_length != 0) {
5845b0563631STom Van Eyck         /* Check if we have fully processed the current block. */
5846b0563631STom Van Eyck         if (tls12_prf->left_in_block == 0) {
5847b0563631STom Van Eyck             status = psa_key_derivation_tls12_prf_generate_next_block(tls12_prf,
5848b0563631STom Van Eyck                                                                       alg);
5849b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
5850b0563631STom Van Eyck                 return status;
5851b0563631STom Van Eyck             }
5852b0563631STom Van Eyck 
5853b0563631STom Van Eyck             continue;
5854b0563631STom Van Eyck         }
5855b0563631STom Van Eyck 
5856b0563631STom Van Eyck         if (tls12_prf->left_in_block > output_length) {
5857b0563631STom Van Eyck             length = (uint8_t) output_length;
5858b0563631STom Van Eyck         } else {
5859b0563631STom Van Eyck             length = tls12_prf->left_in_block;
5860b0563631STom Van Eyck         }
5861b0563631STom Van Eyck 
5862b0563631STom Van Eyck         offset = hash_length - tls12_prf->left_in_block;
5863b0563631STom Van Eyck         memcpy(output, tls12_prf->output_block + offset, length);
5864b0563631STom Van Eyck         output += length;
5865b0563631STom Van Eyck         output_length -= length;
5866b0563631STom Van Eyck         tls12_prf->left_in_block -= length;
5867b0563631STom Van Eyck     }
5868b0563631STom Van Eyck 
5869b0563631STom Van Eyck     return PSA_SUCCESS;
5870b0563631STom Van Eyck }
5871b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||
5872b0563631STom Van Eyck         * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
5873b0563631STom Van Eyck 
5874b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
5875b0563631STom Van Eyck static psa_status_t psa_key_derivation_tls12_ecjpake_to_pms_read(
5876b0563631STom Van Eyck     psa_tls12_ecjpake_to_pms_t *ecjpake,
5877b0563631STom Van Eyck     uint8_t *output,
5878b0563631STom Van Eyck     size_t output_length)
5879b0563631STom Van Eyck {
5880b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
5881b0563631STom Van Eyck     size_t output_size = 0;
5882b0563631STom Van Eyck 
5883b0563631STom Van Eyck     if (output_length != 32) {
5884b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
5885b0563631STom Van Eyck     }
5886b0563631STom Van Eyck 
5887b0563631STom Van Eyck     status = psa_hash_compute(PSA_ALG_SHA_256, ecjpake->data,
5888b0563631STom Van Eyck                               PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE, output, output_length,
5889b0563631STom Van Eyck                               &output_size);
5890b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5891b0563631STom Van Eyck         return status;
5892b0563631STom Van Eyck     }
5893b0563631STom Van Eyck 
5894b0563631STom Van Eyck     if (output_size != output_length) {
5895b0563631STom Van Eyck         return PSA_ERROR_GENERIC_ERROR;
5896b0563631STom Van Eyck     }
5897b0563631STom Van Eyck 
5898b0563631STom Van Eyck     return PSA_SUCCESS;
5899b0563631STom Van Eyck }
5900b0563631STom Van Eyck #endif
5901b0563631STom Van Eyck 
5902b0563631STom Van Eyck #if defined(PSA_HAVE_SOFT_PBKDF2)
5903b0563631STom Van Eyck static psa_status_t psa_key_derivation_pbkdf2_generate_block(
5904b0563631STom Van Eyck     psa_pbkdf2_key_derivation_t *pbkdf2,
5905b0563631STom Van Eyck     psa_algorithm_t prf_alg,
5906b0563631STom Van Eyck     uint8_t prf_output_length,
5907b0563631STom Van Eyck     psa_key_attributes_t *attributes)
5908b0563631STom Van Eyck {
5909b0563631STom Van Eyck     psa_status_t status;
5910b0563631STom Van Eyck     psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT;
5911b0563631STom Van Eyck     size_t mac_output_length;
5912b0563631STom Van Eyck     uint8_t U_i[PSA_MAC_MAX_SIZE];
5913b0563631STom Van Eyck     uint8_t *U_accumulator = pbkdf2->output_block;
5914b0563631STom Van Eyck     uint64_t i;
5915b0563631STom Van Eyck     uint8_t block_counter[4];
5916b0563631STom Van Eyck 
5917b0563631STom Van Eyck     mac_operation.is_sign = 1;
5918b0563631STom Van Eyck     mac_operation.mac_size = prf_output_length;
5919b0563631STom Van Eyck     MBEDTLS_PUT_UINT32_BE(pbkdf2->block_number, block_counter, 0);
5920b0563631STom Van Eyck 
5921b0563631STom Van Eyck     status = psa_driver_wrapper_mac_sign_setup(&mac_operation,
5922b0563631STom Van Eyck                                                attributes,
5923b0563631STom Van Eyck                                                pbkdf2->password,
5924b0563631STom Van Eyck                                                pbkdf2->password_length,
5925b0563631STom Van Eyck                                                prf_alg);
5926b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5927b0563631STom Van Eyck         goto cleanup;
5928b0563631STom Van Eyck     }
5929b0563631STom Van Eyck     status = psa_mac_update(&mac_operation, pbkdf2->salt, pbkdf2->salt_length);
5930b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5931b0563631STom Van Eyck         goto cleanup;
5932b0563631STom Van Eyck     }
5933b0563631STom Van Eyck     status = psa_mac_update(&mac_operation, block_counter, sizeof(block_counter));
5934b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5935b0563631STom Van Eyck         goto cleanup;
5936b0563631STom Van Eyck     }
5937b0563631STom Van Eyck     status = psa_mac_sign_finish(&mac_operation, U_i, sizeof(U_i),
5938b0563631STom Van Eyck                                  &mac_output_length);
5939b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
5940b0563631STom Van Eyck         goto cleanup;
5941b0563631STom Van Eyck     }
5942b0563631STom Van Eyck 
5943b0563631STom Van Eyck     if (mac_output_length != prf_output_length) {
5944b0563631STom Van Eyck         status = PSA_ERROR_CORRUPTION_DETECTED;
5945b0563631STom Van Eyck         goto cleanup;
5946b0563631STom Van Eyck     }
5947b0563631STom Van Eyck 
5948b0563631STom Van Eyck     memcpy(U_accumulator, U_i, prf_output_length);
5949b0563631STom Van Eyck 
5950b0563631STom Van Eyck     for (i = 1; i < pbkdf2->input_cost; i++) {
5951b0563631STom Van Eyck         /* We are passing prf_output_length as mac_size because the driver
5952b0563631STom Van Eyck          * function directly sets mac_output_length as mac_size upon success.
5953b0563631STom Van Eyck          * See https://github.com/Mbed-TLS/mbedtls/issues/7801 */
5954b0563631STom Van Eyck         status = psa_driver_wrapper_mac_compute(attributes,
5955b0563631STom Van Eyck                                                 pbkdf2->password,
5956b0563631STom Van Eyck                                                 pbkdf2->password_length,
5957b0563631STom Van Eyck                                                 prf_alg, U_i, prf_output_length,
5958b0563631STom Van Eyck                                                 U_i, prf_output_length,
5959b0563631STom Van Eyck                                                 &mac_output_length);
5960b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
5961b0563631STom Van Eyck             goto cleanup;
5962b0563631STom Van Eyck         }
5963b0563631STom Van Eyck 
5964b0563631STom Van Eyck         mbedtls_xor(U_accumulator, U_accumulator, U_i, prf_output_length);
5965b0563631STom Van Eyck     }
5966b0563631STom Van Eyck 
5967b0563631STom Van Eyck cleanup:
5968b0563631STom Van Eyck     /* Zeroise buffers to clear sensitive data from memory. */
5969b0563631STom Van Eyck     mbedtls_platform_zeroize(U_i, PSA_MAC_MAX_SIZE);
5970b0563631STom Van Eyck     return status;
5971b0563631STom Van Eyck }
5972b0563631STom Van Eyck 
5973b0563631STom Van Eyck static psa_status_t psa_key_derivation_pbkdf2_read(
5974b0563631STom Van Eyck     psa_pbkdf2_key_derivation_t *pbkdf2,
5975b0563631STom Van Eyck     psa_algorithm_t kdf_alg,
5976b0563631STom Van Eyck     uint8_t *output,
5977b0563631STom Van Eyck     size_t output_length)
5978b0563631STom Van Eyck {
5979b0563631STom Van Eyck     psa_status_t status;
5980b0563631STom Van Eyck     psa_algorithm_t prf_alg;
5981b0563631STom Van Eyck     uint8_t prf_output_length;
5982b0563631STom Van Eyck     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
5983b0563631STom Van Eyck     psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(pbkdf2->password_length));
5984b0563631STom Van Eyck     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
5985b0563631STom Van Eyck 
5986b0563631STom Van Eyck     if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
5987b0563631STom Van Eyck         prf_alg = PSA_ALG_HMAC(PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg));
5988b0563631STom Van Eyck         prf_output_length = PSA_HASH_LENGTH(prf_alg);
5989b0563631STom Van Eyck         psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
5990b0563631STom Van Eyck     } else if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
5991b0563631STom Van Eyck         prf_alg = PSA_ALG_CMAC;
5992b0563631STom Van Eyck         prf_output_length = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC);
5993b0563631STom Van Eyck         psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
5994b0563631STom Van Eyck     } else {
5995b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
5996b0563631STom Van Eyck     }
5997b0563631STom Van Eyck 
5998b0563631STom Van Eyck     switch (pbkdf2->state) {
5999b0563631STom Van Eyck         case PSA_PBKDF2_STATE_PASSWORD_SET:
6000b0563631STom Van Eyck             /* Initially we need a new block so bytes_used is equal to block size*/
6001b0563631STom Van Eyck             pbkdf2->bytes_used = prf_output_length;
6002b0563631STom Van Eyck             pbkdf2->state = PSA_PBKDF2_STATE_OUTPUT;
6003b0563631STom Van Eyck             break;
6004b0563631STom Van Eyck         case PSA_PBKDF2_STATE_OUTPUT:
6005b0563631STom Van Eyck             break;
6006b0563631STom Van Eyck         default:
6007b0563631STom Van Eyck             return PSA_ERROR_BAD_STATE;
6008b0563631STom Van Eyck     }
6009b0563631STom Van Eyck 
6010b0563631STom Van Eyck     while (output_length != 0) {
6011b0563631STom Van Eyck         uint8_t n = prf_output_length - pbkdf2->bytes_used;
6012b0563631STom Van Eyck         if (n > output_length) {
6013b0563631STom Van Eyck             n = (uint8_t) output_length;
6014b0563631STom Van Eyck         }
6015b0563631STom Van Eyck         memcpy(output, pbkdf2->output_block + pbkdf2->bytes_used, n);
6016b0563631STom Van Eyck         output += n;
6017b0563631STom Van Eyck         output_length -= n;
6018b0563631STom Van Eyck         pbkdf2->bytes_used += n;
6019b0563631STom Van Eyck 
6020b0563631STom Van Eyck         if (output_length == 0) {
6021b0563631STom Van Eyck             break;
6022b0563631STom Van Eyck         }
6023b0563631STom Van Eyck 
6024b0563631STom Van Eyck         /* We need a new block */
6025b0563631STom Van Eyck         pbkdf2->bytes_used = 0;
6026b0563631STom Van Eyck         pbkdf2->block_number++;
6027b0563631STom Van Eyck 
6028b0563631STom Van Eyck         status = psa_key_derivation_pbkdf2_generate_block(pbkdf2, prf_alg,
6029b0563631STom Van Eyck                                                           prf_output_length,
6030b0563631STom Van Eyck                                                           &attributes);
6031b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
6032b0563631STom Van Eyck             return status;
6033b0563631STom Van Eyck         }
6034b0563631STom Van Eyck     }
6035b0563631STom Van Eyck 
6036b0563631STom Van Eyck     return PSA_SUCCESS;
6037b0563631STom Van Eyck }
6038b0563631STom Van Eyck #endif /* PSA_HAVE_SOFT_PBKDF2 */
6039b0563631STom Van Eyck 
6040b0563631STom Van Eyck psa_status_t psa_key_derivation_output_bytes(
6041b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
6042b0563631STom Van Eyck     uint8_t *output_external,
6043b0563631STom Van Eyck     size_t output_length)
6044b0563631STom Van Eyck {
6045b0563631STom Van Eyck     psa_status_t status;
6046b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
6047b0563631STom Van Eyck 
6048b0563631STom Van Eyck     psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
6049b0563631STom Van Eyck 
6050b0563631STom Van Eyck     if (operation->alg == 0) {
6051b0563631STom Van Eyck         /* This is a blank operation. */
6052b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
6053b0563631STom Van Eyck     }
6054b0563631STom Van Eyck 
6055b0563631STom Van Eyck     if (output_length == 0 && operation->capacity == 0) {
6056b0563631STom Van Eyck         /* Edge case: this is a finished operation, and 0 bytes
6057b0563631STom Van Eyck          * were requested. The right error in this case could
6058b0563631STom Van Eyck          * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return
6059b0563631STom Van Eyck          * INSUFFICIENT_CAPACITY, which is right for a finished
6060b0563631STom Van Eyck          * operation, for consistency with the case when
6061b0563631STom Van Eyck          * output_length > 0. */
6062b0563631STom Van Eyck         return PSA_ERROR_INSUFFICIENT_DATA;
6063b0563631STom Van Eyck     }
6064b0563631STom Van Eyck 
6065b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_length, output);
6066b0563631STom Van Eyck     if (output_length > operation->capacity) {
6067b0563631STom Van Eyck         operation->capacity = 0;
6068b0563631STom Van Eyck         /* Go through the error path to wipe all confidential data now
6069b0563631STom Van Eyck          * that the operation object is useless. */
6070b0563631STom Van Eyck         status = PSA_ERROR_INSUFFICIENT_DATA;
6071b0563631STom Van Eyck         goto exit;
6072b0563631STom Van Eyck     }
6073b0563631STom Van Eyck 
6074b0563631STom Van Eyck     operation->capacity -= output_length;
6075b0563631STom Van Eyck 
6076b0563631STom Van Eyck #if defined(BUILTIN_ALG_ANY_HKDF)
6077b0563631STom Van Eyck     if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {
6078b0563631STom Van Eyck         status = psa_key_derivation_hkdf_read(&operation->ctx.hkdf, kdf_alg,
6079b0563631STom Van Eyck                                               output, output_length);
6080b0563631STom Van Eyck     } else
6081b0563631STom Van Eyck #endif /* BUILTIN_ALG_ANY_HKDF */
6082b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
6083b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
6084b0563631STom Van Eyck     if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
6085b0563631STom Van Eyck         PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
6086b0563631STom Van Eyck         status = psa_key_derivation_tls12_prf_read(&operation->ctx.tls12_prf,
6087b0563631STom Van Eyck                                                    kdf_alg, output,
6088b0563631STom Van Eyck                                                    output_length);
6089b0563631STom Van Eyck     } else
6090b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||
6091b0563631STom Van Eyck         * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
6092b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
6093b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
6094b0563631STom Van Eyck         status = psa_key_derivation_tls12_ecjpake_to_pms_read(
6095b0563631STom Van Eyck             &operation->ctx.tls12_ecjpake_to_pms, output, output_length);
6096b0563631STom Van Eyck     } else
6097b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
6098b0563631STom Van Eyck #if defined(PSA_HAVE_SOFT_PBKDF2)
6099b0563631STom Van Eyck     if (PSA_ALG_IS_PBKDF2(kdf_alg)) {
6100b0563631STom Van Eyck         status = psa_key_derivation_pbkdf2_read(&operation->ctx.pbkdf2, kdf_alg,
6101b0563631STom Van Eyck                                                 output, output_length);
6102b0563631STom Van Eyck     } else
6103b0563631STom Van Eyck #endif /* PSA_HAVE_SOFT_PBKDF2 */
6104b0563631STom Van Eyck 
6105b0563631STom Van Eyck     {
6106b0563631STom Van Eyck         (void) kdf_alg;
6107b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
6108b0563631STom Van Eyck         LOCAL_OUTPUT_FREE(output_external, output);
6109b0563631STom Van Eyck 
6110b0563631STom Van Eyck         return status;
6111b0563631STom Van Eyck     }
6112b0563631STom Van Eyck 
6113b0563631STom Van Eyck exit:
6114b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
6115b0563631STom Van Eyck         /* Preserve the algorithm upon errors, but clear all sensitive state.
6116b0563631STom Van Eyck          * This allows us to differentiate between exhausted operations and
6117b0563631STom Van Eyck          * blank operations, so we can return PSA_ERROR_BAD_STATE on blank
6118b0563631STom Van Eyck          * operations. */
6119b0563631STom Van Eyck         psa_algorithm_t alg = operation->alg;
6120b0563631STom Van Eyck         psa_key_derivation_abort(operation);
6121b0563631STom Van Eyck         operation->alg = alg;
6122b0563631STom Van Eyck         if (output != NULL) {
6123b0563631STom Van Eyck             memset(output, '!', output_length);
6124b0563631STom Van Eyck         }
6125b0563631STom Van Eyck     }
6126b0563631STom Van Eyck 
6127b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
6128b0563631STom Van Eyck     return status;
6129b0563631STom Van Eyck }
6130b0563631STom Van Eyck 
6131b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
6132b0563631STom Van Eyck static void psa_des_set_key_parity(uint8_t *data, size_t data_size)
6133b0563631STom Van Eyck {
6134b0563631STom Van Eyck     if (data_size >= 8) {
6135b0563631STom Van Eyck         mbedtls_des_key_set_parity(data);
6136b0563631STom Van Eyck     }
6137b0563631STom Van Eyck     if (data_size >= 16) {
6138b0563631STom Van Eyck         mbedtls_des_key_set_parity(data + 8);
6139b0563631STom Van Eyck     }
6140b0563631STom Van Eyck     if (data_size >= 24) {
6141b0563631STom Van Eyck         mbedtls_des_key_set_parity(data + 16);
6142b0563631STom Van Eyck     }
6143b0563631STom Van Eyck }
6144b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */
6145b0563631STom Van Eyck 
6146b0563631STom Van Eyck /*
6147b0563631STom Van Eyck  * ECC keys on a Weierstrass elliptic curve require the generation
6148b0563631STom Van Eyck  * of a private key which is an integer
6149b0563631STom Van Eyck  * in the range [1, N - 1], where N is the boundary of the private key domain:
6150b0563631STom Van Eyck  * N is the prime p for Diffie-Hellman, or the order of the
6151b0563631STom Van Eyck  * curve’s base point for ECC.
6152b0563631STom Van Eyck  *
6153b0563631STom Van Eyck  * Let m be the bit size of N, such that 2^m > N >= 2^(m-1).
6154b0563631STom Van Eyck  * This function generates the private key using the following process:
6155b0563631STom Van Eyck  *
6156b0563631STom Van Eyck  * 1. Draw a byte string of length ceiling(m/8) bytes.
6157b0563631STom Van Eyck  * 2. If m is not a multiple of 8, set the most significant
6158b0563631STom Van Eyck  *    (8 * ceiling(m/8) - m) bits of the first byte in the string to zero.
6159b0563631STom Van Eyck  * 3. Convert the string to integer k by decoding it as a big-endian byte string.
6160b0563631STom Van Eyck  * 4. If k > N - 2, discard the result and return to step 1.
6161b0563631STom Van Eyck  * 5. Output k + 1 as the private key.
6162b0563631STom Van Eyck  *
6163b0563631STom Van Eyck  * This method allows compliance to NIST standards, specifically the methods titled
6164b0563631STom Van Eyck  * Key-Pair Generation by Testing Candidates in the following publications:
6165b0563631STom Van Eyck  * - NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment
6166b0563631STom Van Eyck  *   Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.6.1.1.4 for
6167b0563631STom Van Eyck  *   Diffie-Hellman keys.
6168b0563631STom Van Eyck  *
6169b0563631STom Van Eyck  * - [SP800-56A] §5.6.1.2.2 or FIPS Publication 186-4: Digital Signature
6170b0563631STom Van Eyck  *   Standard (DSS) [FIPS186-4] §B.4.2 for elliptic curve keys.
6171b0563631STom Van Eyck  *
6172b0563631STom Van Eyck  * Note: Function allocates memory for *data buffer, so given *data should be
6173b0563631STom Van Eyck  *       always NULL.
6174b0563631STom Van Eyck  */
6175b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
6176b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
6177b0563631STom Van Eyck static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper(
6178b0563631STom Van Eyck     psa_key_slot_t *slot,
6179b0563631STom Van Eyck     size_t bits,
6180b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
6181b0563631STom Van Eyck     uint8_t **data
6182b0563631STom Van Eyck     )
6183b0563631STom Van Eyck {
6184b0563631STom Van Eyck     unsigned key_out_of_range = 1;
6185b0563631STom Van Eyck     mbedtls_mpi k;
6186b0563631STom Van Eyck     mbedtls_mpi diff_N_2;
6187b0563631STom Van Eyck     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6188b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
6189b0563631STom Van Eyck     size_t m;
6190b0563631STom Van Eyck     size_t m_bytes;
6191b0563631STom Van Eyck 
6192b0563631STom Van Eyck     mbedtls_mpi_init(&k);
6193b0563631STom Van Eyck     mbedtls_mpi_init(&diff_N_2);
6194b0563631STom Van Eyck 
6195b0563631STom Van Eyck     psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
6196b0563631STom Van Eyck         slot->attr.type);
6197b0563631STom Van Eyck     mbedtls_ecp_group_id grp_id =
6198b0563631STom Van Eyck         mbedtls_ecc_group_from_psa(curve, bits);
6199b0563631STom Van Eyck 
6200b0563631STom Van Eyck     if (grp_id == MBEDTLS_ECP_DP_NONE) {
6201b0563631STom Van Eyck         ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
6202b0563631STom Van Eyck         goto cleanup;
6203b0563631STom Van Eyck     }
6204b0563631STom Van Eyck 
6205b0563631STom Van Eyck     mbedtls_ecp_group ecp_group;
6206b0563631STom Van Eyck     mbedtls_ecp_group_init(&ecp_group);
6207b0563631STom Van Eyck 
6208b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ecp_group, grp_id));
6209b0563631STom Van Eyck 
6210b0563631STom Van Eyck     /* N is the boundary of the private key domain (ecp_group.N). */
6211b0563631STom Van Eyck     /* Let m be the bit size of N. */
6212b0563631STom Van Eyck     m = ecp_group.nbits;
6213b0563631STom Van Eyck 
6214b0563631STom Van Eyck     m_bytes = PSA_BITS_TO_BYTES(m);
6215b0563631STom Van Eyck 
6216b0563631STom Van Eyck     /* Calculate N - 2 - it will be needed later. */
6217b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&diff_N_2, &ecp_group.N, 2));
6218b0563631STom Van Eyck 
6219b0563631STom Van Eyck     /* Note: This function is always called with *data == NULL and it
6220b0563631STom Van Eyck      * allocates memory for the data buffer. */
6221b0563631STom Van Eyck     *data = mbedtls_calloc(1, m_bytes);
6222b0563631STom Van Eyck     if (*data == NULL) {
6223b0563631STom Van Eyck         ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;
6224b0563631STom Van Eyck         goto cleanup;
6225b0563631STom Van Eyck     }
6226b0563631STom Van Eyck 
6227b0563631STom Van Eyck     while (key_out_of_range) {
6228b0563631STom Van Eyck         /* 1. Draw a byte string of length ceiling(m/8) bytes. */
6229b0563631STom Van Eyck         if ((status = psa_key_derivation_output_bytes(operation, *data, m_bytes)) != 0) {
6230b0563631STom Van Eyck             goto cleanup;
6231b0563631STom Van Eyck         }
6232b0563631STom Van Eyck 
6233b0563631STom Van Eyck         /* 2. If m is not a multiple of 8 */
6234b0563631STom Van Eyck         if (m % 8 != 0) {
6235b0563631STom Van Eyck             /* Set the most significant
6236b0563631STom Van Eyck              * (8 * ceiling(m/8) - m) bits of the first byte in
6237b0563631STom Van Eyck              * the string to zero.
6238b0563631STom Van Eyck              */
6239b0563631STom Van Eyck             uint8_t clear_bit_mask = (1 << (m % 8)) - 1;
6240b0563631STom Van Eyck             (*data)[0] &= clear_bit_mask;
6241b0563631STom Van Eyck         }
6242b0563631STom Van Eyck 
6243b0563631STom Van Eyck         /* 3. Convert the string to integer k by decoding it as a
6244b0563631STom Van Eyck          *    big-endian byte string.
6245b0563631STom Van Eyck          */
6246b0563631STom Van Eyck         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&k, *data, m_bytes));
6247b0563631STom Van Eyck 
6248b0563631STom Van Eyck         /* 4. If k > N - 2, discard the result and return to step 1.
6249b0563631STom Van Eyck          *    Result of comparison is returned. When it indicates error
6250b0563631STom Van Eyck          *    then this function is called again.
6251b0563631STom Van Eyck          */
6252b0563631STom Van Eyck         MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(&diff_N_2, &k, &key_out_of_range));
6253b0563631STom Van Eyck     }
6254b0563631STom Van Eyck 
6255b0563631STom Van Eyck     /* 5. Output k + 1 as the private key. */
6256b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&k, &k, 1));
6257b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&k, *data, m_bytes));
6258b0563631STom Van Eyck cleanup:
6259b0563631STom Van Eyck     if (ret != 0) {
6260b0563631STom Van Eyck         status = mbedtls_to_psa_error(ret);
6261b0563631STom Van Eyck     }
6262b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
6263b0563631STom Van Eyck         mbedtls_free(*data);
6264b0563631STom Van Eyck         *data = NULL;
6265b0563631STom Van Eyck     }
6266b0563631STom Van Eyck     mbedtls_mpi_free(&k);
6267b0563631STom Van Eyck     mbedtls_mpi_free(&diff_N_2);
6268b0563631STom Van Eyck     return status;
6269b0563631STom Van Eyck }
6270b0563631STom Van Eyck 
6271b0563631STom Van Eyck /* ECC keys on a Montgomery elliptic curve draws a byte string whose length
6272b0563631STom Van Eyck  * is determined by the curve, and sets the mandatory bits accordingly. That is:
6273b0563631STom Van Eyck  *
6274b0563631STom Van Eyck  * - Curve25519 (PSA_ECC_FAMILY_MONTGOMERY, 255 bits):
6275b0563631STom Van Eyck  *   draw a 32-byte string and process it as specified in
6276b0563631STom Van Eyck  *   Elliptic Curves for Security [RFC7748] §5.
6277b0563631STom Van Eyck  *
6278b0563631STom Van Eyck  * - Curve448 (PSA_ECC_FAMILY_MONTGOMERY, 448 bits):
6279b0563631STom Van Eyck  *   draw a 56-byte string and process it as specified in [RFC7748] §5.
6280b0563631STom Van Eyck  *
6281b0563631STom Van Eyck  * Note: Function allocates memory for *data buffer, so given *data should be
6282b0563631STom Van Eyck  *       always NULL.
6283b0563631STom Van Eyck  */
6284b0563631STom Van Eyck 
6285b0563631STom Van Eyck static psa_status_t psa_generate_derived_ecc_key_montgomery_helper(
6286b0563631STom Van Eyck     size_t bits,
6287b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
6288b0563631STom Van Eyck     uint8_t **data
6289b0563631STom Van Eyck     )
6290b0563631STom Van Eyck {
6291b0563631STom Van Eyck     size_t output_length;
6292b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
6293b0563631STom Van Eyck 
6294b0563631STom Van Eyck     switch (bits) {
6295b0563631STom Van Eyck         case 255:
6296b0563631STom Van Eyck             output_length = 32;
6297b0563631STom Van Eyck             break;
6298b0563631STom Van Eyck         case 448:
6299b0563631STom Van Eyck             output_length = 56;
6300b0563631STom Van Eyck             break;
6301b0563631STom Van Eyck         default:
6302b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
6303b0563631STom Van Eyck             break;
6304b0563631STom Van Eyck     }
6305b0563631STom Van Eyck 
6306b0563631STom Van Eyck     *data = mbedtls_calloc(1, output_length);
6307b0563631STom Van Eyck 
6308b0563631STom Van Eyck     if (*data == NULL) {
6309b0563631STom Van Eyck         return PSA_ERROR_INSUFFICIENT_MEMORY;
6310b0563631STom Van Eyck     }
6311b0563631STom Van Eyck 
6312b0563631STom Van Eyck     status = psa_key_derivation_output_bytes(operation, *data, output_length);
6313b0563631STom Van Eyck 
6314b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
6315b0563631STom Van Eyck         return status;
6316b0563631STom Van Eyck     }
6317b0563631STom Van Eyck 
6318b0563631STom Van Eyck     switch (bits) {
6319b0563631STom Van Eyck         case 255:
6320b0563631STom Van Eyck             (*data)[0] &= 248;
6321b0563631STom Van Eyck             (*data)[31] &= 127;
6322b0563631STom Van Eyck             (*data)[31] |= 64;
6323b0563631STom Van Eyck             break;
6324b0563631STom Van Eyck         case 448:
6325b0563631STom Van Eyck             (*data)[0] &= 252;
6326b0563631STom Van Eyck             (*data)[55] |= 128;
6327b0563631STom Van Eyck             break;
6328b0563631STom Van Eyck         default:
6329b0563631STom Van Eyck             return PSA_ERROR_CORRUPTION_DETECTED;
6330b0563631STom Van Eyck             break;
6331b0563631STom Van Eyck     }
6332b0563631STom Van Eyck 
6333b0563631STom Van Eyck     return status;
6334b0563631STom Van Eyck }
6335b0563631STom Van Eyck #else /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */
6336b0563631STom Van Eyck static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper(
6337b0563631STom Van Eyck     psa_key_slot_t *slot, size_t bits,
6338b0563631STom Van Eyck     psa_key_derivation_operation_t *operation, uint8_t **data)
6339b0563631STom Van Eyck {
6340b0563631STom Van Eyck     (void) slot;
6341b0563631STom Van Eyck     (void) bits;
6342b0563631STom Van Eyck     (void) operation;
6343b0563631STom Van Eyck     (void) data;
6344b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
6345b0563631STom Van Eyck }
6346b0563631STom Van Eyck 
6347b0563631STom Van Eyck static psa_status_t psa_generate_derived_ecc_key_montgomery_helper(
6348b0563631STom Van Eyck     size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data)
6349b0563631STom Van Eyck {
6350b0563631STom Van Eyck     (void) bits;
6351b0563631STom Van Eyck     (void) operation;
6352b0563631STom Van Eyck     (void) data;
6353b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
6354b0563631STom Van Eyck }
6355b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */
6356b0563631STom Van Eyck #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE */
6357b0563631STom Van Eyck 
6358b0563631STom Van Eyck static psa_status_t psa_generate_derived_key_internal(
6359b0563631STom Van Eyck     psa_key_slot_t *slot,
6360b0563631STom Van Eyck     size_t bits,
6361b0563631STom Van Eyck     psa_key_derivation_operation_t *operation)
6362b0563631STom Van Eyck {
6363b0563631STom Van Eyck     uint8_t *data = NULL;
6364b0563631STom Van Eyck     size_t bytes = PSA_BITS_TO_BYTES(bits);
6365b0563631STom Van Eyck     size_t storage_size = bytes;
6366b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
6367b0563631STom Van Eyck 
6368b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) {
6369b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
6370b0563631STom Van Eyck     }
6371b0563631STom Van Eyck 
6372b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \
6373b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
6374b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_ECC(slot->attr.type)) {
6375b0563631STom Van Eyck         psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(slot->attr.type);
6376b0563631STom Van Eyck         if (PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) {
6377b0563631STom Van Eyck             /* Weierstrass elliptic curve */
6378b0563631STom Van Eyck             status = psa_generate_derived_ecc_key_weierstrass_helper(slot, bits, operation, &data);
6379b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
6380b0563631STom Van Eyck                 goto exit;
6381b0563631STom Van Eyck             }
6382b0563631STom Van Eyck         } else {
6383b0563631STom Van Eyck             /* Montgomery elliptic curve */
6384b0563631STom Van Eyck             status = psa_generate_derived_ecc_key_montgomery_helper(bits, operation, &data);
6385b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
6386b0563631STom Van Eyck                 goto exit;
6387b0563631STom Van Eyck             }
6388b0563631STom Van Eyck         }
6389b0563631STom Van Eyck     } else
6390b0563631STom Van Eyck #endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) ||
6391b0563631STom Van Eyck           defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) */
6392b0563631STom Van Eyck     if (key_type_is_raw_bytes(slot->attr.type)) {
6393b0563631STom Van Eyck         if (bits % 8 != 0) {
6394b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
6395b0563631STom Van Eyck         }
6396b0563631STom Van Eyck         data = mbedtls_calloc(1, bytes);
6397b0563631STom Van Eyck         if (data == NULL) {
6398b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
6399b0563631STom Van Eyck         }
6400b0563631STom Van Eyck 
6401b0563631STom Van Eyck         status = psa_key_derivation_output_bytes(operation, data, bytes);
6402b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
6403b0563631STom Van Eyck             goto exit;
6404b0563631STom Van Eyck         }
6405b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
6406b0563631STom Van Eyck         if (slot->attr.type == PSA_KEY_TYPE_DES) {
6407b0563631STom Van Eyck             psa_des_set_key_parity(data, bytes);
6408b0563631STom Van Eyck         }
6409b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) */
6410b0563631STom Van Eyck     } else {
6411b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
6412b0563631STom Van Eyck     }
6413b0563631STom Van Eyck 
6414b0563631STom Van Eyck     slot->attr.bits = (psa_key_bits_t) bits;
6415b0563631STom Van Eyck 
6416b0563631STom Van Eyck     if (psa_key_lifetime_is_external(slot->attr.lifetime)) {
6417b0563631STom Van Eyck         status = psa_driver_wrapper_get_key_buffer_size(&slot->attr,
6418b0563631STom Van Eyck                                                         &storage_size);
6419b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
6420b0563631STom Van Eyck             goto exit;
6421b0563631STom Van Eyck         }
6422b0563631STom Van Eyck     }
6423b0563631STom Van Eyck     status = psa_allocate_buffer_to_slot(slot, storage_size);
6424b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
6425b0563631STom Van Eyck         goto exit;
6426b0563631STom Van Eyck     }
6427b0563631STom Van Eyck 
6428b0563631STom Van Eyck     status = psa_driver_wrapper_import_key(&slot->attr,
6429b0563631STom Van Eyck                                            data, bytes,
6430b0563631STom Van Eyck                                            slot->key.data,
6431b0563631STom Van Eyck                                            slot->key.bytes,
6432b0563631STom Van Eyck                                            &slot->key.bytes, &bits);
6433b0563631STom Van Eyck     if (bits != slot->attr.bits) {
6434b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
6435b0563631STom Van Eyck     }
6436b0563631STom Van Eyck 
6437b0563631STom Van Eyck exit:
6438b0563631STom Van Eyck     mbedtls_free(data);
6439b0563631STom Van Eyck     return status;
6440b0563631STom Van Eyck }
6441b0563631STom Van Eyck 
6442*cb034002SJerome Forissier static const psa_custom_key_parameters_t default_custom_production =
6443*cb034002SJerome Forissier     PSA_CUSTOM_KEY_PARAMETERS_INIT;
6444b0563631STom Van Eyck 
6445*cb034002SJerome Forissier int psa_custom_key_parameters_are_default(
6446*cb034002SJerome Forissier     const psa_custom_key_parameters_t *custom,
6447*cb034002SJerome Forissier     size_t custom_data_length)
6448b0563631STom Van Eyck {
6449*cb034002SJerome Forissier     if (custom->flags != 0) {
6450b0563631STom Van Eyck         return 0;
6451b0563631STom Van Eyck     }
6452*cb034002SJerome Forissier     if (custom_data_length != 0) {
6453b0563631STom Van Eyck         return 0;
6454b0563631STom Van Eyck     }
6455b0563631STom Van Eyck     return 1;
6456b0563631STom Van Eyck }
6457b0563631STom Van Eyck 
6458*cb034002SJerome Forissier psa_status_t psa_key_derivation_output_key_custom(
6459b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
6460b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
6461*cb034002SJerome Forissier     const psa_custom_key_parameters_t *custom,
6462*cb034002SJerome Forissier     const uint8_t *custom_data,
6463*cb034002SJerome Forissier     size_t custom_data_length,
6464b0563631STom Van Eyck     mbedtls_svc_key_id_t *key)
6465b0563631STom Van Eyck {
6466b0563631STom Van Eyck     psa_status_t status;
6467b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
6468b0563631STom Van Eyck     psa_se_drv_table_entry_t *driver = NULL;
6469b0563631STom Van Eyck 
6470b0563631STom Van Eyck     *key = MBEDTLS_SVC_KEY_ID_INIT;
6471b0563631STom Van Eyck 
6472b0563631STom Van Eyck     /* Reject any attempt to create a zero-length key so that we don't
6473b0563631STom Van Eyck      * risk tripping up later, e.g. on a malloc(0) that returns NULL. */
6474b0563631STom Van Eyck     if (psa_get_key_bits(attributes) == 0) {
6475b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
6476b0563631STom Van Eyck     }
6477b0563631STom Van Eyck 
6478*cb034002SJerome Forissier     (void) custom_data;         /* We only accept 0-length data */
6479*cb034002SJerome Forissier     if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) {
6480b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
6481b0563631STom Van Eyck     }
6482b0563631STom Van Eyck 
6483b0563631STom Van Eyck     if (operation->alg == PSA_ALG_NONE) {
6484b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
6485b0563631STom Van Eyck     }
6486b0563631STom Van Eyck 
6487b0563631STom Van Eyck     if (!operation->can_output_key) {
6488b0563631STom Van Eyck         return PSA_ERROR_NOT_PERMITTED;
6489b0563631STom Van Eyck     }
6490b0563631STom Van Eyck 
6491b0563631STom Van Eyck     status = psa_start_key_creation(PSA_KEY_CREATION_DERIVE, attributes,
6492b0563631STom Van Eyck                                     &slot, &driver);
6493b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
6494b0563631STom Van Eyck     if (driver != NULL) {
6495b0563631STom Van Eyck         /* Deriving a key in a secure element is not implemented yet. */
6496b0563631STom Van Eyck         status = PSA_ERROR_NOT_SUPPORTED;
6497b0563631STom Van Eyck     }
6498b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
6499b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
6500b0563631STom Van Eyck         status = psa_generate_derived_key_internal(slot,
6501b0563631STom Van Eyck                                                    attributes->bits,
6502b0563631STom Van Eyck                                                    operation);
6503b0563631STom Van Eyck     }
6504b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
6505b0563631STom Van Eyck         status = psa_finish_key_creation(slot, driver, key);
6506b0563631STom Van Eyck     }
6507b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
6508b0563631STom Van Eyck         psa_fail_key_creation(slot, driver);
6509b0563631STom Van Eyck     }
6510b0563631STom Van Eyck 
6511b0563631STom Van Eyck     return status;
6512b0563631STom Van Eyck }
6513b0563631STom Van Eyck 
6514*cb034002SJerome Forissier psa_status_t psa_key_derivation_output_key_ext(
6515*cb034002SJerome Forissier     const psa_key_attributes_t *attributes,
6516*cb034002SJerome Forissier     psa_key_derivation_operation_t *operation,
6517*cb034002SJerome Forissier     const psa_key_production_parameters_t *params,
6518*cb034002SJerome Forissier     size_t params_data_length,
6519*cb034002SJerome Forissier     mbedtls_svc_key_id_t *key)
6520*cb034002SJerome Forissier {
6521*cb034002SJerome Forissier     return psa_key_derivation_output_key_custom(
6522*cb034002SJerome Forissier         attributes, operation,
6523*cb034002SJerome Forissier         (const psa_custom_key_parameters_t *) params,
6524*cb034002SJerome Forissier         params->data, params_data_length,
6525*cb034002SJerome Forissier         key);
6526*cb034002SJerome Forissier }
6527*cb034002SJerome Forissier 
6528b0563631STom Van Eyck psa_status_t psa_key_derivation_output_key(
6529b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
6530b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
6531b0563631STom Van Eyck     mbedtls_svc_key_id_t *key)
6532b0563631STom Van Eyck {
6533*cb034002SJerome Forissier     return psa_key_derivation_output_key_custom(attributes, operation,
6534*cb034002SJerome Forissier                                                 &default_custom_production,
6535*cb034002SJerome Forissier                                                 NULL, 0,
6536b0563631STom Van Eyck                                                 key);
6537b0563631STom Van Eyck }
6538b0563631STom Van Eyck 
6539b0563631STom Van Eyck 
6540b0563631STom Van Eyck /****************************************************************/
6541b0563631STom Van Eyck /* Key derivation */
6542b0563631STom Van Eyck /****************************************************************/
6543b0563631STom Van Eyck 
6544b0563631STom Van Eyck #if defined(AT_LEAST_ONE_BUILTIN_KDF)
6545b0563631STom Van Eyck static int is_kdf_alg_supported(psa_algorithm_t kdf_alg)
6546b0563631STom Van Eyck {
6547b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
6548b0563631STom Van Eyck     if (PSA_ALG_IS_HKDF(kdf_alg)) {
6549b0563631STom Van Eyck         return 1;
6550b0563631STom Van Eyck     }
6551b0563631STom Van Eyck #endif
6552b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
6553b0563631STom Van Eyck     if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
6554b0563631STom Van Eyck         return 1;
6555b0563631STom Van Eyck     }
6556b0563631STom Van Eyck #endif
6557b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
6558b0563631STom Van Eyck     if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
6559b0563631STom Van Eyck         return 1;
6560b0563631STom Van Eyck     }
6561b0563631STom Van Eyck #endif
6562b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)
6563b0563631STom Van Eyck     if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) {
6564b0563631STom Van Eyck         return 1;
6565b0563631STom Van Eyck     }
6566b0563631STom Van Eyck #endif
6567b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
6568b0563631STom Van Eyck     if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
6569b0563631STom Van Eyck         return 1;
6570b0563631STom Van Eyck     }
6571b0563631STom Van Eyck #endif
6572b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
6573b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
6574b0563631STom Van Eyck         return 1;
6575b0563631STom Van Eyck     }
6576b0563631STom Van Eyck #endif
6577b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
6578b0563631STom Van Eyck     if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
6579b0563631STom Van Eyck         return 1;
6580b0563631STom Van Eyck     }
6581b0563631STom Van Eyck #endif
6582b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)
6583b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
6584b0563631STom Van Eyck         return 1;
6585b0563631STom Van Eyck     }
6586b0563631STom Van Eyck #endif
6587b0563631STom Van Eyck     return 0;
6588b0563631STom Van Eyck }
6589b0563631STom Van Eyck 
6590b0563631STom Van Eyck static psa_status_t psa_hash_try_support(psa_algorithm_t alg)
6591b0563631STom Van Eyck {
6592b0563631STom Van Eyck     psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
6593b0563631STom Van Eyck     psa_status_t status = psa_hash_setup(&operation, alg);
6594b0563631STom Van Eyck     psa_hash_abort(&operation);
6595b0563631STom Van Eyck     return status;
6596b0563631STom Van Eyck }
6597b0563631STom Van Eyck 
6598b0563631STom Van Eyck static psa_status_t psa_key_derivation_set_maximum_capacity(
6599b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
6600b0563631STom Van Eyck     psa_algorithm_t kdf_alg)
6601b0563631STom Van Eyck {
6602b0563631STom Van Eyck #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
6603b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
6604b0563631STom Van Eyck         operation->capacity = PSA_HASH_LENGTH(PSA_ALG_SHA_256);
6605b0563631STom Van Eyck         return PSA_SUCCESS;
6606b0563631STom Van Eyck     }
6607b0563631STom Van Eyck #endif
6608b0563631STom Van Eyck #if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128)
6609b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
6610b0563631STom Van Eyck #if (SIZE_MAX > UINT32_MAX)
6611b0563631STom Van Eyck         operation->capacity = UINT32_MAX * (size_t) PSA_MAC_LENGTH(
6612b0563631STom Van Eyck             PSA_KEY_TYPE_AES,
6613b0563631STom Van Eyck             128U,
6614b0563631STom Van Eyck             PSA_ALG_CMAC);
6615b0563631STom Van Eyck #else
6616b0563631STom Van Eyck         operation->capacity = SIZE_MAX;
6617b0563631STom Van Eyck #endif
6618b0563631STom Van Eyck         return PSA_SUCCESS;
6619b0563631STom Van Eyck     }
6620b0563631STom Van Eyck #endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */
6621b0563631STom Van Eyck 
6622b0563631STom Van Eyck     /* After this point, if kdf_alg is not valid then value of hash_alg may be
6623b0563631STom Van Eyck      * invalid or meaningless but it does not affect this function */
6624b0563631STom Van Eyck     psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(kdf_alg);
6625b0563631STom Van Eyck     size_t hash_size = PSA_HASH_LENGTH(hash_alg);
6626b0563631STom Van Eyck     if (hash_size == 0) {
6627b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
6628b0563631STom Van Eyck     }
6629b0563631STom Van Eyck 
6630b0563631STom Van Eyck     /* Make sure that hash_alg is a supported hash algorithm. Otherwise
6631b0563631STom Van Eyck      * we might fail later, which is somewhat unfriendly and potentially
6632b0563631STom Van Eyck      * risk-prone. */
6633b0563631STom Van Eyck     psa_status_t status = psa_hash_try_support(hash_alg);
6634b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
6635b0563631STom Van Eyck         return status;
6636b0563631STom Van Eyck     }
6637b0563631STom Van Eyck 
6638b0563631STom Van Eyck #if defined(PSA_WANT_ALG_HKDF)
6639b0563631STom Van Eyck     if (PSA_ALG_IS_HKDF(kdf_alg)) {
6640b0563631STom Van Eyck         operation->capacity = 255 * hash_size;
6641b0563631STom Van Eyck     } else
6642b0563631STom Van Eyck #endif
6643b0563631STom Van Eyck #if defined(PSA_WANT_ALG_HKDF_EXTRACT)
6644b0563631STom Van Eyck     if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
6645b0563631STom Van Eyck         operation->capacity = hash_size;
6646b0563631STom Van Eyck     } else
6647b0563631STom Van Eyck #endif
6648b0563631STom Van Eyck #if defined(PSA_WANT_ALG_HKDF_EXPAND)
6649b0563631STom Van Eyck     if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
6650b0563631STom Van Eyck         operation->capacity = 255 * hash_size;
6651b0563631STom Van Eyck     } else
6652b0563631STom Van Eyck #endif
6653b0563631STom Van Eyck #if defined(PSA_WANT_ALG_TLS12_PRF)
6654b0563631STom Van Eyck     if (PSA_ALG_IS_TLS12_PRF(kdf_alg) &&
6655b0563631STom Van Eyck         (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {
6656b0563631STom Van Eyck         operation->capacity = SIZE_MAX;
6657b0563631STom Van Eyck     } else
6658b0563631STom Van Eyck #endif
6659b0563631STom Van Eyck #if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)
6660b0563631STom Van Eyck     if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg) &&
6661b0563631STom Van Eyck         (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {
6662b0563631STom Van Eyck         /* Master Secret is always 48 bytes
6663b0563631STom Van Eyck          * https://datatracker.ietf.org/doc/html/rfc5246.html#section-8.1 */
6664b0563631STom Van Eyck         operation->capacity = 48U;
6665b0563631STom Van Eyck     } else
6666b0563631STom Van Eyck #endif
6667b0563631STom Van Eyck #if defined(PSA_WANT_ALG_PBKDF2_HMAC)
6668b0563631STom Van Eyck     if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
6669b0563631STom Van Eyck #if (SIZE_MAX > UINT32_MAX)
6670b0563631STom Van Eyck         operation->capacity = UINT32_MAX * hash_size;
6671b0563631STom Van Eyck #else
6672b0563631STom Van Eyck         operation->capacity = SIZE_MAX;
6673b0563631STom Van Eyck #endif
6674b0563631STom Van Eyck     } else
6675b0563631STom Van Eyck #endif /* PSA_WANT_ALG_PBKDF2_HMAC */
6676b0563631STom Van Eyck     {
6677b0563631STom Van Eyck         (void) hash_size;
6678b0563631STom Van Eyck         status = PSA_ERROR_NOT_SUPPORTED;
6679b0563631STom Van Eyck     }
6680b0563631STom Van Eyck     return status;
6681b0563631STom Van Eyck }
6682b0563631STom Van Eyck 
6683b0563631STom Van Eyck static psa_status_t psa_key_derivation_setup_kdf(
6684b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
6685b0563631STom Van Eyck     psa_algorithm_t kdf_alg)
6686b0563631STom Van Eyck {
6687b0563631STom Van Eyck     /* Make sure that operation->ctx is properly zero-initialised. (Macro
6688b0563631STom Van Eyck      * initialisers for this union leave some bytes unspecified.) */
6689b0563631STom Van Eyck     memset(&operation->ctx, 0, sizeof(operation->ctx));
6690b0563631STom Van Eyck 
6691b0563631STom Van Eyck     /* Make sure that kdf_alg is a supported key derivation algorithm. */
6692b0563631STom Van Eyck     if (!is_kdf_alg_supported(kdf_alg)) {
6693b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
6694b0563631STom Van Eyck     }
6695b0563631STom Van Eyck 
6696b0563631STom Van Eyck     psa_status_t status = psa_key_derivation_set_maximum_capacity(operation,
6697b0563631STom Van Eyck                                                                   kdf_alg);
6698b0563631STom Van Eyck     return status;
6699b0563631STom Van Eyck }
6700b0563631STom Van Eyck 
6701b0563631STom Van Eyck static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg)
6702b0563631STom Van Eyck {
6703b0563631STom Van Eyck #if defined(PSA_WANT_ALG_ECDH)
6704b0563631STom Van Eyck     if (alg == PSA_ALG_ECDH) {
6705b0563631STom Van Eyck         return PSA_SUCCESS;
6706b0563631STom Van Eyck     }
6707b0563631STom Van Eyck #endif
6708b0563631STom Van Eyck #if defined(PSA_WANT_ALG_FFDH)
6709b0563631STom Van Eyck     if (alg == PSA_ALG_FFDH) {
6710b0563631STom Van Eyck         return PSA_SUCCESS;
6711b0563631STom Van Eyck     }
6712b0563631STom Van Eyck #endif
6713b0563631STom Van Eyck     (void) alg;
6714b0563631STom Van Eyck     return PSA_ERROR_NOT_SUPPORTED;
6715b0563631STom Van Eyck }
6716b0563631STom Van Eyck 
6717b0563631STom Van Eyck static int psa_key_derivation_allows_free_form_secret_input(
6718b0563631STom Van Eyck     psa_algorithm_t kdf_alg)
6719b0563631STom Van Eyck {
6720b0563631STom Van Eyck #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
6721b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
6722b0563631STom Van Eyck         return 0;
6723b0563631STom Van Eyck     }
6724b0563631STom Van Eyck #endif
6725b0563631STom Van Eyck     (void) kdf_alg;
6726b0563631STom Van Eyck     return 1;
6727b0563631STom Van Eyck }
6728b0563631STom Van Eyck #endif /* AT_LEAST_ONE_BUILTIN_KDF */
6729b0563631STom Van Eyck 
6730b0563631STom Van Eyck psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation,
6731b0563631STom Van Eyck                                       psa_algorithm_t alg)
6732b0563631STom Van Eyck {
6733b0563631STom Van Eyck     psa_status_t status;
6734b0563631STom Van Eyck 
6735b0563631STom Van Eyck     if (operation->alg != 0) {
6736b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
6737b0563631STom Van Eyck     }
6738b0563631STom Van Eyck 
6739b0563631STom Van Eyck     if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
6740b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
6741b0563631STom Van Eyck     } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) {
6742b0563631STom Van Eyck #if defined(AT_LEAST_ONE_BUILTIN_KDF)
6743b0563631STom Van Eyck         psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg);
6744b0563631STom Van Eyck         psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg);
6745b0563631STom Van Eyck         status = psa_key_agreement_try_support(ka_alg);
6746b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
6747b0563631STom Van Eyck             return status;
6748b0563631STom Van Eyck         }
6749b0563631STom Van Eyck         if (!psa_key_derivation_allows_free_form_secret_input(kdf_alg)) {
6750b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
6751b0563631STom Van Eyck         }
6752b0563631STom Van Eyck         status = psa_key_derivation_setup_kdf(operation, kdf_alg);
6753b0563631STom Van Eyck #else
6754b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
6755b0563631STom Van Eyck #endif /* AT_LEAST_ONE_BUILTIN_KDF */
6756b0563631STom Van Eyck     } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) {
6757b0563631STom Van Eyck #if defined(AT_LEAST_ONE_BUILTIN_KDF)
6758b0563631STom Van Eyck         status = psa_key_derivation_setup_kdf(operation, alg);
6759b0563631STom Van Eyck #else
6760b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
6761b0563631STom Van Eyck #endif /* AT_LEAST_ONE_BUILTIN_KDF */
6762b0563631STom Van Eyck     } else {
6763b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
6764b0563631STom Van Eyck     }
6765b0563631STom Van Eyck 
6766b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
6767b0563631STom Van Eyck         operation->alg = alg;
6768b0563631STom Van Eyck     }
6769b0563631STom Van Eyck     return status;
6770b0563631STom Van Eyck }
6771b0563631STom Van Eyck 
6772b0563631STom Van Eyck #if defined(BUILTIN_ALG_ANY_HKDF)
6773b0563631STom Van Eyck static psa_status_t psa_hkdf_input(psa_hkdf_key_derivation_t *hkdf,
6774b0563631STom Van Eyck                                    psa_algorithm_t kdf_alg,
6775b0563631STom Van Eyck                                    psa_key_derivation_step_t step,
6776b0563631STom Van Eyck                                    const uint8_t *data,
6777b0563631STom Van Eyck                                    size_t data_length)
6778b0563631STom Van Eyck {
6779b0563631STom Van Eyck     psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);
6780b0563631STom Van Eyck     psa_status_t status;
6781b0563631STom Van Eyck     switch (step) {
6782b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SALT:
6783b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
6784b0563631STom Van Eyck             if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
6785b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
6786b0563631STom Van Eyck             }
6787b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */
6788b0563631STom Van Eyck             if (hkdf->state != HKDF_STATE_INIT) {
6789b0563631STom Van Eyck                 return PSA_ERROR_BAD_STATE;
6790b0563631STom Van Eyck             } else {
6791b0563631STom Van Eyck                 status = psa_key_derivation_start_hmac(&hkdf->hmac,
6792b0563631STom Van Eyck                                                        hash_alg,
6793b0563631STom Van Eyck                                                        data, data_length);
6794b0563631STom Van Eyck                 if (status != PSA_SUCCESS) {
6795b0563631STom Van Eyck                     return status;
6796b0563631STom Van Eyck                 }
6797b0563631STom Van Eyck                 hkdf->state = HKDF_STATE_STARTED;
6798b0563631STom Van Eyck                 return PSA_SUCCESS;
6799b0563631STom Van Eyck             }
6800b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SECRET:
6801b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
6802b0563631STom Van Eyck             if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
6803b0563631STom Van Eyck                 /* We shouldn't be in different state as HKDF_EXPAND only allows
6804b0563631STom Van Eyck                  * two inputs: SECRET (this case) and INFO which does not modify
6805b0563631STom Van Eyck                  * the state. It could happen only if the hkdf
6806b0563631STom Van Eyck                  * object was corrupted. */
6807b0563631STom Van Eyck                 if (hkdf->state != HKDF_STATE_INIT) {
6808b0563631STom Van Eyck                     return PSA_ERROR_BAD_STATE;
6809b0563631STom Van Eyck                 }
6810b0563631STom Van Eyck 
6811b0563631STom Van Eyck                 /* Allow only input that fits expected prk size */
6812b0563631STom Van Eyck                 if (data_length != PSA_HASH_LENGTH(hash_alg)) {
6813b0563631STom Van Eyck                     return PSA_ERROR_INVALID_ARGUMENT;
6814b0563631STom Van Eyck                 }
6815b0563631STom Van Eyck 
6816b0563631STom Van Eyck                 memcpy(hkdf->prk, data, data_length);
6817b0563631STom Van Eyck             } else
6818b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */
6819b0563631STom Van Eyck             {
6820b0563631STom Van Eyck                 /* HKDF: If no salt was provided, use an empty salt.
6821b0563631STom Van Eyck                  * HKDF-EXTRACT: salt is mandatory. */
6822b0563631STom Van Eyck                 if (hkdf->state == HKDF_STATE_INIT) {
6823b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
6824b0563631STom Van Eyck                     if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
6825b0563631STom Van Eyck                         return PSA_ERROR_BAD_STATE;
6826b0563631STom Van Eyck                     }
6827b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
6828b0563631STom Van Eyck                     status = psa_key_derivation_start_hmac(&hkdf->hmac,
6829b0563631STom Van Eyck                                                            hash_alg,
6830b0563631STom Van Eyck                                                            NULL, 0);
6831b0563631STom Van Eyck                     if (status != PSA_SUCCESS) {
6832b0563631STom Van Eyck                         return status;
6833b0563631STom Van Eyck                     }
6834b0563631STom Van Eyck                     hkdf->state = HKDF_STATE_STARTED;
6835b0563631STom Van Eyck                 }
6836b0563631STom Van Eyck                 if (hkdf->state != HKDF_STATE_STARTED) {
6837b0563631STom Van Eyck                     return PSA_ERROR_BAD_STATE;
6838b0563631STom Van Eyck                 }
6839b0563631STom Van Eyck                 status = psa_mac_update(&hkdf->hmac,
6840b0563631STom Van Eyck                                         data, data_length);
6841b0563631STom Van Eyck                 if (status != PSA_SUCCESS) {
6842b0563631STom Van Eyck                     return status;
6843b0563631STom Van Eyck                 }
6844b0563631STom Van Eyck                 status = psa_mac_sign_finish(&hkdf->hmac,
6845b0563631STom Van Eyck                                              hkdf->prk,
6846b0563631STom Van Eyck                                              sizeof(hkdf->prk),
6847b0563631STom Van Eyck                                              &data_length);
6848b0563631STom Van Eyck                 if (status != PSA_SUCCESS) {
6849b0563631STom Van Eyck                     return status;
6850b0563631STom Van Eyck                 }
6851b0563631STom Van Eyck             }
6852b0563631STom Van Eyck 
6853b0563631STom Van Eyck             hkdf->state = HKDF_STATE_KEYED;
6854b0563631STom Van Eyck             hkdf->block_number = 0;
6855b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
6856b0563631STom Van Eyck             if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
6857b0563631STom Van Eyck                 /* The only block of output is the PRK. */
6858b0563631STom Van Eyck                 memcpy(hkdf->output_block, hkdf->prk, PSA_HASH_LENGTH(hash_alg));
6859b0563631STom Van Eyck                 hkdf->offset_in_block = 0;
6860b0563631STom Van Eyck             } else
6861b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
6862b0563631STom Van Eyck             {
6863b0563631STom Van Eyck                 /* Block 0 is empty, and the next block will be
6864b0563631STom Van Eyck                  * generated by psa_key_derivation_hkdf_read(). */
6865b0563631STom Van Eyck                 hkdf->offset_in_block = PSA_HASH_LENGTH(hash_alg);
6866b0563631STom Van Eyck             }
6867b0563631STom Van Eyck 
6868b0563631STom Van Eyck             return PSA_SUCCESS;
6869b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_INFO:
6870b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
6871b0563631STom Van Eyck             if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
6872b0563631STom Van Eyck                 return PSA_ERROR_INVALID_ARGUMENT;
6873b0563631STom Van Eyck             }
6874b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
6875b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
6876b0563631STom Van Eyck             if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg) &&
6877b0563631STom Van Eyck                 hkdf->state == HKDF_STATE_INIT) {
6878b0563631STom Van Eyck                 return PSA_ERROR_BAD_STATE;
6879b0563631STom Van Eyck             }
6880b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
6881b0563631STom Van Eyck             if (hkdf->state == HKDF_STATE_OUTPUT) {
6882b0563631STom Van Eyck                 return PSA_ERROR_BAD_STATE;
6883b0563631STom Van Eyck             }
6884b0563631STom Van Eyck             if (hkdf->info_set) {
6885b0563631STom Van Eyck                 return PSA_ERROR_BAD_STATE;
6886b0563631STom Van Eyck             }
6887b0563631STom Van Eyck             hkdf->info_length = data_length;
6888b0563631STom Van Eyck             if (data_length != 0) {
6889b0563631STom Van Eyck                 hkdf->info = mbedtls_calloc(1, data_length);
6890b0563631STom Van Eyck                 if (hkdf->info == NULL) {
6891b0563631STom Van Eyck                     return PSA_ERROR_INSUFFICIENT_MEMORY;
6892b0563631STom Van Eyck                 }
6893b0563631STom Van Eyck                 memcpy(hkdf->info, data, data_length);
6894b0563631STom Van Eyck             }
6895b0563631STom Van Eyck             hkdf->info_set = 1;
6896b0563631STom Van Eyck             return PSA_SUCCESS;
6897b0563631STom Van Eyck         default:
6898b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
6899b0563631STom Van Eyck     }
6900b0563631STom Van Eyck }
6901b0563631STom Van Eyck #endif /* BUILTIN_ALG_ANY_HKDF */
6902b0563631STom Van Eyck 
6903b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
6904b0563631STom Van Eyck     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
6905b0563631STom Van Eyck static psa_status_t psa_tls12_prf_set_seed(psa_tls12_prf_key_derivation_t *prf,
6906b0563631STom Van Eyck                                            const uint8_t *data,
6907b0563631STom Van Eyck                                            size_t data_length)
6908b0563631STom Van Eyck {
6909b0563631STom Van Eyck     if (prf->state != PSA_TLS12_PRF_STATE_INIT) {
6910b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
6911b0563631STom Van Eyck     }
6912b0563631STom Van Eyck 
6913b0563631STom Van Eyck     if (data_length != 0) {
6914b0563631STom Van Eyck         prf->seed = mbedtls_calloc(1, data_length);
6915b0563631STom Van Eyck         if (prf->seed == NULL) {
6916b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
6917b0563631STom Van Eyck         }
6918b0563631STom Van Eyck 
6919b0563631STom Van Eyck         memcpy(prf->seed, data, data_length);
6920b0563631STom Van Eyck         prf->seed_length = data_length;
6921b0563631STom Van Eyck     }
6922b0563631STom Van Eyck 
6923b0563631STom Van Eyck     prf->state = PSA_TLS12_PRF_STATE_SEED_SET;
6924b0563631STom Van Eyck 
6925b0563631STom Van Eyck     return PSA_SUCCESS;
6926b0563631STom Van Eyck }
6927b0563631STom Van Eyck 
6928b0563631STom Van Eyck static psa_status_t psa_tls12_prf_set_key(psa_tls12_prf_key_derivation_t *prf,
6929b0563631STom Van Eyck                                           const uint8_t *data,
6930b0563631STom Van Eyck                                           size_t data_length)
6931b0563631STom Van Eyck {
6932b0563631STom Van Eyck     if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET &&
6933b0563631STom Van Eyck         prf->state != PSA_TLS12_PRF_STATE_OTHER_KEY_SET) {
6934b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
6935b0563631STom Van Eyck     }
6936b0563631STom Van Eyck 
6937b0563631STom Van Eyck     if (data_length != 0) {
6938b0563631STom Van Eyck         prf->secret = mbedtls_calloc(1, data_length);
6939b0563631STom Van Eyck         if (prf->secret == NULL) {
6940b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
6941b0563631STom Van Eyck         }
6942b0563631STom Van Eyck 
6943b0563631STom Van Eyck         memcpy(prf->secret, data, data_length);
6944b0563631STom Van Eyck         prf->secret_length = data_length;
6945b0563631STom Van Eyck     }
6946b0563631STom Van Eyck 
6947b0563631STom Van Eyck     prf->state = PSA_TLS12_PRF_STATE_KEY_SET;
6948b0563631STom Van Eyck 
6949b0563631STom Van Eyck     return PSA_SUCCESS;
6950b0563631STom Van Eyck }
6951b0563631STom Van Eyck 
6952b0563631STom Van Eyck static psa_status_t psa_tls12_prf_set_label(psa_tls12_prf_key_derivation_t *prf,
6953b0563631STom Van Eyck                                             const uint8_t *data,
6954b0563631STom Van Eyck                                             size_t data_length)
6955b0563631STom Van Eyck {
6956b0563631STom Van Eyck     if (prf->state != PSA_TLS12_PRF_STATE_KEY_SET) {
6957b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
6958b0563631STom Van Eyck     }
6959b0563631STom Van Eyck 
6960b0563631STom Van Eyck     if (data_length != 0) {
6961b0563631STom Van Eyck         prf->label = mbedtls_calloc(1, data_length);
6962b0563631STom Van Eyck         if (prf->label == NULL) {
6963b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
6964b0563631STom Van Eyck         }
6965b0563631STom Van Eyck 
6966b0563631STom Van Eyck         memcpy(prf->label, data, data_length);
6967b0563631STom Van Eyck         prf->label_length = data_length;
6968b0563631STom Van Eyck     }
6969b0563631STom Van Eyck 
6970b0563631STom Van Eyck     prf->state = PSA_TLS12_PRF_STATE_LABEL_SET;
6971b0563631STom Van Eyck 
6972b0563631STom Van Eyck     return PSA_SUCCESS;
6973b0563631STom Van Eyck }
6974b0563631STom Van Eyck 
6975b0563631STom Van Eyck static psa_status_t psa_tls12_prf_input(psa_tls12_prf_key_derivation_t *prf,
6976b0563631STom Van Eyck                                         psa_key_derivation_step_t step,
6977b0563631STom Van Eyck                                         const uint8_t *data,
6978b0563631STom Van Eyck                                         size_t data_length)
6979b0563631STom Van Eyck {
6980b0563631STom Van Eyck     switch (step) {
6981b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SEED:
6982b0563631STom Van Eyck             return psa_tls12_prf_set_seed(prf, data, data_length);
6983b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SECRET:
6984b0563631STom Van Eyck             return psa_tls12_prf_set_key(prf, data, data_length);
6985b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_LABEL:
6986b0563631STom Van Eyck             return psa_tls12_prf_set_label(prf, data, data_length);
6987b0563631STom Van Eyck         default:
6988b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
6989b0563631STom Van Eyck     }
6990b0563631STom Van Eyck }
6991b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
6992b0563631STom Van Eyck         * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
6993b0563631STom Van Eyck 
6994b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
6995b0563631STom Van Eyck static psa_status_t psa_tls12_prf_psk_to_ms_set_key(
6996b0563631STom Van Eyck     psa_tls12_prf_key_derivation_t *prf,
6997b0563631STom Van Eyck     const uint8_t *data,
6998b0563631STom Van Eyck     size_t data_length)
6999b0563631STom Van Eyck {
7000b0563631STom Van Eyck     psa_status_t status;
7001b0563631STom Van Eyck     const size_t pms_len = (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET ?
7002b0563631STom Van Eyck                             4 + data_length + prf->other_secret_length :
7003b0563631STom Van Eyck                             4 + 2 * data_length);
7004b0563631STom Van Eyck 
7005b0563631STom Van Eyck     if (data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) {
7006b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7007b0563631STom Van Eyck     }
7008b0563631STom Van Eyck 
7009b0563631STom Van Eyck     uint8_t *pms = mbedtls_calloc(1, pms_len);
7010b0563631STom Van Eyck     if (pms == NULL) {
7011b0563631STom Van Eyck         return PSA_ERROR_INSUFFICIENT_MEMORY;
7012b0563631STom Van Eyck     }
7013b0563631STom Van Eyck     uint8_t *cur = pms;
7014b0563631STom Van Eyck 
7015b0563631STom Van Eyck     /* pure-PSK:
7016b0563631STom Van Eyck      * Quoting RFC 4279, Section 2:
7017b0563631STom Van Eyck      *
7018b0563631STom Van Eyck      * The premaster secret is formed as follows: if the PSK is N octets
7019b0563631STom Van Eyck      * long, concatenate a uint16 with the value N, N zero octets, a second
7020b0563631STom Van Eyck      * uint16 with the value N, and the PSK itself.
7021b0563631STom Van Eyck      *
7022b0563631STom Van Eyck      * mixed-PSK:
7023b0563631STom Van Eyck      * In a DHE-PSK, RSA-PSK, ECDHE-PSK the premaster secret is formed as
7024b0563631STom Van Eyck      * follows: concatenate a uint16 with the length of the other secret,
7025b0563631STom Van Eyck      * the other secret itself, uint16 with the length of PSK, and the
7026b0563631STom Van Eyck      * PSK itself.
7027b0563631STom Van Eyck      * For details please check:
7028b0563631STom Van Eyck      * - RFC 4279, Section 4 for the definition of RSA-PSK,
7029b0563631STom Van Eyck      * - RFC 4279, Section 3 for the definition of DHE-PSK,
7030b0563631STom Van Eyck      * - RFC 5489 for the definition of ECDHE-PSK.
7031b0563631STom Van Eyck      */
7032b0563631STom Van Eyck 
7033b0563631STom Van Eyck     if (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET) {
7034b0563631STom Van Eyck         *cur++ = MBEDTLS_BYTE_1(prf->other_secret_length);
7035b0563631STom Van Eyck         *cur++ = MBEDTLS_BYTE_0(prf->other_secret_length);
7036b0563631STom Van Eyck         if (prf->other_secret_length != 0) {
7037b0563631STom Van Eyck             memcpy(cur, prf->other_secret, prf->other_secret_length);
7038b0563631STom Van Eyck             mbedtls_platform_zeroize(prf->other_secret, prf->other_secret_length);
7039b0563631STom Van Eyck             cur += prf->other_secret_length;
7040b0563631STom Van Eyck         }
7041b0563631STom Van Eyck     } else {
7042b0563631STom Van Eyck         *cur++ = MBEDTLS_BYTE_1(data_length);
7043b0563631STom Van Eyck         *cur++ = MBEDTLS_BYTE_0(data_length);
7044b0563631STom Van Eyck         memset(cur, 0, data_length);
7045b0563631STom Van Eyck         cur += data_length;
7046b0563631STom Van Eyck     }
7047b0563631STom Van Eyck 
7048b0563631STom Van Eyck     *cur++ = MBEDTLS_BYTE_1(data_length);
7049b0563631STom Van Eyck     *cur++ = MBEDTLS_BYTE_0(data_length);
7050b0563631STom Van Eyck     memcpy(cur, data, data_length);
7051b0563631STom Van Eyck     cur += data_length;
7052b0563631STom Van Eyck 
7053b0563631STom Van Eyck     status = psa_tls12_prf_set_key(prf, pms, (size_t) (cur - pms));
7054b0563631STom Van Eyck 
7055b0563631STom Van Eyck     mbedtls_zeroize_and_free(pms, pms_len);
7056b0563631STom Van Eyck     return status;
7057b0563631STom Van Eyck }
7058b0563631STom Van Eyck 
7059b0563631STom Van Eyck static psa_status_t psa_tls12_prf_psk_to_ms_set_other_key(
7060b0563631STom Van Eyck     psa_tls12_prf_key_derivation_t *prf,
7061b0563631STom Van Eyck     const uint8_t *data,
7062b0563631STom Van Eyck     size_t data_length)
7063b0563631STom Van Eyck {
7064b0563631STom Van Eyck     if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET) {
7065b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
7066b0563631STom Van Eyck     }
7067b0563631STom Van Eyck 
7068b0563631STom Van Eyck     if (data_length != 0) {
7069b0563631STom Van Eyck         prf->other_secret = mbedtls_calloc(1, data_length);
7070b0563631STom Van Eyck         if (prf->other_secret == NULL) {
7071b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
7072b0563631STom Van Eyck         }
7073b0563631STom Van Eyck 
7074b0563631STom Van Eyck         memcpy(prf->other_secret, data, data_length);
7075b0563631STom Van Eyck         prf->other_secret_length = data_length;
7076b0563631STom Van Eyck     } else {
7077b0563631STom Van Eyck         prf->other_secret_length = 0;
7078b0563631STom Van Eyck     }
7079b0563631STom Van Eyck 
7080b0563631STom Van Eyck     prf->state = PSA_TLS12_PRF_STATE_OTHER_KEY_SET;
7081b0563631STom Van Eyck 
7082b0563631STom Van Eyck     return PSA_SUCCESS;
7083b0563631STom Van Eyck }
7084b0563631STom Van Eyck 
7085b0563631STom Van Eyck static psa_status_t psa_tls12_prf_psk_to_ms_input(
7086b0563631STom Van Eyck     psa_tls12_prf_key_derivation_t *prf,
7087b0563631STom Van Eyck     psa_key_derivation_step_t step,
7088b0563631STom Van Eyck     const uint8_t *data,
7089b0563631STom Van Eyck     size_t data_length)
7090b0563631STom Van Eyck {
7091b0563631STom Van Eyck     switch (step) {
7092b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SECRET:
7093b0563631STom Van Eyck             return psa_tls12_prf_psk_to_ms_set_key(prf,
7094b0563631STom Van Eyck                                                    data, data_length);
7095b0563631STom Van Eyck             break;
7096b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET:
7097b0563631STom Van Eyck             return psa_tls12_prf_psk_to_ms_set_other_key(prf,
7098b0563631STom Van Eyck                                                          data,
7099b0563631STom Van Eyck                                                          data_length);
7100b0563631STom Van Eyck             break;
7101b0563631STom Van Eyck         default:
7102b0563631STom Van Eyck             return psa_tls12_prf_input(prf, step, data, data_length);
7103b0563631STom Van Eyck             break;
7104b0563631STom Van Eyck 
7105b0563631STom Van Eyck     }
7106b0563631STom Van Eyck }
7107b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
7108b0563631STom Van Eyck 
7109b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
7110b0563631STom Van Eyck static psa_status_t psa_tls12_ecjpake_to_pms_input(
7111b0563631STom Van Eyck     psa_tls12_ecjpake_to_pms_t *ecjpake,
7112b0563631STom Van Eyck     psa_key_derivation_step_t step,
7113b0563631STom Van Eyck     const uint8_t *data,
7114b0563631STom Van Eyck     size_t data_length)
7115b0563631STom Van Eyck {
7116b0563631STom Van Eyck     if (data_length != PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE ||
7117b0563631STom Van Eyck         step != PSA_KEY_DERIVATION_INPUT_SECRET) {
7118b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7119b0563631STom Van Eyck     }
7120b0563631STom Van Eyck 
7121b0563631STom Van Eyck     /* Check if the passed point is in an uncompressed form */
7122b0563631STom Van Eyck     if (data[0] != 0x04) {
7123b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7124b0563631STom Van Eyck     }
7125b0563631STom Van Eyck 
7126b0563631STom Van Eyck     /* Only K.X has to be extracted - bytes 1 to 32 inclusive. */
7127b0563631STom Van Eyck     memcpy(ecjpake->data, data + 1, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE);
7128b0563631STom Van Eyck 
7129b0563631STom Van Eyck     return PSA_SUCCESS;
7130b0563631STom Van Eyck }
7131b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
7132b0563631STom Van Eyck 
7133b0563631STom Van Eyck #if defined(PSA_HAVE_SOFT_PBKDF2)
7134b0563631STom Van Eyck static psa_status_t psa_pbkdf2_set_input_cost(
7135b0563631STom Van Eyck     psa_pbkdf2_key_derivation_t *pbkdf2,
7136b0563631STom Van Eyck     psa_key_derivation_step_t step,
7137b0563631STom Van Eyck     uint64_t data)
7138b0563631STom Van Eyck {
7139b0563631STom Van Eyck     if (step != PSA_KEY_DERIVATION_INPUT_COST) {
7140b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7141b0563631STom Van Eyck     }
7142b0563631STom Van Eyck 
7143b0563631STom Van Eyck     if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) {
7144b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
7145b0563631STom Van Eyck     }
7146b0563631STom Van Eyck 
7147b0563631STom Van Eyck     if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) {
7148b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
7149b0563631STom Van Eyck     }
7150b0563631STom Van Eyck 
7151b0563631STom Van Eyck     if (data == 0) {
7152b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7153b0563631STom Van Eyck     }
7154b0563631STom Van Eyck 
7155b0563631STom Van Eyck     pbkdf2->input_cost = data;
7156b0563631STom Van Eyck     pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET;
7157b0563631STom Van Eyck 
7158b0563631STom Van Eyck     return PSA_SUCCESS;
7159b0563631STom Van Eyck }
7160b0563631STom Van Eyck 
7161b0563631STom Van Eyck static psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2,
7162b0563631STom Van Eyck                                         const uint8_t *data,
7163b0563631STom Van Eyck                                         size_t data_length)
7164b0563631STom Van Eyck {
7165b0563631STom Van Eyck     if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) {
7166b0563631STom Van Eyck         pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET;
7167b0563631STom Van Eyck     } else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) {
7168b0563631STom Van Eyck         /* Appending to existing salt. No state change. */
7169b0563631STom Van Eyck     } else {
7170b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
7171b0563631STom Van Eyck     }
7172b0563631STom Van Eyck 
7173b0563631STom Van Eyck     if (data_length == 0) {
7174b0563631STom Van Eyck         /* Appending an empty string, nothing to do. */
7175b0563631STom Van Eyck     } else {
7176b0563631STom Van Eyck         uint8_t *next_salt;
7177b0563631STom Van Eyck 
7178b0563631STom Van Eyck         next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length);
7179b0563631STom Van Eyck         if (next_salt == NULL) {
7180b0563631STom Van Eyck             return PSA_ERROR_INSUFFICIENT_MEMORY;
7181b0563631STom Van Eyck         }
7182b0563631STom Van Eyck 
7183b0563631STom Van Eyck         if (pbkdf2->salt_length != 0) {
7184b0563631STom Van Eyck             memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length);
7185b0563631STom Van Eyck         }
7186b0563631STom Van Eyck         memcpy(next_salt + pbkdf2->salt_length, data, data_length);
7187b0563631STom Van Eyck         pbkdf2->salt_length += data_length;
7188b0563631STom Van Eyck         mbedtls_free(pbkdf2->salt);
7189b0563631STom Van Eyck         pbkdf2->salt = next_salt;
7190b0563631STom Van Eyck     }
7191b0563631STom Van Eyck     return PSA_SUCCESS;
7192b0563631STom Van Eyck }
7193b0563631STom Van Eyck 
7194b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
7195b0563631STom Van Eyck static psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg,
7196b0563631STom Van Eyck                                                  const uint8_t *input,
7197b0563631STom Van Eyck                                                  size_t input_len,
7198b0563631STom Van Eyck                                                  uint8_t *output,
7199b0563631STom Van Eyck                                                  size_t *output_len)
7200b0563631STom Van Eyck {
7201b0563631STom Van Eyck     psa_status_t status = PSA_SUCCESS;
7202b0563631STom Van Eyck     if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) {
7203b0563631STom Van Eyck         return psa_hash_compute(hash_alg, input, input_len, output,
7204b0563631STom Van Eyck                                 PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len);
7205b0563631STom Van Eyck     } else if (input_len > 0) {
7206b0563631STom Van Eyck         memcpy(output, input, input_len);
7207b0563631STom Van Eyck     }
7208b0563631STom Van Eyck     *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg);
7209b0563631STom Van Eyck     return status;
7210b0563631STom Van Eyck }
7211b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
7212b0563631STom Van Eyck 
7213b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)
7214b0563631STom Van Eyck static psa_status_t psa_pbkdf2_cmac_set_password(const uint8_t *input,
7215b0563631STom Van Eyck                                                  size_t input_len,
7216b0563631STom Van Eyck                                                  uint8_t *output,
7217b0563631STom Van Eyck                                                  size_t *output_len)
7218b0563631STom Van Eyck {
7219b0563631STom Van Eyck     psa_status_t status = PSA_SUCCESS;
7220b0563631STom Van Eyck     if (input_len != PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC)) {
7221b0563631STom Van Eyck         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
7222b0563631STom Van Eyck         uint8_t zeros[16] = { 0 };
7223b0563631STom Van Eyck         psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
7224b0563631STom Van Eyck         psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(zeros)));
7225b0563631STom Van Eyck         psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
7226b0563631STom Van Eyck         /* Passing PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC) as
7227b0563631STom Van Eyck          * mac_size as the driver function sets mac_output_length = mac_size
7228b0563631STom Van Eyck          * on success. See https://github.com/Mbed-TLS/mbedtls/issues/7801 */
7229b0563631STom Van Eyck         status = psa_driver_wrapper_mac_compute(&attributes,
7230b0563631STom Van Eyck                                                 zeros, sizeof(zeros),
7231b0563631STom Van Eyck                                                 PSA_ALG_CMAC, input, input_len,
7232b0563631STom Van Eyck                                                 output,
7233b0563631STom Van Eyck                                                 PSA_MAC_LENGTH(PSA_KEY_TYPE_AES,
7234b0563631STom Van Eyck                                                                128U,
7235b0563631STom Van Eyck                                                                PSA_ALG_CMAC),
7236b0563631STom Van Eyck                                                 output_len);
7237b0563631STom Van Eyck     } else {
7238b0563631STom Van Eyck         memcpy(output, input, input_len);
7239b0563631STom Van Eyck         *output_len = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC);
7240b0563631STom Van Eyck     }
7241b0563631STom Van Eyck     return status;
7242b0563631STom Van Eyck }
7243b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */
7244b0563631STom Van Eyck 
7245b0563631STom Van Eyck static psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2,
7246b0563631STom Van Eyck                                             psa_algorithm_t kdf_alg,
7247b0563631STom Van Eyck                                             const uint8_t *data,
7248b0563631STom Van Eyck                                             size_t data_length)
7249b0563631STom Van Eyck {
7250b0563631STom Van Eyck     psa_status_t status = PSA_SUCCESS;
7251b0563631STom Van Eyck     if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) {
7252b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
7253b0563631STom Van Eyck     }
7254b0563631STom Van Eyck 
7255b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
7256b0563631STom Van Eyck     if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
7257b0563631STom Van Eyck         psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg);
7258b0563631STom Van Eyck         status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length,
7259b0563631STom Van Eyck                                               pbkdf2->password,
7260b0563631STom Van Eyck                                               &pbkdf2->password_length);
7261b0563631STom Van Eyck     } else
7262b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
7263b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)
7264b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
7265b0563631STom Van Eyck         status = psa_pbkdf2_cmac_set_password(data, data_length,
7266b0563631STom Van Eyck                                               pbkdf2->password,
7267b0563631STom Van Eyck                                               &pbkdf2->password_length);
7268b0563631STom Van Eyck     } else
7269b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */
7270b0563631STom Van Eyck     {
7271b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7272b0563631STom Van Eyck     }
7273b0563631STom Van Eyck 
7274b0563631STom Van Eyck     pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET;
7275b0563631STom Van Eyck 
7276b0563631STom Van Eyck     return status;
7277b0563631STom Van Eyck }
7278b0563631STom Van Eyck 
7279b0563631STom Van Eyck static psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2,
7280b0563631STom Van Eyck                                      psa_algorithm_t kdf_alg,
7281b0563631STom Van Eyck                                      psa_key_derivation_step_t step,
7282b0563631STom Van Eyck                                      const uint8_t *data,
7283b0563631STom Van Eyck                                      size_t data_length)
7284b0563631STom Van Eyck {
7285b0563631STom Van Eyck     switch (step) {
7286b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SALT:
7287b0563631STom Van Eyck             return psa_pbkdf2_set_salt(pbkdf2, data, data_length);
7288b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_PASSWORD:
7289b0563631STom Van Eyck             return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length);
7290b0563631STom Van Eyck         default:
7291b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
7292b0563631STom Van Eyck     }
7293b0563631STom Van Eyck }
7294b0563631STom Van Eyck #endif /* PSA_HAVE_SOFT_PBKDF2 */
7295b0563631STom Van Eyck 
7296b0563631STom Van Eyck /** Check whether the given key type is acceptable for the given
7297b0563631STom Van Eyck  * input step of a key derivation.
7298b0563631STom Van Eyck  *
7299b0563631STom Van Eyck  * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE.
7300b0563631STom Van Eyck  * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA.
7301b0563631STom Van Eyck  * Both secret and non-secret inputs can alternatively have the type
7302b0563631STom Van Eyck  * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning
7303b0563631STom Van Eyck  * that the input was passed as a buffer rather than via a key object.
7304b0563631STom Van Eyck  */
7305b0563631STom Van Eyck static int psa_key_derivation_check_input_type(
7306b0563631STom Van Eyck     psa_key_derivation_step_t step,
7307b0563631STom Van Eyck     psa_key_type_t key_type)
7308b0563631STom Van Eyck {
7309b0563631STom Van Eyck     switch (step) {
7310b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SECRET:
7311b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_DERIVE) {
7312b0563631STom Van Eyck                 return PSA_SUCCESS;
7313b0563631STom Van Eyck             }
7314b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_NONE) {
7315b0563631STom Van Eyck                 return PSA_SUCCESS;
7316b0563631STom Van Eyck             }
7317b0563631STom Van Eyck             break;
7318b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET:
7319b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_DERIVE) {
7320b0563631STom Van Eyck                 return PSA_SUCCESS;
7321b0563631STom Van Eyck             }
7322b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_NONE) {
7323b0563631STom Van Eyck                 return PSA_SUCCESS;
7324b0563631STom Van Eyck             }
7325b0563631STom Van Eyck             break;
7326b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_LABEL:
7327b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SALT:
7328b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_INFO:
7329b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_SEED:
7330b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_RAW_DATA) {
7331b0563631STom Van Eyck                 return PSA_SUCCESS;
7332b0563631STom Van Eyck             }
7333b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_NONE) {
7334b0563631STom Van Eyck                 return PSA_SUCCESS;
7335b0563631STom Van Eyck             }
7336b0563631STom Van Eyck             break;
7337b0563631STom Van Eyck         case PSA_KEY_DERIVATION_INPUT_PASSWORD:
7338b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_PASSWORD) {
7339b0563631STom Van Eyck                 return PSA_SUCCESS;
7340b0563631STom Van Eyck             }
7341b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_DERIVE) {
7342b0563631STom Van Eyck                 return PSA_SUCCESS;
7343b0563631STom Van Eyck             }
7344b0563631STom Van Eyck             if (key_type == PSA_KEY_TYPE_NONE) {
7345b0563631STom Van Eyck                 return PSA_SUCCESS;
7346b0563631STom Van Eyck             }
7347b0563631STom Van Eyck             break;
7348b0563631STom Van Eyck     }
7349b0563631STom Van Eyck     return PSA_ERROR_INVALID_ARGUMENT;
7350b0563631STom Van Eyck }
7351b0563631STom Van Eyck 
7352b0563631STom Van Eyck static psa_status_t psa_key_derivation_input_internal(
7353b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
7354b0563631STom Van Eyck     psa_key_derivation_step_t step,
7355b0563631STom Van Eyck     psa_key_type_t key_type,
7356b0563631STom Van Eyck     const uint8_t *data,
7357b0563631STom Van Eyck     size_t data_length)
7358b0563631STom Van Eyck {
7359b0563631STom Van Eyck     psa_status_t status;
7360b0563631STom Van Eyck     psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
7361b0563631STom Van Eyck 
7362b0563631STom Van Eyck     status = psa_key_derivation_check_input_type(step, key_type);
7363b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
7364b0563631STom Van Eyck         goto exit;
7365b0563631STom Van Eyck     }
7366b0563631STom Van Eyck 
7367b0563631STom Van Eyck #if defined(BUILTIN_ALG_ANY_HKDF)
7368b0563631STom Van Eyck     if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {
7369b0563631STom Van Eyck         status = psa_hkdf_input(&operation->ctx.hkdf, kdf_alg,
7370b0563631STom Van Eyck                                 step, data, data_length);
7371b0563631STom Van Eyck     } else
7372b0563631STom Van Eyck #endif /* BUILTIN_ALG_ANY_HKDF */
7373b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)
7374b0563631STom Van Eyck     if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) {
7375b0563631STom Van Eyck         status = psa_tls12_prf_input(&operation->ctx.tls12_prf,
7376b0563631STom Van Eyck                                      step, data, data_length);
7377b0563631STom Van Eyck     } else
7378b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */
7379b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
7380b0563631STom Van Eyck     if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
7381b0563631STom Van Eyck         status = psa_tls12_prf_psk_to_ms_input(&operation->ctx.tls12_prf,
7382b0563631STom Van Eyck                                                step, data, data_length);
7383b0563631STom Van Eyck     } else
7384b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
7385b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
7386b0563631STom Van Eyck     if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
7387b0563631STom Van Eyck         status = psa_tls12_ecjpake_to_pms_input(
7388b0563631STom Van Eyck             &operation->ctx.tls12_ecjpake_to_pms, step, data, data_length);
7389b0563631STom Van Eyck     } else
7390b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
7391b0563631STom Van Eyck #if defined(PSA_HAVE_SOFT_PBKDF2)
7392b0563631STom Van Eyck     if (PSA_ALG_IS_PBKDF2(kdf_alg)) {
7393b0563631STom Van Eyck         status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg,
7394b0563631STom Van Eyck                                   step, data, data_length);
7395b0563631STom Van Eyck     } else
7396b0563631STom Van Eyck #endif /* PSA_HAVE_SOFT_PBKDF2 */
7397b0563631STom Van Eyck     {
7398b0563631STom Van Eyck         /* This can't happen unless the operation object was not initialized */
7399b0563631STom Van Eyck         (void) data;
7400b0563631STom Van Eyck         (void) data_length;
7401b0563631STom Van Eyck         (void) kdf_alg;
7402b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
7403b0563631STom Van Eyck     }
7404b0563631STom Van Eyck 
7405b0563631STom Van Eyck exit:
7406b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
7407b0563631STom Van Eyck         psa_key_derivation_abort(operation);
7408b0563631STom Van Eyck     }
7409b0563631STom Van Eyck     return status;
7410b0563631STom Van Eyck }
7411b0563631STom Van Eyck 
7412b0563631STom Van Eyck static psa_status_t psa_key_derivation_input_integer_internal(
7413b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
7414b0563631STom Van Eyck     psa_key_derivation_step_t step,
7415b0563631STom Van Eyck     uint64_t value)
7416b0563631STom Van Eyck {
7417b0563631STom Van Eyck     psa_status_t status;
7418b0563631STom Van Eyck     psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
7419b0563631STom Van Eyck 
7420b0563631STom Van Eyck #if defined(PSA_HAVE_SOFT_PBKDF2)
7421b0563631STom Van Eyck     if (PSA_ALG_IS_PBKDF2(kdf_alg)) {
7422b0563631STom Van Eyck         status = psa_pbkdf2_set_input_cost(
7423b0563631STom Van Eyck             &operation->ctx.pbkdf2, step, value);
7424b0563631STom Van Eyck     } else
7425b0563631STom Van Eyck #endif /* PSA_HAVE_SOFT_PBKDF2 */
7426b0563631STom Van Eyck     {
7427b0563631STom Van Eyck         (void) step;
7428b0563631STom Van Eyck         (void) value;
7429b0563631STom Van Eyck         (void) kdf_alg;
7430b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
7431b0563631STom Van Eyck     }
7432b0563631STom Van Eyck 
7433b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
7434b0563631STom Van Eyck         psa_key_derivation_abort(operation);
7435b0563631STom Van Eyck     }
7436b0563631STom Van Eyck     return status;
7437b0563631STom Van Eyck }
7438b0563631STom Van Eyck 
7439b0563631STom Van Eyck psa_status_t psa_key_derivation_input_bytes(
7440b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
7441b0563631STom Van Eyck     psa_key_derivation_step_t step,
7442b0563631STom Van Eyck     const uint8_t *data_external,
7443b0563631STom Van Eyck     size_t data_length)
7444b0563631STom Van Eyck {
7445b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
7446b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(data_external, data);
7447b0563631STom Van Eyck 
7448b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(data_external, data_length, data);
7449b0563631STom Van Eyck 
7450b0563631STom Van Eyck     status = psa_key_derivation_input_internal(operation, step,
7451b0563631STom Van Eyck                                                PSA_KEY_TYPE_NONE,
7452b0563631STom Van Eyck                                                data, data_length);
7453b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
7454b0563631STom Van Eyck exit:
7455b0563631STom Van Eyck #endif
7456b0563631STom Van Eyck     LOCAL_INPUT_FREE(data_external, data);
7457b0563631STom Van Eyck     return status;
7458b0563631STom Van Eyck }
7459b0563631STom Van Eyck 
7460b0563631STom Van Eyck psa_status_t psa_key_derivation_input_integer(
7461b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
7462b0563631STom Van Eyck     psa_key_derivation_step_t step,
7463b0563631STom Van Eyck     uint64_t value)
7464b0563631STom Van Eyck {
7465b0563631STom Van Eyck     return psa_key_derivation_input_integer_internal(operation, step, value);
7466b0563631STom Van Eyck }
7467b0563631STom Van Eyck 
7468b0563631STom Van Eyck psa_status_t psa_key_derivation_input_key(
7469b0563631STom Van Eyck     psa_key_derivation_operation_t *operation,
7470b0563631STom Van Eyck     psa_key_derivation_step_t step,
7471b0563631STom Van Eyck     mbedtls_svc_key_id_t key)
7472b0563631STom Van Eyck {
7473b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
7474b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
7475b0563631STom Van Eyck     psa_key_slot_t *slot;
7476b0563631STom Van Eyck 
7477b0563631STom Van Eyck     status = psa_get_and_lock_transparent_key_slot_with_policy(
7478b0563631STom Van Eyck         key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg);
7479b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
7480b0563631STom Van Eyck         psa_key_derivation_abort(operation);
7481b0563631STom Van Eyck         return status;
7482b0563631STom Van Eyck     }
7483b0563631STom Van Eyck 
7484b0563631STom Van Eyck     /* Passing a key object as a SECRET or PASSWORD input unlocks the
7485b0563631STom Van Eyck      * permission to output to a key object. */
7486b0563631STom Van Eyck     if (step == PSA_KEY_DERIVATION_INPUT_SECRET ||
7487b0563631STom Van Eyck         step == PSA_KEY_DERIVATION_INPUT_PASSWORD) {
7488b0563631STom Van Eyck         operation->can_output_key = 1;
7489b0563631STom Van Eyck     }
7490b0563631STom Van Eyck 
7491b0563631STom Van Eyck     status = psa_key_derivation_input_internal(operation,
7492b0563631STom Van Eyck                                                step, slot->attr.type,
7493b0563631STom Van Eyck                                                slot->key.data,
7494b0563631STom Van Eyck                                                slot->key.bytes);
7495b0563631STom Van Eyck 
7496b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
7497b0563631STom Van Eyck 
7498b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
7499b0563631STom Van Eyck }
7500b0563631STom Van Eyck 
7501b0563631STom Van Eyck 
7502b0563631STom Van Eyck 
7503b0563631STom Van Eyck /****************************************************************/
7504b0563631STom Van Eyck /* Key agreement */
7505b0563631STom Van Eyck /****************************************************************/
7506b0563631STom Van Eyck 
7507b0563631STom Van Eyck psa_status_t psa_key_agreement_raw_builtin(const psa_key_attributes_t *attributes,
7508b0563631STom Van Eyck                                            const uint8_t *key_buffer,
7509b0563631STom Van Eyck                                            size_t key_buffer_size,
7510b0563631STom Van Eyck                                            psa_algorithm_t alg,
7511b0563631STom Van Eyck                                            const uint8_t *peer_key,
7512b0563631STom Van Eyck                                            size_t peer_key_length,
7513b0563631STom Van Eyck                                            uint8_t *shared_secret,
7514b0563631STom Van Eyck                                            size_t shared_secret_size,
7515b0563631STom Van Eyck                                            size_t *shared_secret_length)
7516b0563631STom Van Eyck {
7517b0563631STom Van Eyck     switch (alg) {
7518b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
7519b0563631STom Van Eyck         case PSA_ALG_ECDH:
7520b0563631STom Van Eyck             return mbedtls_psa_key_agreement_ecdh(attributes, key_buffer,
7521b0563631STom Van Eyck                                                   key_buffer_size, alg,
7522b0563631STom Van Eyck                                                   peer_key, peer_key_length,
7523b0563631STom Van Eyck                                                   shared_secret,
7524b0563631STom Van Eyck                                                   shared_secret_size,
7525b0563631STom Van Eyck                                                   shared_secret_length);
7526b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
7527b0563631STom Van Eyck 
7528b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
7529b0563631STom Van Eyck         case PSA_ALG_FFDH:
7530b0563631STom Van Eyck             return mbedtls_psa_ffdh_key_agreement(attributes,
7531b0563631STom Van Eyck                                                   peer_key,
7532b0563631STom Van Eyck                                                   peer_key_length,
7533b0563631STom Van Eyck                                                   key_buffer,
7534b0563631STom Van Eyck                                                   key_buffer_size,
7535b0563631STom Van Eyck                                                   shared_secret,
7536b0563631STom Van Eyck                                                   shared_secret_size,
7537b0563631STom Van Eyck                                                   shared_secret_length);
7538b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */
7539b0563631STom Van Eyck 
7540b0563631STom Van Eyck         default:
7541b0563631STom Van Eyck             (void) attributes;
7542b0563631STom Van Eyck             (void) key_buffer;
7543b0563631STom Van Eyck             (void) key_buffer_size;
7544b0563631STom Van Eyck             (void) peer_key;
7545b0563631STom Van Eyck             (void) peer_key_length;
7546b0563631STom Van Eyck             (void) shared_secret;
7547b0563631STom Van Eyck             (void) shared_secret_size;
7548b0563631STom Van Eyck             (void) shared_secret_length;
7549b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
7550b0563631STom Van Eyck     }
7551b0563631STom Van Eyck }
7552b0563631STom Van Eyck 
7553b0563631STom Van Eyck /** Internal function for raw key agreement
7554b0563631STom Van Eyck  *  Calls the driver wrapper which will hand off key agreement task
7555b0563631STom Van Eyck  *  to the driver's implementation if a driver is present.
7556b0563631STom Van Eyck  *  Fallback specified in the driver wrapper is built-in raw key agreement
7557b0563631STom Van Eyck  *  (psa_key_agreement_raw_builtin).
7558b0563631STom Van Eyck  */
7559b0563631STom Van Eyck static psa_status_t psa_key_agreement_raw_internal(psa_algorithm_t alg,
7560b0563631STom Van Eyck                                                    psa_key_slot_t *private_key,
7561b0563631STom Van Eyck                                                    const uint8_t *peer_key,
7562b0563631STom Van Eyck                                                    size_t peer_key_length,
7563b0563631STom Van Eyck                                                    uint8_t *shared_secret,
7564b0563631STom Van Eyck                                                    size_t shared_secret_size,
7565b0563631STom Van Eyck                                                    size_t *shared_secret_length)
7566b0563631STom Van Eyck {
7567b0563631STom Van Eyck     if (!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
7568b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
7569b0563631STom Van Eyck     }
7570b0563631STom Van Eyck 
7571b0563631STom Van Eyck     return psa_driver_wrapper_key_agreement(&private_key->attr,
7572b0563631STom Van Eyck                                             private_key->key.data,
7573b0563631STom Van Eyck                                             private_key->key.bytes, alg,
7574b0563631STom Van Eyck                                             peer_key, peer_key_length,
7575b0563631STom Van Eyck                                             shared_secret,
7576b0563631STom Van Eyck                                             shared_secret_size,
7577b0563631STom Van Eyck                                             shared_secret_length);
7578b0563631STom Van Eyck }
7579b0563631STom Van Eyck 
7580b0563631STom Van Eyck /* Note that if this function fails, you must call psa_key_derivation_abort()
7581b0563631STom Van Eyck  * to potentially free embedded data structures and wipe confidential data.
7582b0563631STom Van Eyck  */
7583b0563631STom Van Eyck static psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *operation,
7584b0563631STom Van Eyck                                                psa_key_derivation_step_t step,
7585b0563631STom Van Eyck                                                psa_key_slot_t *private_key,
7586b0563631STom Van Eyck                                                const uint8_t *peer_key,
7587b0563631STom Van Eyck                                                size_t peer_key_length)
7588b0563631STom Van Eyck {
7589b0563631STom Van Eyck     psa_status_t status;
7590b0563631STom Van Eyck     uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 };
7591b0563631STom Van Eyck     size_t shared_secret_length = 0;
7592b0563631STom Van Eyck     psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg);
7593b0563631STom Van Eyck 
7594b0563631STom Van Eyck     /* Step 1: run the secret agreement algorithm to generate the shared
7595b0563631STom Van Eyck      * secret. */
7596b0563631STom Van Eyck     status = psa_key_agreement_raw_internal(ka_alg,
7597b0563631STom Van Eyck                                             private_key,
7598b0563631STom Van Eyck                                             peer_key, peer_key_length,
7599b0563631STom Van Eyck                                             shared_secret,
7600b0563631STom Van Eyck                                             sizeof(shared_secret),
7601b0563631STom Van Eyck                                             &shared_secret_length);
7602b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
7603b0563631STom Van Eyck         goto exit;
7604b0563631STom Van Eyck     }
7605b0563631STom Van Eyck 
7606b0563631STom Van Eyck     /* Step 2: set up the key derivation to generate key material from
7607b0563631STom Van Eyck      * the shared secret. A shared secret is permitted wherever a key
7608b0563631STom Van Eyck      * of type DERIVE is permitted. */
7609b0563631STom Van Eyck     status = psa_key_derivation_input_internal(operation, step,
7610b0563631STom Van Eyck                                                PSA_KEY_TYPE_DERIVE,
7611b0563631STom Van Eyck                                                shared_secret,
7612b0563631STom Van Eyck                                                shared_secret_length);
7613b0563631STom Van Eyck exit:
7614b0563631STom Van Eyck     mbedtls_platform_zeroize(shared_secret, shared_secret_length);
7615b0563631STom Van Eyck     return status;
7616b0563631STom Van Eyck }
7617b0563631STom Van Eyck 
7618b0563631STom Van Eyck psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation,
7619b0563631STom Van Eyck                                               psa_key_derivation_step_t step,
7620b0563631STom Van Eyck                                               mbedtls_svc_key_id_t private_key,
7621b0563631STom Van Eyck                                               const uint8_t *peer_key_external,
7622b0563631STom Van Eyck                                               size_t peer_key_length)
7623b0563631STom Van Eyck {
7624b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
7625b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
7626b0563631STom Van Eyck     psa_key_slot_t *slot;
7627b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(peer_key_external, peer_key);
7628b0563631STom Van Eyck 
7629b0563631STom Van Eyck     if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) {
7630b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7631b0563631STom Van Eyck     }
7632b0563631STom Van Eyck     status = psa_get_and_lock_transparent_key_slot_with_policy(
7633b0563631STom Van Eyck         private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg);
7634b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
7635b0563631STom Van Eyck         return status;
7636b0563631STom Van Eyck     }
7637b0563631STom Van Eyck 
7638b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key);
7639b0563631STom Van Eyck     status = psa_key_agreement_internal(operation, step,
7640b0563631STom Van Eyck                                         slot,
7641b0563631STom Van Eyck                                         peer_key, peer_key_length);
7642b0563631STom Van Eyck 
7643b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
7644b0563631STom Van Eyck exit:
7645b0563631STom Van Eyck #endif
7646b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
7647b0563631STom Van Eyck         psa_key_derivation_abort(operation);
7648b0563631STom Van Eyck     } else {
7649b0563631STom Van Eyck         /* If a private key has been added as SECRET, we allow the derived
7650b0563631STom Van Eyck          * key material to be used as a key in PSA Crypto. */
7651b0563631STom Van Eyck         if (step == PSA_KEY_DERIVATION_INPUT_SECRET) {
7652b0563631STom Van Eyck             operation->can_output_key = 1;
7653b0563631STom Van Eyck         }
7654b0563631STom Van Eyck     }
7655b0563631STom Van Eyck 
7656b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
7657b0563631STom Van Eyck     LOCAL_INPUT_FREE(peer_key_external, peer_key);
7658b0563631STom Van Eyck 
7659b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
7660b0563631STom Van Eyck }
7661b0563631STom Van Eyck 
7662b0563631STom Van Eyck psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
7663b0563631STom Van Eyck                                    mbedtls_svc_key_id_t private_key,
7664b0563631STom Van Eyck                                    const uint8_t *peer_key_external,
7665b0563631STom Van Eyck                                    size_t peer_key_length,
7666b0563631STom Van Eyck                                    uint8_t *output_external,
7667b0563631STom Van Eyck                                    size_t output_size,
7668b0563631STom Van Eyck                                    size_t *output_length)
7669b0563631STom Van Eyck {
7670b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
7671b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
7672b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
7673b0563631STom Van Eyck     size_t expected_length;
7674b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(peer_key_external, peer_key);
7675b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
7676b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
7677b0563631STom Van Eyck 
7678b0563631STom Van Eyck     if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) {
7679b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
7680b0563631STom Van Eyck         goto exit;
7681b0563631STom Van Eyck     }
7682b0563631STom Van Eyck     status = psa_get_and_lock_transparent_key_slot_with_policy(
7683b0563631STom Van Eyck         private_key, &slot, PSA_KEY_USAGE_DERIVE, alg);
7684b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
7685b0563631STom Van Eyck         goto exit;
7686b0563631STom Van Eyck     }
7687b0563631STom Van Eyck 
7688b0563631STom Van Eyck     /* PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is in general an upper bound
7689b0563631STom Van Eyck      * for the output size. The PSA specification only guarantees that this
7690b0563631STom Van Eyck      * function works if output_size >= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(...),
7691b0563631STom Van Eyck      * but it might be nice to allow smaller buffers if the output fits.
7692b0563631STom Van Eyck      * At the time of writing this comment, with only ECDH implemented,
7693b0563631STom Van Eyck      * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is exact so the point is moot.
7694b0563631STom Van Eyck      * If FFDH is implemented, PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() can easily
7695b0563631STom Van Eyck      * be exact for it as well. */
7696b0563631STom Van Eyck     expected_length =
7697b0563631STom Van Eyck         PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(slot->attr.type, slot->attr.bits);
7698b0563631STom Van Eyck     if (output_size < expected_length) {
7699b0563631STom Van Eyck         status = PSA_ERROR_BUFFER_TOO_SMALL;
7700b0563631STom Van Eyck         goto exit;
7701b0563631STom Van Eyck     }
7702b0563631STom Van Eyck 
7703b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key);
7704b0563631STom Van Eyck     status = psa_key_agreement_raw_internal(alg, slot,
7705b0563631STom Van Eyck                                             peer_key, peer_key_length,
7706b0563631STom Van Eyck                                             output, output_size,
7707b0563631STom Van Eyck                                             output_length);
7708b0563631STom Van Eyck 
7709b0563631STom Van Eyck exit:
7710b0563631STom Van Eyck     /* Check for successful allocation of output,
7711b0563631STom Van Eyck      * with an unsuccessful status. */
7712b0563631STom Van Eyck     if (output != NULL && status != PSA_SUCCESS) {
7713b0563631STom Van Eyck         /* If an error happens and is not handled properly, the output
7714b0563631STom Van Eyck          * may be used as a key to protect sensitive data. Arrange for such
7715b0563631STom Van Eyck          * a key to be random, which is likely to result in decryption or
7716b0563631STom Van Eyck          * verification errors. This is better than filling the buffer with
7717b0563631STom Van Eyck          * some constant data such as zeros, which would result in the data
7718b0563631STom Van Eyck          * being protected with a reproducible, easily knowable key.
7719b0563631STom Van Eyck          */
7720b0563631STom Van Eyck         psa_generate_random_internal(output, output_size);
7721b0563631STom Van Eyck         *output_length = output_size;
7722b0563631STom Van Eyck     }
7723b0563631STom Van Eyck 
7724b0563631STom Van Eyck     if (output == NULL) {
7725b0563631STom Van Eyck         /* output allocation failed. */
7726b0563631STom Van Eyck         *output_length = 0;
7727b0563631STom Van Eyck     }
7728b0563631STom Van Eyck 
7729b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
7730b0563631STom Van Eyck 
7731b0563631STom Van Eyck     LOCAL_INPUT_FREE(peer_key_external, peer_key);
7732b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
7733b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
7734b0563631STom Van Eyck }
7735b0563631STom Van Eyck 
7736b0563631STom Van Eyck 
7737b0563631STom Van Eyck /****************************************************************/
7738b0563631STom Van Eyck /* Random generation */
7739b0563631STom Van Eyck /****************************************************************/
7740b0563631STom Van Eyck 
7741b0563631STom Van Eyck #if defined(MBEDTLS_PSA_INJECT_ENTROPY)
7742b0563631STom Van Eyck #include "entropy_poll.h"
7743b0563631STom Van Eyck #endif
7744b0563631STom Van Eyck 
7745b0563631STom Van Eyck /** Initialize the PSA random generator.
7746b0563631STom Van Eyck  *
7747b0563631STom Van Eyck  *  Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling
7748b0563631STom Van Eyck  *  this function if mutexes are enabled.
7749b0563631STom Van Eyck  */
7750b0563631STom Van Eyck static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng)
7751b0563631STom Van Eyck {
7752b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
7753b0563631STom Van Eyck     memset(rng, 0, sizeof(*rng));
7754b0563631STom Van Eyck #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
7755b0563631STom Van Eyck 
7756b0563631STom Van Eyck     /* Set default configuration if
7757b0563631STom Van Eyck      * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */
7758b0563631STom Van Eyck     if (rng->entropy_init == NULL) {
7759b0563631STom Van Eyck         rng->entropy_init = mbedtls_entropy_init;
7760b0563631STom Van Eyck     }
7761b0563631STom Van Eyck     if (rng->entropy_free == NULL) {
7762b0563631STom Van Eyck         rng->entropy_free = mbedtls_entropy_free;
7763b0563631STom Van Eyck     }
7764b0563631STom Van Eyck 
7765b0563631STom Van Eyck     rng->entropy_init(&rng->entropy);
7766b0563631STom Van Eyck #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
7767b0563631STom Van Eyck     defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
7768b0563631STom Van Eyck     /* The PSA entropy injection feature depends on using NV seed as an entropy
7769b0563631STom Van Eyck      * source. Add NV seed as an entropy source for PSA entropy injection. */
7770b0563631STom Van Eyck     mbedtls_entropy_add_source(&rng->entropy,
7771b0563631STom Van Eyck                                mbedtls_nv_seed_poll, NULL,
7772b0563631STom Van Eyck                                MBEDTLS_ENTROPY_BLOCK_SIZE,
7773b0563631STom Van Eyck                                MBEDTLS_ENTROPY_SOURCE_STRONG);
7774b0563631STom Van Eyck #endif
7775b0563631STom Van Eyck 
7776b0563631STom Van Eyck     mbedtls_psa_drbg_init(&rng->drbg);
7777b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
7778b0563631STom Van Eyck }
7779b0563631STom Van Eyck 
7780b0563631STom Van Eyck /** Deinitialize the PSA random generator.
7781b0563631STom Van Eyck  *
7782b0563631STom Van Eyck  *  Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling
7783b0563631STom Van Eyck  *  this function if mutexes are enabled.
7784b0563631STom Van Eyck  */
7785b0563631STom Van Eyck static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng)
7786b0563631STom Van Eyck {
7787b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
7788b0563631STom Van Eyck     memset(rng, 0, sizeof(*rng));
7789b0563631STom Van Eyck #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
7790b0563631STom Van Eyck     mbedtls_psa_drbg_free(&rng->drbg);
7791b0563631STom Van Eyck     rng->entropy_free(&rng->entropy);
7792b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
7793b0563631STom Van Eyck }
7794b0563631STom Van Eyck 
7795b0563631STom Van Eyck /** Seed the PSA random generator.
7796b0563631STom Van Eyck  */
7797b0563631STom Van Eyck static psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng)
7798b0563631STom Van Eyck {
7799b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
7800b0563631STom Van Eyck     /* Do nothing: the external RNG seeds itself. */
7801b0563631STom Van Eyck     (void) rng;
7802b0563631STom Van Eyck     return PSA_SUCCESS;
7803b0563631STom Van Eyck #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
7804b0563631STom Van Eyck     const unsigned char drbg_seed[] = "PSA";
7805b0563631STom Van Eyck     int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy,
7806b0563631STom Van Eyck                                     drbg_seed, sizeof(drbg_seed) - 1);
7807b0563631STom Van Eyck     return mbedtls_to_psa_error(ret);
7808b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
7809b0563631STom Van Eyck }
7810b0563631STom Van Eyck 
7811b0563631STom Van Eyck psa_status_t psa_generate_random(uint8_t *output_external,
7812b0563631STom Van Eyck                                  size_t output_size)
7813b0563631STom Van Eyck {
7814b0563631STom Van Eyck     psa_status_t status;
7815b0563631STom Van Eyck 
7816b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
7817b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
7818b0563631STom Van Eyck 
7819b0563631STom Van Eyck     status = psa_generate_random_internal(output, output_size);
7820b0563631STom Van Eyck 
7821b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
7822b0563631STom Van Eyck exit:
7823b0563631STom Van Eyck #endif
7824b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
7825b0563631STom Van Eyck     return status;
7826b0563631STom Van Eyck }
7827b0563631STom Van Eyck 
7828b0563631STom Van Eyck #if defined(MBEDTLS_PSA_INJECT_ENTROPY)
7829b0563631STom Van Eyck psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
7830b0563631STom Van Eyck                                         size_t seed_size)
7831b0563631STom Van Eyck {
7832b0563631STom Van Eyck     if (psa_get_initialized()) {
7833b0563631STom Van Eyck         return PSA_ERROR_NOT_PERMITTED;
7834b0563631STom Van Eyck     }
7835b0563631STom Van Eyck 
7836b0563631STom Van Eyck     if (((seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) ||
7837b0563631STom Van Eyck          (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) ||
7838b0563631STom Van Eyck         (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) {
7839b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7840b0563631STom Van Eyck     }
7841b0563631STom Van Eyck 
7842b0563631STom Van Eyck     return mbedtls_psa_storage_inject_entropy(seed, seed_size);
7843b0563631STom Van Eyck }
7844b0563631STom Van Eyck #endif /* MBEDTLS_PSA_INJECT_ENTROPY */
7845b0563631STom Van Eyck 
7846b0563631STom Van Eyck /** Validate the key type and size for key generation
7847b0563631STom Van Eyck  *
7848b0563631STom Van Eyck  * \param  type  The key type
7849b0563631STom Van Eyck  * \param  bits  The number of bits of the key
7850b0563631STom Van Eyck  *
7851b0563631STom Van Eyck  * \retval #PSA_SUCCESS
7852b0563631STom Van Eyck  *         The key type and size are valid.
7853b0563631STom Van Eyck  * \retval #PSA_ERROR_INVALID_ARGUMENT
7854b0563631STom Van Eyck  *         The size in bits of the key is not valid.
7855b0563631STom Van Eyck  * \retval #PSA_ERROR_NOT_SUPPORTED
7856b0563631STom Van Eyck  *         The type and/or the size in bits of the key or the combination of
7857b0563631STom Van Eyck  *         the two is not supported.
7858b0563631STom Van Eyck  */
7859b0563631STom Van Eyck static psa_status_t psa_validate_key_type_and_size_for_key_generation(
7860b0563631STom Van Eyck     psa_key_type_t type, size_t bits)
7861b0563631STom Van Eyck {
7862b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
7863b0563631STom Van Eyck 
7864b0563631STom Van Eyck     if (key_type_is_raw_bytes(type)) {
7865b0563631STom Van Eyck         status = psa_validate_unstructured_key_bit_size(type, bits);
7866b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
7867b0563631STom Van Eyck             return status;
7868b0563631STom Van Eyck         }
7869b0563631STom Van Eyck     } else
7870b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
7871b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_RSA(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
7872b0563631STom Van Eyck         if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {
7873b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
7874b0563631STom Van Eyck         }
7875b0563631STom Van Eyck         if (bits < PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS) {
7876b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
7877b0563631STom Van Eyck         }
7878b0563631STom Van Eyck 
7879b0563631STom Van Eyck         /* Accept only byte-aligned keys, for the same reasons as
7880b0563631STom Van Eyck          * in psa_import_rsa_key(). */
7881b0563631STom Van Eyck         if (bits % 8 != 0) {
7882b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
7883b0563631STom Van Eyck         }
7884b0563631STom Van Eyck     } else
7885b0563631STom Van Eyck #endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */
7886b0563631STom Van Eyck 
7887b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
7888b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
7889b0563631STom Van Eyck         /* To avoid empty block, return successfully here. */
7890b0563631STom Van Eyck         return PSA_SUCCESS;
7891b0563631STom Van Eyck     } else
7892b0563631STom Van Eyck #endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */
7893b0563631STom Van Eyck 
7894b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
7895b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
7896b0563631STom Van Eyck         if (psa_is_dh_key_size_valid(bits) == 0) {
7897b0563631STom Van Eyck             return PSA_ERROR_NOT_SUPPORTED;
7898b0563631STom Van Eyck         }
7899b0563631STom Van Eyck     } else
7900b0563631STom Van Eyck #endif /* defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) */
7901b0563631STom Van Eyck     {
7902b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
7903b0563631STom Van Eyck     }
7904b0563631STom Van Eyck 
7905b0563631STom Van Eyck     return PSA_SUCCESS;
7906b0563631STom Van Eyck }
7907b0563631STom Van Eyck 
7908b0563631STom Van Eyck psa_status_t psa_generate_key_internal(
7909b0563631STom Van Eyck     const psa_key_attributes_t *attributes,
7910*cb034002SJerome Forissier     const psa_custom_key_parameters_t *custom,
7911*cb034002SJerome Forissier     const uint8_t *custom_data,
7912*cb034002SJerome Forissier     size_t custom_data_length,
7913b0563631STom Van Eyck     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
7914b0563631STom Van Eyck {
7915b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
7916b0563631STom Van Eyck     psa_key_type_t type = attributes->type;
7917b0563631STom Van Eyck 
7918b0563631STom Van Eyck     /* Only used for RSA */
7919*cb034002SJerome Forissier     (void) custom;
7920*cb034002SJerome Forissier     (void) custom_data;
7921*cb034002SJerome Forissier     (void) custom_data_length;
7922b0563631STom Van Eyck 
7923b0563631STom Van Eyck     if (key_type_is_raw_bytes(type)) {
7924b0563631STom Van Eyck         status = psa_generate_random_internal(key_buffer, key_buffer_size);
7925b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
7926b0563631STom Van Eyck             return status;
7927b0563631STom Van Eyck         }
7928b0563631STom Van Eyck 
7929b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
7930b0563631STom Van Eyck         if (type == PSA_KEY_TYPE_DES) {
7931b0563631STom Van Eyck             psa_des_set_key_parity(key_buffer, key_buffer_size);
7932b0563631STom Van Eyck         }
7933b0563631STom Van Eyck #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */
7934b0563631STom Van Eyck     } else
7935b0563631STom Van Eyck 
7936b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
7937b0563631STom Van Eyck     if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
7938b0563631STom Van Eyck         return mbedtls_psa_rsa_generate_key(attributes,
7939*cb034002SJerome Forissier                                             custom_data, custom_data_length,
7940b0563631STom Van Eyck                                             key_buffer,
7941b0563631STom Van Eyck                                             key_buffer_size,
7942b0563631STom Van Eyck                                             key_buffer_length);
7943b0563631STom Van Eyck     } else
7944b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */
7945b0563631STom Van Eyck 
7946b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
7947b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
7948b0563631STom Van Eyck         return mbedtls_psa_ecp_generate_key(attributes,
7949b0563631STom Van Eyck                                             key_buffer,
7950b0563631STom Van Eyck                                             key_buffer_size,
7951b0563631STom Van Eyck                                             key_buffer_length);
7952b0563631STom Van Eyck     } else
7953b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */
7954b0563631STom Van Eyck 
7955b0563631STom Van Eyck #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)
7956b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
7957b0563631STom Van Eyck         return mbedtls_psa_ffdh_generate_key(attributes,
7958b0563631STom Van Eyck                                              key_buffer,
7959b0563631STom Van Eyck                                              key_buffer_size,
7960b0563631STom Van Eyck                                              key_buffer_length);
7961b0563631STom Van Eyck     } else
7962b0563631STom Van Eyck #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) */
7963b0563631STom Van Eyck     {
7964b0563631STom Van Eyck         (void) key_buffer_length;
7965b0563631STom Van Eyck         return PSA_ERROR_NOT_SUPPORTED;
7966b0563631STom Van Eyck     }
7967b0563631STom Van Eyck 
7968b0563631STom Van Eyck     return PSA_SUCCESS;
7969b0563631STom Van Eyck }
7970b0563631STom Van Eyck 
7971*cb034002SJerome Forissier psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes,
7972*cb034002SJerome Forissier                                      const psa_custom_key_parameters_t *custom,
7973*cb034002SJerome Forissier                                      const uint8_t *custom_data,
7974*cb034002SJerome Forissier                                      size_t custom_data_length,
7975b0563631STom Van Eyck                                      mbedtls_svc_key_id_t *key)
7976b0563631STom Van Eyck {
7977b0563631STom Van Eyck     psa_status_t status;
7978b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
7979b0563631STom Van Eyck     psa_se_drv_table_entry_t *driver = NULL;
7980b0563631STom Van Eyck     size_t key_buffer_size;
7981b0563631STom Van Eyck 
7982b0563631STom Van Eyck     *key = MBEDTLS_SVC_KEY_ID_INIT;
7983b0563631STom Van Eyck 
7984b0563631STom Van Eyck     /* Reject any attempt to create a zero-length key so that we don't
7985b0563631STom Van Eyck      * risk tripping up later, e.g. on a malloc(0) that returns NULL. */
7986b0563631STom Van Eyck     if (psa_get_key_bits(attributes) == 0) {
7987b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7988b0563631STom Van Eyck     }
7989b0563631STom Van Eyck 
7990b0563631STom Van Eyck     /* Reject any attempt to create a public key. */
7991b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->type)) {
7992b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
7993b0563631STom Van Eyck     }
7994b0563631STom Van Eyck 
7995b0563631STom Van Eyck #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
7996b0563631STom Van Eyck     if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
7997*cb034002SJerome Forissier         if (custom->flags != 0) {
7998b0563631STom Van Eyck             return PSA_ERROR_INVALID_ARGUMENT;
7999b0563631STom Van Eyck         }
8000b0563631STom Van Eyck     } else
8001b0563631STom Van Eyck #endif
8002*cb034002SJerome Forissier     if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) {
8003b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
8004b0563631STom Van Eyck     }
8005b0563631STom Van Eyck 
8006b0563631STom Van Eyck     status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes,
8007b0563631STom Van Eyck                                     &slot, &driver);
8008b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8009b0563631STom Van Eyck         goto exit;
8010b0563631STom Van Eyck     }
8011b0563631STom Van Eyck 
8012b0563631STom Van Eyck     /* In the case of a transparent key or an opaque key stored in local
8013b0563631STom Van Eyck      * storage ( thus not in the case of generating a key in a secure element
8014b0563631STom Van Eyck      * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a
8015b0563631STom Van Eyck      * buffer to hold the generated key material. */
8016b0563631STom Van Eyck     if (slot->key.data == NULL) {
8017b0563631STom Van Eyck         if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) ==
8018b0563631STom Van Eyck             PSA_KEY_LOCATION_LOCAL_STORAGE) {
8019b0563631STom Van Eyck             status = psa_validate_key_type_and_size_for_key_generation(
8020b0563631STom Van Eyck                 attributes->type, attributes->bits);
8021b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
8022b0563631STom Van Eyck                 goto exit;
8023b0563631STom Van Eyck             }
8024b0563631STom Van Eyck 
8025b0563631STom Van Eyck             key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
8026b0563631STom Van Eyck                 attributes->type,
8027b0563631STom Van Eyck                 attributes->bits);
8028b0563631STom Van Eyck         } else {
8029b0563631STom Van Eyck             status = psa_driver_wrapper_get_key_buffer_size(
8030b0563631STom Van Eyck                 attributes, &key_buffer_size);
8031b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
8032b0563631STom Van Eyck                 goto exit;
8033b0563631STom Van Eyck             }
8034b0563631STom Van Eyck         }
8035b0563631STom Van Eyck 
8036b0563631STom Van Eyck         status = psa_allocate_buffer_to_slot(slot, key_buffer_size);
8037b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
8038b0563631STom Van Eyck             goto exit;
8039b0563631STom Van Eyck         }
8040b0563631STom Van Eyck     }
8041b0563631STom Van Eyck 
8042b0563631STom Van Eyck     status = psa_driver_wrapper_generate_key(attributes,
8043*cb034002SJerome Forissier                                              custom,
8044*cb034002SJerome Forissier                                              custom_data, custom_data_length,
8045b0563631STom Van Eyck                                              slot->key.data, slot->key.bytes,
8046b0563631STom Van Eyck                                              &slot->key.bytes);
8047b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8048b0563631STom Van Eyck         psa_remove_key_data_from_memory(slot);
8049b0563631STom Van Eyck     }
8050b0563631STom Van Eyck 
8051b0563631STom Van Eyck exit:
8052b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
8053b0563631STom Van Eyck         status = psa_finish_key_creation(slot, driver, key);
8054b0563631STom Van Eyck     }
8055b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8056b0563631STom Van Eyck         psa_fail_key_creation(slot, driver);
8057b0563631STom Van Eyck     }
8058b0563631STom Van Eyck 
8059b0563631STom Van Eyck     return status;
8060b0563631STom Van Eyck }
8061b0563631STom Van Eyck 
8062*cb034002SJerome Forissier psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
8063*cb034002SJerome Forissier                                   const psa_key_production_parameters_t *params,
8064*cb034002SJerome Forissier                                   size_t params_data_length,
8065*cb034002SJerome Forissier                                   mbedtls_svc_key_id_t *key)
8066*cb034002SJerome Forissier {
8067*cb034002SJerome Forissier     return psa_generate_key_custom(
8068*cb034002SJerome Forissier         attributes,
8069*cb034002SJerome Forissier         (const psa_custom_key_parameters_t *) params,
8070*cb034002SJerome Forissier         params->data, params_data_length,
8071*cb034002SJerome Forissier         key);
8072*cb034002SJerome Forissier }
8073*cb034002SJerome Forissier 
8074b0563631STom Van Eyck psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
8075b0563631STom Van Eyck                               mbedtls_svc_key_id_t *key)
8076b0563631STom Van Eyck {
8077*cb034002SJerome Forissier     return psa_generate_key_custom(attributes,
8078*cb034002SJerome Forissier                                    &default_custom_production,
8079*cb034002SJerome Forissier                                    NULL, 0,
8080b0563631STom Van Eyck                                    key);
8081b0563631STom Van Eyck }
8082b0563631STom Van Eyck 
8083b0563631STom Van Eyck /****************************************************************/
8084b0563631STom Van Eyck /* Module setup */
8085b0563631STom Van Eyck /****************************************************************/
8086b0563631STom Van Eyck 
8087b0563631STom Van Eyck #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
8088b0563631STom Van Eyck psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
8089b0563631STom Van Eyck     void (* entropy_init)(mbedtls_entropy_context *ctx),
8090b0563631STom Van Eyck     void (* entropy_free)(mbedtls_entropy_context *ctx))
8091b0563631STom Van Eyck {
8092b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8093b0563631STom Van Eyck 
8094b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8095b0563631STom Van Eyck     mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
8096b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8097b0563631STom Van Eyck 
8098b0563631STom Van Eyck     if (global_data.rng_state != RNG_NOT_INITIALIZED) {
8099b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8100b0563631STom Van Eyck     } else {
8101b0563631STom Van Eyck         global_data.rng.entropy_init = entropy_init;
8102b0563631STom Van Eyck         global_data.rng.entropy_free = entropy_free;
8103b0563631STom Van Eyck         status = PSA_SUCCESS;
8104b0563631STom Van Eyck     }
8105b0563631STom Van Eyck 
8106b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8107b0563631STom Van Eyck     mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
8108b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8109b0563631STom Van Eyck 
8110b0563631STom Van Eyck     return status;
8111b0563631STom Van Eyck }
8112b0563631STom Van Eyck #endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
8113b0563631STom Van Eyck 
8114b0563631STom Van Eyck void mbedtls_psa_crypto_free(void)
8115b0563631STom Van Eyck {
8116b0563631STom Van Eyck 
8117b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8118b0563631STom Van Eyck     mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
8119b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8120b0563631STom Van Eyck 
8121b0563631STom Van Eyck     /* Nothing to do to free transaction. */
8122b0563631STom Van Eyck     if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) {
8123b0563631STom Van Eyck         global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
8124b0563631STom Van Eyck     }
8125b0563631STom Van Eyck 
8126b0563631STom Van Eyck     if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) {
8127b0563631STom Van Eyck         psa_wipe_all_key_slots();
8128b0563631STom Van Eyck         global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
8129b0563631STom Van Eyck     }
8130b0563631STom Van Eyck 
8131b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8132b0563631STom Van Eyck     mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
8133b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8134b0563631STom Van Eyck 
8135b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8136b0563631STom Van Eyck     mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
8137b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8138b0563631STom Van Eyck 
8139b0563631STom Van Eyck     if (global_data.rng_state != RNG_NOT_INITIALIZED) {
8140b0563631STom Van Eyck         mbedtls_psa_random_free(&global_data.rng);
8141b0563631STom Van Eyck     }
8142b0563631STom Van Eyck     global_data.rng_state = RNG_NOT_INITIALIZED;
8143b0563631STom Van Eyck     mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng));
8144b0563631STom Van Eyck 
8145b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8146b0563631STom Van Eyck     mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
8147b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8148b0563631STom Van Eyck 
8149b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8150b0563631STom Van Eyck     mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
8151b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8152b0563631STom Van Eyck 
8153b0563631STom Van Eyck     /* Terminate drivers */
8154b0563631STom Van Eyck     if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) {
8155b0563631STom Van Eyck         psa_driver_wrapper_free();
8156b0563631STom Van Eyck         global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
8157b0563631STom Van Eyck     }
8158b0563631STom Van Eyck 
8159b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8160b0563631STom Van Eyck     mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
8161b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8162b0563631STom Van Eyck 
8163b0563631STom Van Eyck }
8164b0563631STom Van Eyck 
8165b0563631STom Van Eyck #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
8166b0563631STom Van Eyck /** Recover a transaction that was interrupted by a power failure.
8167b0563631STom Van Eyck  *
8168b0563631STom Van Eyck  * This function is called during initialization, before psa_crypto_init()
8169b0563631STom Van Eyck  * returns. If this function returns a failure status, the initialization
8170b0563631STom Van Eyck  * fails.
8171b0563631STom Van Eyck  */
8172b0563631STom Van Eyck static psa_status_t psa_crypto_recover_transaction(
8173b0563631STom Van Eyck     const psa_crypto_transaction_t *transaction)
8174b0563631STom Van Eyck {
8175b0563631STom Van Eyck     switch (transaction->unknown.type) {
8176b0563631STom Van Eyck         case PSA_CRYPTO_TRANSACTION_CREATE_KEY:
8177b0563631STom Van Eyck         case PSA_CRYPTO_TRANSACTION_DESTROY_KEY:
8178b0563631STom Van Eyck         /* TODO - fall through to the failure case until this
8179b0563631STom Van Eyck          * is implemented.
8180b0563631STom Van Eyck          * https://github.com/ARMmbed/mbed-crypto/issues/218
8181b0563631STom Van Eyck          */
8182b0563631STom Van Eyck         default:
8183b0563631STom Van Eyck             /* We found an unsupported transaction in the storage.
8184b0563631STom Van Eyck              * We don't know what state the storage is in. Give up. */
8185b0563631STom Van Eyck             return PSA_ERROR_DATA_INVALID;
8186b0563631STom Van Eyck     }
8187b0563631STom Van Eyck }
8188b0563631STom Van Eyck #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
8189b0563631STom Van Eyck 
8190b0563631STom Van Eyck static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem)
8191b0563631STom Van Eyck {
8192b0563631STom Van Eyck     psa_status_t status = PSA_SUCCESS;
8193b0563631STom Van Eyck     uint8_t driver_wrappers_initialized = 0;
8194b0563631STom Van Eyck 
8195b0563631STom Van Eyck     switch (subsystem) {
8196b0563631STom Van Eyck         case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS:
8197b0563631STom Van Eyck 
8198b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8199b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
8200b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8201b0563631STom Van Eyck 
8202b0563631STom Van Eyck             if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) {
8203b0563631STom Van Eyck                 /* Init drivers */
8204b0563631STom Van Eyck                 status = psa_driver_wrapper_init();
8205b0563631STom Van Eyck 
8206b0563631STom Van Eyck                 /* Drivers need shutdown regardless of startup errors. */
8207b0563631STom Van Eyck                 global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
8208b0563631STom Van Eyck 
8209b0563631STom Van Eyck 
8210b0563631STom Van Eyck             }
8211b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8212b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
8213b0563631STom Van Eyck                                             &mbedtls_threading_psa_globaldata_mutex));
8214b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8215b0563631STom Van Eyck 
8216b0563631STom Van Eyck             break;
8217b0563631STom Van Eyck 
8218b0563631STom Van Eyck         case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS:
8219b0563631STom Van Eyck 
8220b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8221b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
8222b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8223b0563631STom Van Eyck 
8224b0563631STom Van Eyck             if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) {
8225b0563631STom Van Eyck                 status = psa_initialize_key_slots();
8226b0563631STom Van Eyck 
8227b0563631STom Van Eyck                 /* Need to wipe keys even if initialization fails. */
8228b0563631STom Van Eyck                 global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
8229b0563631STom Van Eyck 
8230b0563631STom Van Eyck             }
8231b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8232b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
8233b0563631STom Van Eyck                                             &mbedtls_threading_psa_globaldata_mutex));
8234b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8235b0563631STom Van Eyck 
8236b0563631STom Van Eyck             break;
8237b0563631STom Van Eyck 
8238b0563631STom Van Eyck         case PSA_CRYPTO_SUBSYSTEM_RNG:
8239b0563631STom Van Eyck 
8240b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8241b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
8242b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8243b0563631STom Van Eyck 
8244b0563631STom Van Eyck             driver_wrappers_initialized =
8245b0563631STom Van Eyck                 (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED);
8246b0563631STom Van Eyck 
8247b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8248b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
8249b0563631STom Van Eyck                                             &mbedtls_threading_psa_globaldata_mutex));
8250b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8251b0563631STom Van Eyck 
8252b0563631STom Van Eyck             /* Need to use separate mutex here, as initialisation can require
8253b0563631STom Van Eyck              * testing of init flags, which requires locking the global data
8254b0563631STom Van Eyck              * mutex. */
8255b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8256b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex));
8257b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8258b0563631STom Van Eyck 
8259b0563631STom Van Eyck             /* Initialize and seed the random generator. */
8260b0563631STom Van Eyck             if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) {
8261b0563631STom Van Eyck                 mbedtls_psa_random_init(&global_data.rng);
8262b0563631STom Van Eyck                 global_data.rng_state = RNG_INITIALIZED;
8263b0563631STom Van Eyck 
8264b0563631STom Van Eyck                 status = mbedtls_psa_random_seed(&global_data.rng);
8265b0563631STom Van Eyck                 if (status == PSA_SUCCESS) {
8266b0563631STom Van Eyck                     global_data.rng_state = RNG_SEEDED;
8267b0563631STom Van Eyck                 }
8268b0563631STom Van Eyck             }
8269b0563631STom Van Eyck 
8270b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8271b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
8272b0563631STom Van Eyck                                             &mbedtls_threading_psa_rngdata_mutex));
8273b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8274b0563631STom Van Eyck 
8275b0563631STom Van Eyck             break;
8276b0563631STom Van Eyck 
8277b0563631STom Van Eyck         case PSA_CRYPTO_SUBSYSTEM_TRANSACTION:
8278b0563631STom Van Eyck 
8279b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8280b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
8281b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8282b0563631STom Van Eyck 
8283b0563631STom Van Eyck             if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) {
8284b0563631STom Van Eyck #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
8285b0563631STom Van Eyck                 status = psa_crypto_load_transaction();
8286b0563631STom Van Eyck                 if (status == PSA_SUCCESS) {
8287b0563631STom Van Eyck                     status = psa_crypto_recover_transaction(&psa_crypto_transaction);
8288b0563631STom Van Eyck                     if (status == PSA_SUCCESS) {
8289b0563631STom Van Eyck                         global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
8290b0563631STom Van Eyck                     }
8291b0563631STom Van Eyck                     status = psa_crypto_stop_transaction();
8292b0563631STom Van Eyck                 } else if (status == PSA_ERROR_DOES_NOT_EXIST) {
8293b0563631STom Van Eyck                     /* There's no transaction to complete. It's all good. */
8294b0563631STom Van Eyck                     global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
8295b0563631STom Van Eyck                     status = PSA_SUCCESS;
8296b0563631STom Van Eyck                 }
8297b0563631STom Van Eyck #else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
8298b0563631STom Van Eyck                 global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
8299b0563631STom Van Eyck                 status = PSA_SUCCESS;
8300b0563631STom Van Eyck #endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
8301b0563631STom Van Eyck             }
8302b0563631STom Van Eyck 
8303b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8304b0563631STom Van Eyck             PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
8305b0563631STom Van Eyck                                             &mbedtls_threading_psa_globaldata_mutex));
8306b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8307b0563631STom Van Eyck 
8308b0563631STom Van Eyck             break;
8309b0563631STom Van Eyck 
8310b0563631STom Van Eyck         default:
8311b0563631STom Van Eyck             status = PSA_ERROR_CORRUPTION_DETECTED;
8312b0563631STom Van Eyck     }
8313b0563631STom Van Eyck 
8314b0563631STom Van Eyck     /* Exit label only required when using threading macros. */
8315b0563631STom Van Eyck #if defined(MBEDTLS_THREADING_C)
8316b0563631STom Van Eyck exit:
8317b0563631STom Van Eyck #endif /* defined(MBEDTLS_THREADING_C) */
8318b0563631STom Van Eyck 
8319b0563631STom Van Eyck     return status;
8320b0563631STom Van Eyck }
8321b0563631STom Van Eyck 
8322b0563631STom Van Eyck psa_status_t psa_crypto_init(void)
8323b0563631STom Van Eyck {
8324b0563631STom Van Eyck     psa_status_t status;
8325b0563631STom Van Eyck 
8326b0563631STom Van Eyck     /* Double initialization is explicitly allowed. Early out if everything is
8327b0563631STom Van Eyck      * done. */
8328b0563631STom Van Eyck     if (psa_get_initialized()) {
8329b0563631STom Van Eyck         return PSA_SUCCESS;
8330b0563631STom Van Eyck     }
8331b0563631STom Van Eyck 
8332b0563631STom Van Eyck     status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS);
8333b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8334b0563631STom Van Eyck         goto exit;
8335b0563631STom Van Eyck     }
8336b0563631STom Van Eyck 
8337b0563631STom Van Eyck     status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS);
8338b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8339b0563631STom Van Eyck         goto exit;
8340b0563631STom Van Eyck     }
8341b0563631STom Van Eyck 
8342b0563631STom Van Eyck     status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG);
8343b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8344b0563631STom Van Eyck         goto exit;
8345b0563631STom Van Eyck     }
8346b0563631STom Van Eyck 
8347b0563631STom Van Eyck     status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION);
8348b0563631STom Van Eyck 
8349b0563631STom Van Eyck exit:
8350b0563631STom Van Eyck 
8351b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8352b0563631STom Van Eyck         mbedtls_psa_crypto_free();
8353b0563631STom Van Eyck     }
8354b0563631STom Van Eyck 
8355b0563631STom Van Eyck     return status;
8356b0563631STom Van Eyck }
8357b0563631STom Van Eyck 
8358b0563631STom Van Eyck #if defined(PSA_WANT_ALG_SOME_PAKE)
8359b0563631STom Van Eyck psa_status_t psa_crypto_driver_pake_get_password_len(
8360b0563631STom Van Eyck     const psa_crypto_driver_pake_inputs_t *inputs,
8361b0563631STom Van Eyck     size_t *password_len)
8362b0563631STom Van Eyck {
8363b0563631STom Van Eyck     if (inputs->password_len == 0) {
8364b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8365b0563631STom Van Eyck     }
8366b0563631STom Van Eyck 
8367b0563631STom Van Eyck     *password_len = inputs->password_len;
8368b0563631STom Van Eyck 
8369b0563631STom Van Eyck     return PSA_SUCCESS;
8370b0563631STom Van Eyck }
8371b0563631STom Van Eyck 
8372b0563631STom Van Eyck psa_status_t psa_crypto_driver_pake_get_password(
8373b0563631STom Van Eyck     const psa_crypto_driver_pake_inputs_t *inputs,
8374b0563631STom Van Eyck     uint8_t *buffer, size_t buffer_size, size_t *buffer_length)
8375b0563631STom Van Eyck {
8376b0563631STom Van Eyck     if (inputs->password_len == 0) {
8377b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8378b0563631STom Van Eyck     }
8379b0563631STom Van Eyck 
8380b0563631STom Van Eyck     if (buffer_size < inputs->password_len) {
8381b0563631STom Van Eyck         return PSA_ERROR_BUFFER_TOO_SMALL;
8382b0563631STom Van Eyck     }
8383b0563631STom Van Eyck 
8384b0563631STom Van Eyck     memcpy(buffer, inputs->password, inputs->password_len);
8385b0563631STom Van Eyck     *buffer_length = inputs->password_len;
8386b0563631STom Van Eyck 
8387b0563631STom Van Eyck     return PSA_SUCCESS;
8388b0563631STom Van Eyck }
8389b0563631STom Van Eyck 
8390b0563631STom Van Eyck psa_status_t psa_crypto_driver_pake_get_user_len(
8391b0563631STom Van Eyck     const psa_crypto_driver_pake_inputs_t *inputs,
8392b0563631STom Van Eyck     size_t *user_len)
8393b0563631STom Van Eyck {
8394b0563631STom Van Eyck     if (inputs->user_len == 0) {
8395b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8396b0563631STom Van Eyck     }
8397b0563631STom Van Eyck 
8398b0563631STom Van Eyck     *user_len = inputs->user_len;
8399b0563631STom Van Eyck 
8400b0563631STom Van Eyck     return PSA_SUCCESS;
8401b0563631STom Van Eyck }
8402b0563631STom Van Eyck 
8403b0563631STom Van Eyck psa_status_t psa_crypto_driver_pake_get_user(
8404b0563631STom Van Eyck     const psa_crypto_driver_pake_inputs_t *inputs,
8405b0563631STom Van Eyck     uint8_t *user_id, size_t user_id_size, size_t *user_id_len)
8406b0563631STom Van Eyck {
8407b0563631STom Van Eyck     if (inputs->user_len == 0) {
8408b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8409b0563631STom Van Eyck     }
8410b0563631STom Van Eyck 
8411b0563631STom Van Eyck     if (user_id_size < inputs->user_len) {
8412b0563631STom Van Eyck         return PSA_ERROR_BUFFER_TOO_SMALL;
8413b0563631STom Van Eyck     }
8414b0563631STom Van Eyck 
8415b0563631STom Van Eyck     memcpy(user_id, inputs->user, inputs->user_len);
8416b0563631STom Van Eyck     *user_id_len = inputs->user_len;
8417b0563631STom Van Eyck 
8418b0563631STom Van Eyck     return PSA_SUCCESS;
8419b0563631STom Van Eyck }
8420b0563631STom Van Eyck 
8421b0563631STom Van Eyck psa_status_t psa_crypto_driver_pake_get_peer_len(
8422b0563631STom Van Eyck     const psa_crypto_driver_pake_inputs_t *inputs,
8423b0563631STom Van Eyck     size_t *peer_len)
8424b0563631STom Van Eyck {
8425b0563631STom Van Eyck     if (inputs->peer_len == 0) {
8426b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8427b0563631STom Van Eyck     }
8428b0563631STom Van Eyck 
8429b0563631STom Van Eyck     *peer_len = inputs->peer_len;
8430b0563631STom Van Eyck 
8431b0563631STom Van Eyck     return PSA_SUCCESS;
8432b0563631STom Van Eyck }
8433b0563631STom Van Eyck 
8434b0563631STom Van Eyck psa_status_t psa_crypto_driver_pake_get_peer(
8435b0563631STom Van Eyck     const psa_crypto_driver_pake_inputs_t *inputs,
8436b0563631STom Van Eyck     uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length)
8437b0563631STom Van Eyck {
8438b0563631STom Van Eyck     if (inputs->peer_len == 0) {
8439b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8440b0563631STom Van Eyck     }
8441b0563631STom Van Eyck 
8442b0563631STom Van Eyck     if (peer_id_size < inputs->peer_len) {
8443b0563631STom Van Eyck         return PSA_ERROR_BUFFER_TOO_SMALL;
8444b0563631STom Van Eyck     }
8445b0563631STom Van Eyck 
8446b0563631STom Van Eyck     memcpy(peer_id, inputs->peer, inputs->peer_len);
8447b0563631STom Van Eyck     *peer_id_length = inputs->peer_len;
8448b0563631STom Van Eyck 
8449b0563631STom Van Eyck     return PSA_SUCCESS;
8450b0563631STom Van Eyck }
8451b0563631STom Van Eyck 
8452b0563631STom Van Eyck psa_status_t psa_crypto_driver_pake_get_cipher_suite(
8453b0563631STom Van Eyck     const psa_crypto_driver_pake_inputs_t *inputs,
8454b0563631STom Van Eyck     psa_pake_cipher_suite_t *cipher_suite)
8455b0563631STom Van Eyck {
8456b0563631STom Van Eyck     if (inputs->cipher_suite.algorithm == PSA_ALG_NONE) {
8457b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8458b0563631STom Van Eyck     }
8459b0563631STom Van Eyck 
8460b0563631STom Van Eyck     *cipher_suite = inputs->cipher_suite;
8461b0563631STom Van Eyck 
8462b0563631STom Van Eyck     return PSA_SUCCESS;
8463b0563631STom Van Eyck }
8464b0563631STom Van Eyck 
8465b0563631STom Van Eyck psa_status_t psa_pake_setup(
8466b0563631STom Van Eyck     psa_pake_operation_t *operation,
8467b0563631STom Van Eyck     const psa_pake_cipher_suite_t *cipher_suite)
8468b0563631STom Van Eyck {
8469b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8470b0563631STom Van Eyck 
8471b0563631STom Van Eyck     if (operation->stage != PSA_PAKE_OPERATION_STAGE_SETUP) {
8472b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8473b0563631STom Van Eyck         goto exit;
8474b0563631STom Van Eyck     }
8475b0563631STom Van Eyck 
8476b0563631STom Van Eyck     if (PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 ||
8477b0563631STom Van Eyck         PSA_ALG_IS_HASH(cipher_suite->hash) == 0) {
8478b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
8479b0563631STom Van Eyck         goto exit;
8480b0563631STom Van Eyck     }
8481b0563631STom Van Eyck 
8482b0563631STom Van Eyck     memset(&operation->data.inputs, 0, sizeof(operation->data.inputs));
8483b0563631STom Van Eyck 
8484b0563631STom Van Eyck     operation->alg = cipher_suite->algorithm;
8485b0563631STom Van Eyck     operation->primitive = PSA_PAKE_PRIMITIVE(cipher_suite->type,
8486b0563631STom Van Eyck                                               cipher_suite->family, cipher_suite->bits);
8487b0563631STom Van Eyck     operation->data.inputs.cipher_suite = *cipher_suite;
8488b0563631STom Van Eyck 
8489b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8490b0563631STom Van Eyck     if (operation->alg == PSA_ALG_JPAKE) {
8491b0563631STom Van Eyck         psa_jpake_computation_stage_t *computation_stage =
8492b0563631STom Van Eyck             &operation->computation_stage.jpake;
8493b0563631STom Van Eyck 
8494b0563631STom Van Eyck         memset(computation_stage, 0, sizeof(*computation_stage));
8495b0563631STom Van Eyck         computation_stage->step = PSA_PAKE_STEP_KEY_SHARE;
8496b0563631STom Van Eyck     } else
8497b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
8498b0563631STom Van Eyck     {
8499b0563631STom Van Eyck         status = PSA_ERROR_NOT_SUPPORTED;
8500b0563631STom Van Eyck         goto exit;
8501b0563631STom Van Eyck     }
8502b0563631STom Van Eyck 
8503b0563631STom Van Eyck     operation->stage = PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS;
8504b0563631STom Van Eyck 
8505b0563631STom Van Eyck     return PSA_SUCCESS;
8506b0563631STom Van Eyck exit:
8507b0563631STom Van Eyck     psa_pake_abort(operation);
8508b0563631STom Van Eyck     return status;
8509b0563631STom Van Eyck }
8510b0563631STom Van Eyck 
8511b0563631STom Van Eyck psa_status_t psa_pake_set_password_key(
8512b0563631STom Van Eyck     psa_pake_operation_t *operation,
8513b0563631STom Van Eyck     mbedtls_svc_key_id_t password)
8514b0563631STom Van Eyck {
8515b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8516b0563631STom Van Eyck     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
8517b0563631STom Van Eyck     psa_key_slot_t *slot = NULL;
8518b0563631STom Van Eyck     psa_key_type_t type;
8519b0563631STom Van Eyck 
8520b0563631STom Van Eyck     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
8521b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8522b0563631STom Van Eyck         goto exit;
8523b0563631STom Van Eyck     }
8524b0563631STom Van Eyck 
8525b0563631STom Van Eyck     status = psa_get_and_lock_key_slot_with_policy(password, &slot,
8526b0563631STom Van Eyck                                                    PSA_KEY_USAGE_DERIVE,
8527b0563631STom Van Eyck                                                    operation->alg);
8528b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8529b0563631STom Van Eyck         goto exit;
8530b0563631STom Van Eyck     }
8531b0563631STom Van Eyck 
8532b0563631STom Van Eyck     type = psa_get_key_type(&slot->attr);
8533b0563631STom Van Eyck 
8534b0563631STom Van Eyck     if (type != PSA_KEY_TYPE_PASSWORD &&
8535b0563631STom Van Eyck         type != PSA_KEY_TYPE_PASSWORD_HASH) {
8536b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
8537b0563631STom Van Eyck         goto exit;
8538b0563631STom Van Eyck     }
8539b0563631STom Van Eyck 
8540b0563631STom Van Eyck     operation->data.inputs.password = mbedtls_calloc(1, slot->key.bytes);
8541b0563631STom Van Eyck     if (operation->data.inputs.password == NULL) {
8542b0563631STom Van Eyck         status = PSA_ERROR_INSUFFICIENT_MEMORY;
8543b0563631STom Van Eyck         goto exit;
8544b0563631STom Van Eyck     }
8545b0563631STom Van Eyck 
8546b0563631STom Van Eyck     memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes);
8547b0563631STom Van Eyck     operation->data.inputs.password_len = slot->key.bytes;
8548b0563631STom Van Eyck     operation->data.inputs.attributes = slot->attr;
8549b0563631STom Van Eyck 
8550b0563631STom Van Eyck exit:
8551b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8552b0563631STom Van Eyck         psa_pake_abort(operation);
8553b0563631STom Van Eyck     }
8554b0563631STom Van Eyck     unlock_status = psa_unregister_read_under_mutex(slot);
8555b0563631STom Van Eyck     return (status == PSA_SUCCESS) ? unlock_status : status;
8556b0563631STom Van Eyck }
8557b0563631STom Van Eyck 
8558b0563631STom Van Eyck psa_status_t psa_pake_set_user(
8559b0563631STom Van Eyck     psa_pake_operation_t *operation,
8560b0563631STom Van Eyck     const uint8_t *user_id_external,
8561b0563631STom Van Eyck     size_t user_id_len)
8562b0563631STom Van Eyck {
8563b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8564b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(user_id_external, user_id);
8565b0563631STom Van Eyck 
8566b0563631STom Van Eyck     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
8567b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8568b0563631STom Van Eyck         goto exit;
8569b0563631STom Van Eyck     }
8570b0563631STom Van Eyck 
8571b0563631STom Van Eyck     if (user_id_len == 0) {
8572b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
8573b0563631STom Van Eyck         goto exit;
8574b0563631STom Van Eyck     }
8575b0563631STom Van Eyck 
8576b0563631STom Van Eyck     if (operation->data.inputs.user_len != 0) {
8577b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8578b0563631STom Van Eyck         goto exit;
8579b0563631STom Van Eyck     }
8580b0563631STom Van Eyck 
8581b0563631STom Van Eyck     operation->data.inputs.user = mbedtls_calloc(1, user_id_len);
8582b0563631STom Van Eyck     if (operation->data.inputs.user == NULL) {
8583b0563631STom Van Eyck         status = PSA_ERROR_INSUFFICIENT_MEMORY;
8584b0563631STom Van Eyck         goto exit;
8585b0563631STom Van Eyck     }
8586b0563631STom Van Eyck 
8587b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(user_id_external, user_id_len, user_id);
8588b0563631STom Van Eyck 
8589b0563631STom Van Eyck     memcpy(operation->data.inputs.user, user_id, user_id_len);
8590b0563631STom Van Eyck     operation->data.inputs.user_len = user_id_len;
8591b0563631STom Van Eyck 
8592b0563631STom Van Eyck     status = PSA_SUCCESS;
8593b0563631STom Van Eyck 
8594b0563631STom Van Eyck exit:
8595b0563631STom Van Eyck     LOCAL_INPUT_FREE(user_id_external, user_id);
8596b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8597b0563631STom Van Eyck         psa_pake_abort(operation);
8598b0563631STom Van Eyck     }
8599b0563631STom Van Eyck     return status;
8600b0563631STom Van Eyck }
8601b0563631STom Van Eyck 
8602b0563631STom Van Eyck psa_status_t psa_pake_set_peer(
8603b0563631STom Van Eyck     psa_pake_operation_t *operation,
8604b0563631STom Van Eyck     const uint8_t *peer_id_external,
8605b0563631STom Van Eyck     size_t peer_id_len)
8606b0563631STom Van Eyck {
8607b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8608b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(peer_id_external, peer_id);
8609b0563631STom Van Eyck 
8610b0563631STom Van Eyck     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
8611b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8612b0563631STom Van Eyck         goto exit;
8613b0563631STom Van Eyck     }
8614b0563631STom Van Eyck 
8615b0563631STom Van Eyck     if (peer_id_len == 0) {
8616b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
8617b0563631STom Van Eyck         goto exit;
8618b0563631STom Van Eyck     }
8619b0563631STom Van Eyck 
8620b0563631STom Van Eyck     if (operation->data.inputs.peer_len != 0) {
8621b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8622b0563631STom Van Eyck         goto exit;
8623b0563631STom Van Eyck     }
8624b0563631STom Van Eyck 
8625b0563631STom Van Eyck     operation->data.inputs.peer = mbedtls_calloc(1, peer_id_len);
8626b0563631STom Van Eyck     if (operation->data.inputs.peer == NULL) {
8627b0563631STom Van Eyck         status = PSA_ERROR_INSUFFICIENT_MEMORY;
8628b0563631STom Van Eyck         goto exit;
8629b0563631STom Van Eyck     }
8630b0563631STom Van Eyck 
8631b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(peer_id_external, peer_id_len, peer_id);
8632b0563631STom Van Eyck 
8633b0563631STom Van Eyck     memcpy(operation->data.inputs.peer, peer_id, peer_id_len);
8634b0563631STom Van Eyck     operation->data.inputs.peer_len = peer_id_len;
8635b0563631STom Van Eyck 
8636b0563631STom Van Eyck     status = PSA_SUCCESS;
8637b0563631STom Van Eyck 
8638b0563631STom Van Eyck exit:
8639b0563631STom Van Eyck     LOCAL_INPUT_FREE(peer_id_external, peer_id);
8640b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8641b0563631STom Van Eyck         psa_pake_abort(operation);
8642b0563631STom Van Eyck     }
8643b0563631STom Van Eyck     return status;
8644b0563631STom Van Eyck }
8645b0563631STom Van Eyck 
8646b0563631STom Van Eyck psa_status_t psa_pake_set_role(
8647b0563631STom Van Eyck     psa_pake_operation_t *operation,
8648b0563631STom Van Eyck     psa_pake_role_t role)
8649b0563631STom Van Eyck {
8650b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8651b0563631STom Van Eyck 
8652b0563631STom Van Eyck     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
8653b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8654b0563631STom Van Eyck         goto exit;
8655b0563631STom Van Eyck     }
8656b0563631STom Van Eyck 
8657b0563631STom Van Eyck     switch (operation->alg) {
8658b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8659b0563631STom Van Eyck         case PSA_ALG_JPAKE:
8660b0563631STom Van Eyck             if (role == PSA_PAKE_ROLE_NONE) {
8661b0563631STom Van Eyck                 return PSA_SUCCESS;
8662b0563631STom Van Eyck             }
8663b0563631STom Van Eyck             status = PSA_ERROR_INVALID_ARGUMENT;
8664b0563631STom Van Eyck             break;
8665b0563631STom Van Eyck #endif
8666b0563631STom Van Eyck         default:
8667b0563631STom Van Eyck             (void) role;
8668b0563631STom Van Eyck             status = PSA_ERROR_NOT_SUPPORTED;
8669b0563631STom Van Eyck             goto exit;
8670b0563631STom Van Eyck     }
8671b0563631STom Van Eyck exit:
8672b0563631STom Van Eyck     psa_pake_abort(operation);
8673b0563631STom Van Eyck     return status;
8674b0563631STom Van Eyck }
8675b0563631STom Van Eyck 
8676b0563631STom Van Eyck /* Auxiliary function to convert core computation stage to single driver step. */
8677b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8678b0563631STom Van Eyck static psa_crypto_driver_pake_step_t convert_jpake_computation_stage_to_driver_step(
8679b0563631STom Van Eyck     psa_jpake_computation_stage_t *stage)
8680b0563631STom Van Eyck {
8681b0563631STom Van Eyck     psa_crypto_driver_pake_step_t key_share_step;
8682b0563631STom Van Eyck     if (stage->round == PSA_JPAKE_FIRST) {
8683b0563631STom Van Eyck         int is_x1;
8684b0563631STom Van Eyck 
8685b0563631STom Van Eyck         if (stage->io_mode == PSA_JPAKE_OUTPUT) {
8686b0563631STom Van Eyck             is_x1 = (stage->outputs < 1);
8687b0563631STom Van Eyck         } else {
8688b0563631STom Van Eyck             is_x1 = (stage->inputs < 1);
8689b0563631STom Van Eyck         }
8690b0563631STom Van Eyck 
8691b0563631STom Van Eyck         key_share_step = is_x1 ?
8692b0563631STom Van Eyck                          PSA_JPAKE_X1_STEP_KEY_SHARE :
8693b0563631STom Van Eyck                          PSA_JPAKE_X2_STEP_KEY_SHARE;
8694b0563631STom Van Eyck     } else if (stage->round == PSA_JPAKE_SECOND) {
8695b0563631STom Van Eyck         key_share_step = (stage->io_mode == PSA_JPAKE_OUTPUT) ?
8696b0563631STom Van Eyck                          PSA_JPAKE_X2S_STEP_KEY_SHARE :
8697b0563631STom Van Eyck                          PSA_JPAKE_X4S_STEP_KEY_SHARE;
8698b0563631STom Van Eyck     } else {
8699b0563631STom Van Eyck         return PSA_JPAKE_STEP_INVALID;
8700b0563631STom Van Eyck     }
8701b0563631STom Van Eyck     return (psa_crypto_driver_pake_step_t) (key_share_step + stage->step - PSA_PAKE_STEP_KEY_SHARE);
8702b0563631STom Van Eyck }
8703b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
8704b0563631STom Van Eyck 
8705b0563631STom Van Eyck static psa_status_t psa_pake_complete_inputs(
8706b0563631STom Van Eyck     psa_pake_operation_t *operation)
8707b0563631STom Van Eyck {
8708b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8709b0563631STom Van Eyck     /* Create copy of the inputs on stack as inputs share memory
8710b0563631STom Van Eyck        with the driver context which will be setup by the driver. */
8711b0563631STom Van Eyck     psa_crypto_driver_pake_inputs_t inputs = operation->data.inputs;
8712b0563631STom Van Eyck 
8713b0563631STom Van Eyck     if (inputs.password_len == 0) {
8714b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8715b0563631STom Van Eyck     }
8716b0563631STom Van Eyck 
8717b0563631STom Van Eyck     if (operation->alg == PSA_ALG_JPAKE) {
8718b0563631STom Van Eyck         if (inputs.user_len == 0 || inputs.peer_len == 0) {
8719b0563631STom Van Eyck             return PSA_ERROR_BAD_STATE;
8720b0563631STom Van Eyck         }
8721b0563631STom Van Eyck     }
8722b0563631STom Van Eyck 
8723b0563631STom Van Eyck     /* Clear driver context */
8724b0563631STom Van Eyck     mbedtls_platform_zeroize(&operation->data, sizeof(operation->data));
8725b0563631STom Van Eyck 
8726b0563631STom Van Eyck     status = psa_driver_wrapper_pake_setup(operation, &inputs);
8727b0563631STom Van Eyck 
8728b0563631STom Van Eyck     /* Driver is responsible for creating its own copy of the password. */
8729b0563631STom Van Eyck     mbedtls_zeroize_and_free(inputs.password, inputs.password_len);
8730b0563631STom Van Eyck 
8731b0563631STom Van Eyck     /* User and peer are translated to role. */
8732b0563631STom Van Eyck     mbedtls_free(inputs.user);
8733b0563631STom Van Eyck     mbedtls_free(inputs.peer);
8734b0563631STom Van Eyck 
8735b0563631STom Van Eyck     if (status == PSA_SUCCESS) {
8736b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8737b0563631STom Van Eyck         if (operation->alg == PSA_ALG_JPAKE) {
8738b0563631STom Van Eyck             operation->stage = PSA_PAKE_OPERATION_STAGE_COMPUTATION;
8739b0563631STom Van Eyck         } else
8740b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
8741b0563631STom Van Eyck         {
8742b0563631STom Van Eyck             status = PSA_ERROR_NOT_SUPPORTED;
8743b0563631STom Van Eyck         }
8744b0563631STom Van Eyck     }
8745b0563631STom Van Eyck     return status;
8746b0563631STom Van Eyck }
8747b0563631STom Van Eyck 
8748b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8749b0563631STom Van Eyck static psa_status_t psa_jpake_prologue(
8750b0563631STom Van Eyck     psa_pake_operation_t *operation,
8751b0563631STom Van Eyck     psa_pake_step_t step,
8752b0563631STom Van Eyck     psa_jpake_io_mode_t io_mode)
8753b0563631STom Van Eyck {
8754b0563631STom Van Eyck     if (step != PSA_PAKE_STEP_KEY_SHARE &&
8755b0563631STom Van Eyck         step != PSA_PAKE_STEP_ZK_PUBLIC &&
8756b0563631STom Van Eyck         step != PSA_PAKE_STEP_ZK_PROOF) {
8757b0563631STom Van Eyck         return PSA_ERROR_INVALID_ARGUMENT;
8758b0563631STom Van Eyck     }
8759b0563631STom Van Eyck 
8760b0563631STom Van Eyck     psa_jpake_computation_stage_t *computation_stage =
8761b0563631STom Van Eyck         &operation->computation_stage.jpake;
8762b0563631STom Van Eyck 
8763b0563631STom Van Eyck     if (computation_stage->round != PSA_JPAKE_FIRST &&
8764b0563631STom Van Eyck         computation_stage->round != PSA_JPAKE_SECOND) {
8765b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8766b0563631STom Van Eyck     }
8767b0563631STom Van Eyck 
8768b0563631STom Van Eyck     /* Check that the step we are given is the one we were expecting */
8769b0563631STom Van Eyck     if (step != computation_stage->step) {
8770b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8771b0563631STom Van Eyck     }
8772b0563631STom Van Eyck 
8773b0563631STom Van Eyck     if (step == PSA_PAKE_STEP_KEY_SHARE &&
8774b0563631STom Van Eyck         computation_stage->inputs == 0 &&
8775b0563631STom Van Eyck         computation_stage->outputs == 0) {
8776b0563631STom Van Eyck         /* Start of the round, so function decides whether we are inputting
8777b0563631STom Van Eyck          * or outputting */
8778b0563631STom Van Eyck         computation_stage->io_mode = io_mode;
8779b0563631STom Van Eyck     } else if (computation_stage->io_mode != io_mode) {
8780b0563631STom Van Eyck         /* Middle of the round so the mode we are in must match the function
8781b0563631STom Van Eyck          * called by the user */
8782b0563631STom Van Eyck         return PSA_ERROR_BAD_STATE;
8783b0563631STom Van Eyck     }
8784b0563631STom Van Eyck 
8785b0563631STom Van Eyck     return PSA_SUCCESS;
8786b0563631STom Van Eyck }
8787b0563631STom Van Eyck 
8788b0563631STom Van Eyck static psa_status_t psa_jpake_epilogue(
8789b0563631STom Van Eyck     psa_pake_operation_t *operation,
8790b0563631STom Van Eyck     psa_jpake_io_mode_t io_mode)
8791b0563631STom Van Eyck {
8792b0563631STom Van Eyck     psa_jpake_computation_stage_t *stage =
8793b0563631STom Van Eyck         &operation->computation_stage.jpake;
8794b0563631STom Van Eyck 
8795b0563631STom Van Eyck     if (stage->step == PSA_PAKE_STEP_ZK_PROOF) {
8796b0563631STom Van Eyck         /* End of an input/output */
8797b0563631STom Van Eyck         if (io_mode == PSA_JPAKE_INPUT) {
8798b0563631STom Van Eyck             stage->inputs++;
8799b0563631STom Van Eyck             if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round)) {
8800b0563631STom Van Eyck                 stage->io_mode = PSA_JPAKE_OUTPUT;
8801b0563631STom Van Eyck             }
8802b0563631STom Van Eyck         }
8803b0563631STom Van Eyck         if (io_mode == PSA_JPAKE_OUTPUT) {
8804b0563631STom Van Eyck             stage->outputs++;
8805b0563631STom Van Eyck             if (stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) {
8806b0563631STom Van Eyck                 stage->io_mode = PSA_JPAKE_INPUT;
8807b0563631STom Van Eyck             }
8808b0563631STom Van Eyck         }
8809b0563631STom Van Eyck         if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round) &&
8810b0563631STom Van Eyck             stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) {
8811b0563631STom Van Eyck             /* End of a round, move to the next round */
8812b0563631STom Van Eyck             stage->inputs = 0;
8813b0563631STom Van Eyck             stage->outputs = 0;
8814b0563631STom Van Eyck             stage->round++;
8815b0563631STom Van Eyck         }
8816b0563631STom Van Eyck         stage->step = PSA_PAKE_STEP_KEY_SHARE;
8817b0563631STom Van Eyck     } else {
8818b0563631STom Van Eyck         stage->step++;
8819b0563631STom Van Eyck     }
8820b0563631STom Van Eyck     return PSA_SUCCESS;
8821b0563631STom Van Eyck }
8822b0563631STom Van Eyck 
8823b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
8824b0563631STom Van Eyck 
8825b0563631STom Van Eyck psa_status_t psa_pake_output(
8826b0563631STom Van Eyck     psa_pake_operation_t *operation,
8827b0563631STom Van Eyck     psa_pake_step_t step,
8828b0563631STom Van Eyck     uint8_t *output_external,
8829b0563631STom Van Eyck     size_t output_size,
8830b0563631STom Van Eyck     size_t *output_length)
8831b0563631STom Van Eyck {
8832b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8833b0563631STom Van Eyck     psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;
8834b0563631STom Van Eyck     LOCAL_OUTPUT_DECLARE(output_external, output);
8835b0563631STom Van Eyck     *output_length = 0;
8836b0563631STom Van Eyck 
8837b0563631STom Van Eyck     if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
8838b0563631STom Van Eyck         status = psa_pake_complete_inputs(operation);
8839b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
8840b0563631STom Van Eyck             goto exit;
8841b0563631STom Van Eyck         }
8842b0563631STom Van Eyck     }
8843b0563631STom Van Eyck 
8844b0563631STom Van Eyck     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
8845b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8846b0563631STom Van Eyck         goto exit;
8847b0563631STom Van Eyck     }
8848b0563631STom Van Eyck 
8849b0563631STom Van Eyck     if (output_size == 0) {
8850b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
8851b0563631STom Van Eyck         goto exit;
8852b0563631STom Van Eyck     }
8853b0563631STom Van Eyck 
8854b0563631STom Van Eyck     switch (operation->alg) {
8855b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8856b0563631STom Van Eyck         case PSA_ALG_JPAKE:
8857b0563631STom Van Eyck             status = psa_jpake_prologue(operation, step, PSA_JPAKE_OUTPUT);
8858b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
8859b0563631STom Van Eyck                 goto exit;
8860b0563631STom Van Eyck             }
8861b0563631STom Van Eyck             driver_step = convert_jpake_computation_stage_to_driver_step(
8862b0563631STom Van Eyck                 &operation->computation_stage.jpake);
8863b0563631STom Van Eyck             break;
8864b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
8865b0563631STom Van Eyck         default:
8866b0563631STom Van Eyck             (void) step;
8867b0563631STom Van Eyck             status = PSA_ERROR_NOT_SUPPORTED;
8868b0563631STom Van Eyck             goto exit;
8869b0563631STom Van Eyck     }
8870b0563631STom Van Eyck 
8871b0563631STom Van Eyck     LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
8872b0563631STom Van Eyck 
8873b0563631STom Van Eyck     status = psa_driver_wrapper_pake_output(operation, driver_step,
8874b0563631STom Van Eyck                                             output, output_size, output_length);
8875b0563631STom Van Eyck 
8876b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8877b0563631STom Van Eyck         goto exit;
8878b0563631STom Van Eyck     }
8879b0563631STom Van Eyck 
8880b0563631STom Van Eyck     switch (operation->alg) {
8881b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8882b0563631STom Van Eyck         case PSA_ALG_JPAKE:
8883b0563631STom Van Eyck             status = psa_jpake_epilogue(operation, PSA_JPAKE_OUTPUT);
8884b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
8885b0563631STom Van Eyck                 goto exit;
8886b0563631STom Van Eyck             }
8887b0563631STom Van Eyck             break;
8888b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
8889b0563631STom Van Eyck         default:
8890b0563631STom Van Eyck             status = PSA_ERROR_NOT_SUPPORTED;
8891b0563631STom Van Eyck             goto exit;
8892b0563631STom Van Eyck     }
8893b0563631STom Van Eyck 
8894b0563631STom Van Eyck exit:
8895b0563631STom Van Eyck     LOCAL_OUTPUT_FREE(output_external, output);
8896b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8897b0563631STom Van Eyck         psa_pake_abort(operation);
8898b0563631STom Van Eyck     }
8899b0563631STom Van Eyck     return status;
8900b0563631STom Van Eyck }
8901b0563631STom Van Eyck 
8902b0563631STom Van Eyck psa_status_t psa_pake_input(
8903b0563631STom Van Eyck     psa_pake_operation_t *operation,
8904b0563631STom Van Eyck     psa_pake_step_t step,
8905b0563631STom Van Eyck     const uint8_t *input_external,
8906b0563631STom Van Eyck     size_t input_length)
8907b0563631STom Van Eyck {
8908b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8909b0563631STom Van Eyck     psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;
8910b0563631STom Van Eyck     const size_t max_input_length = (size_t) PSA_PAKE_INPUT_SIZE(operation->alg,
8911b0563631STom Van Eyck                                                                  operation->primitive,
8912b0563631STom Van Eyck                                                                  step);
8913b0563631STom Van Eyck     LOCAL_INPUT_DECLARE(input_external, input);
8914b0563631STom Van Eyck 
8915b0563631STom Van Eyck     if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
8916b0563631STom Van Eyck         status = psa_pake_complete_inputs(operation);
8917b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
8918b0563631STom Van Eyck             goto exit;
8919b0563631STom Van Eyck         }
8920b0563631STom Van Eyck     }
8921b0563631STom Van Eyck 
8922b0563631STom Van Eyck     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
8923b0563631STom Van Eyck         status =  PSA_ERROR_BAD_STATE;
8924b0563631STom Van Eyck         goto exit;
8925b0563631STom Van Eyck     }
8926b0563631STom Van Eyck 
8927b0563631STom Van Eyck     if (input_length == 0 || input_length > max_input_length) {
8928b0563631STom Van Eyck         status = PSA_ERROR_INVALID_ARGUMENT;
8929b0563631STom Van Eyck         goto exit;
8930b0563631STom Van Eyck     }
8931b0563631STom Van Eyck 
8932b0563631STom Van Eyck     switch (operation->alg) {
8933b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8934b0563631STom Van Eyck         case PSA_ALG_JPAKE:
8935b0563631STom Van Eyck             status = psa_jpake_prologue(operation, step, PSA_JPAKE_INPUT);
8936b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
8937b0563631STom Van Eyck                 goto exit;
8938b0563631STom Van Eyck             }
8939b0563631STom Van Eyck             driver_step = convert_jpake_computation_stage_to_driver_step(
8940b0563631STom Van Eyck                 &operation->computation_stage.jpake);
8941b0563631STom Van Eyck             break;
8942b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
8943b0563631STom Van Eyck         default:
8944b0563631STom Van Eyck             (void) step;
8945b0563631STom Van Eyck             status = PSA_ERROR_NOT_SUPPORTED;
8946b0563631STom Van Eyck             goto exit;
8947b0563631STom Van Eyck     }
8948b0563631STom Van Eyck 
8949b0563631STom Van Eyck     LOCAL_INPUT_ALLOC(input_external, input_length, input);
8950b0563631STom Van Eyck     status = psa_driver_wrapper_pake_input(operation, driver_step,
8951b0563631STom Van Eyck                                            input, input_length);
8952b0563631STom Van Eyck 
8953b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8954b0563631STom Van Eyck         goto exit;
8955b0563631STom Van Eyck     }
8956b0563631STom Van Eyck 
8957b0563631STom Van Eyck     switch (operation->alg) {
8958b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8959b0563631STom Van Eyck         case PSA_ALG_JPAKE:
8960b0563631STom Van Eyck             status = psa_jpake_epilogue(operation, PSA_JPAKE_INPUT);
8961b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
8962b0563631STom Van Eyck                 goto exit;
8963b0563631STom Van Eyck             }
8964b0563631STom Van Eyck             break;
8965b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
8966b0563631STom Van Eyck         default:
8967b0563631STom Van Eyck             status = PSA_ERROR_NOT_SUPPORTED;
8968b0563631STom Van Eyck             goto exit;
8969b0563631STom Van Eyck     }
8970b0563631STom Van Eyck 
8971b0563631STom Van Eyck exit:
8972b0563631STom Van Eyck     LOCAL_INPUT_FREE(input_external, input);
8973b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
8974b0563631STom Van Eyck         psa_pake_abort(operation);
8975b0563631STom Van Eyck     }
8976b0563631STom Van Eyck     return status;
8977b0563631STom Van Eyck }
8978b0563631STom Van Eyck 
8979b0563631STom Van Eyck psa_status_t psa_pake_get_implicit_key(
8980b0563631STom Van Eyck     psa_pake_operation_t *operation,
8981b0563631STom Van Eyck     psa_key_derivation_operation_t *output)
8982b0563631STom Van Eyck {
8983b0563631STom Van Eyck     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
8984b0563631STom Van Eyck     psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
8985b0563631STom Van Eyck     uint8_t shared_key[MBEDTLS_PSA_JPAKE_BUFFER_SIZE];
8986b0563631STom Van Eyck     size_t shared_key_len = 0;
8987b0563631STom Van Eyck 
8988b0563631STom Van Eyck     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
8989b0563631STom Van Eyck         status = PSA_ERROR_BAD_STATE;
8990b0563631STom Van Eyck         goto exit;
8991b0563631STom Van Eyck     }
8992b0563631STom Van Eyck 
8993b0563631STom Van Eyck #if defined(PSA_WANT_ALG_JPAKE)
8994b0563631STom Van Eyck     if (operation->alg == PSA_ALG_JPAKE) {
8995b0563631STom Van Eyck         psa_jpake_computation_stage_t *computation_stage =
8996b0563631STom Van Eyck             &operation->computation_stage.jpake;
8997b0563631STom Van Eyck         if (computation_stage->round != PSA_JPAKE_FINISHED) {
8998b0563631STom Van Eyck             status = PSA_ERROR_BAD_STATE;
8999b0563631STom Van Eyck             goto exit;
9000b0563631STom Van Eyck         }
9001b0563631STom Van Eyck     } else
9002b0563631STom Van Eyck #endif /* PSA_WANT_ALG_JPAKE */
9003b0563631STom Van Eyck     {
9004b0563631STom Van Eyck         status = PSA_ERROR_NOT_SUPPORTED;
9005b0563631STom Van Eyck         goto exit;
9006b0563631STom Van Eyck     }
9007b0563631STom Van Eyck 
9008b0563631STom Van Eyck     status = psa_driver_wrapper_pake_get_implicit_key(operation,
9009b0563631STom Van Eyck                                                       shared_key,
9010b0563631STom Van Eyck                                                       sizeof(shared_key),
9011b0563631STom Van Eyck                                                       &shared_key_len);
9012b0563631STom Van Eyck 
9013b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
9014b0563631STom Van Eyck         goto exit;
9015b0563631STom Van Eyck     }
9016b0563631STom Van Eyck 
9017b0563631STom Van Eyck     status = psa_key_derivation_input_bytes(output,
9018b0563631STom Van Eyck                                             PSA_KEY_DERIVATION_INPUT_SECRET,
9019b0563631STom Van Eyck                                             shared_key,
9020b0563631STom Van Eyck                                             shared_key_len);
9021b0563631STom Van Eyck 
9022b0563631STom Van Eyck     mbedtls_platform_zeroize(shared_key, sizeof(shared_key));
9023b0563631STom Van Eyck exit:
9024b0563631STom Van Eyck     abort_status = psa_pake_abort(operation);
9025b0563631STom Van Eyck     return status == PSA_SUCCESS ? abort_status : status;
9026b0563631STom Van Eyck }
9027b0563631STom Van Eyck 
9028b0563631STom Van Eyck psa_status_t psa_pake_abort(
9029b0563631STom Van Eyck     psa_pake_operation_t *operation)
9030b0563631STom Van Eyck {
9031b0563631STom Van Eyck     psa_status_t status = PSA_SUCCESS;
9032b0563631STom Van Eyck 
9033b0563631STom Van Eyck     if (operation->stage == PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
9034b0563631STom Van Eyck         status = psa_driver_wrapper_pake_abort(operation);
9035b0563631STom Van Eyck     }
9036b0563631STom Van Eyck 
9037b0563631STom Van Eyck     if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
9038b0563631STom Van Eyck         if (operation->data.inputs.password != NULL) {
9039b0563631STom Van Eyck             mbedtls_zeroize_and_free(operation->data.inputs.password,
9040b0563631STom Van Eyck                                      operation->data.inputs.password_len);
9041b0563631STom Van Eyck         }
9042b0563631STom Van Eyck         if (operation->data.inputs.user != NULL) {
9043b0563631STom Van Eyck             mbedtls_free(operation->data.inputs.user);
9044b0563631STom Van Eyck         }
9045b0563631STom Van Eyck         if (operation->data.inputs.peer != NULL) {
9046b0563631STom Van Eyck             mbedtls_free(operation->data.inputs.peer);
9047b0563631STom Van Eyck         }
9048b0563631STom Van Eyck     }
9049b0563631STom Van Eyck     memset(operation, 0, sizeof(psa_pake_operation_t));
9050b0563631STom Van Eyck 
9051b0563631STom Van Eyck     return status;
9052b0563631STom Van Eyck }
9053b0563631STom Van Eyck #endif /* PSA_WANT_ALG_SOME_PAKE */
9054b0563631STom Van Eyck 
9055b0563631STom Van Eyck /* Memory copying test hooks. These are called before input copy, after input
9056b0563631STom Van Eyck  * copy, before output copy and after output copy, respectively.
9057b0563631STom Van Eyck  * They are used by memory-poisoning tests to temporarily unpoison buffers
9058b0563631STom Van Eyck  * while they are copied. */
9059b0563631STom Van Eyck #if defined(MBEDTLS_TEST_HOOKS)
9060b0563631STom Van Eyck void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL;
9061b0563631STom Van Eyck void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL;
9062b0563631STom Van Eyck void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL;
9063b0563631STom Van Eyck void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL;
9064b0563631STom Van Eyck #endif
9065b0563631STom Van Eyck 
9066b0563631STom Van Eyck /** Copy from an input buffer to a local copy.
9067b0563631STom Van Eyck  *
9068b0563631STom Van Eyck  * \param[in] input             Pointer to input buffer.
9069b0563631STom Van Eyck  * \param[in] input_len         Length of the input buffer.
9070b0563631STom Van Eyck  * \param[out] input_copy       Pointer to a local copy in which to store the input data.
9071b0563631STom Van Eyck  * \param[out] input_copy_len   Length of the local copy buffer.
9072b0563631STom Van Eyck  * \return                      #PSA_SUCCESS, if the buffer was successfully
9073b0563631STom Van Eyck  *                              copied.
9074b0563631STom Van Eyck  * \return                      #PSA_ERROR_CORRUPTION_DETECTED, if the local
9075b0563631STom Van Eyck  *                              copy is too small to hold contents of the
9076b0563631STom Van Eyck  *                              input buffer.
9077b0563631STom Van Eyck  */
9078b0563631STom Van Eyck MBEDTLS_STATIC_TESTABLE
9079b0563631STom Van Eyck psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len,
9080b0563631STom Van Eyck                                    uint8_t *input_copy, size_t input_copy_len)
9081b0563631STom Van Eyck {
9082b0563631STom Van Eyck     if (input_len > input_copy_len) {
9083b0563631STom Van Eyck         return PSA_ERROR_CORRUPTION_DETECTED;
9084b0563631STom Van Eyck     }
9085b0563631STom Van Eyck 
9086b0563631STom Van Eyck #if defined(MBEDTLS_TEST_HOOKS)
9087b0563631STom Van Eyck     if (psa_input_pre_copy_hook != NULL) {
9088b0563631STom Van Eyck         psa_input_pre_copy_hook(input, input_len);
9089b0563631STom Van Eyck     }
9090b0563631STom Van Eyck #endif
9091b0563631STom Van Eyck 
9092b0563631STom Van Eyck     if (input_len > 0) {
9093b0563631STom Van Eyck         memcpy(input_copy, input, input_len);
9094b0563631STom Van Eyck     }
9095b0563631STom Van Eyck 
9096b0563631STom Van Eyck #if defined(MBEDTLS_TEST_HOOKS)
9097b0563631STom Van Eyck     if (psa_input_post_copy_hook != NULL) {
9098b0563631STom Van Eyck         psa_input_post_copy_hook(input, input_len);
9099b0563631STom Van Eyck     }
9100b0563631STom Van Eyck #endif
9101b0563631STom Van Eyck 
9102b0563631STom Van Eyck     return PSA_SUCCESS;
9103b0563631STom Van Eyck }
9104b0563631STom Van Eyck 
9105b0563631STom Van Eyck /** Copy from a local output buffer into a user-supplied one.
9106b0563631STom Van Eyck  *
9107b0563631STom Van Eyck  * \param[in] output_copy       Pointer to a local buffer containing the output.
9108b0563631STom Van Eyck  * \param[in] output_copy_len   Length of the local buffer.
9109b0563631STom Van Eyck  * \param[out] output           Pointer to user-supplied output buffer.
9110b0563631STom Van Eyck  * \param[out] output_len       Length of the user-supplied output buffer.
9111b0563631STom Van Eyck  * \return                      #PSA_SUCCESS, if the buffer was successfully
9112b0563631STom Van Eyck  *                              copied.
9113b0563631STom Van Eyck  * \return                      #PSA_ERROR_BUFFER_TOO_SMALL, if the
9114b0563631STom Van Eyck  *                              user-supplied output buffer is too small to
9115b0563631STom Van Eyck  *                              hold the contents of the local buffer.
9116b0563631STom Van Eyck  */
9117b0563631STom Van Eyck MBEDTLS_STATIC_TESTABLE
9118b0563631STom Van Eyck psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len,
9119b0563631STom Van Eyck                                     uint8_t *output, size_t output_len)
9120b0563631STom Van Eyck {
9121b0563631STom Van Eyck     if (output_len < output_copy_len) {
9122b0563631STom Van Eyck         return PSA_ERROR_BUFFER_TOO_SMALL;
9123b0563631STom Van Eyck     }
9124b0563631STom Van Eyck 
9125b0563631STom Van Eyck #if defined(MBEDTLS_TEST_HOOKS)
9126b0563631STom Van Eyck     if (psa_output_pre_copy_hook != NULL) {
9127b0563631STom Van Eyck         psa_output_pre_copy_hook(output, output_len);
9128b0563631STom Van Eyck     }
9129b0563631STom Van Eyck #endif
9130b0563631STom Van Eyck 
9131b0563631STom Van Eyck     if (output_copy_len > 0) {
9132b0563631STom Van Eyck         memcpy(output, output_copy, output_copy_len);
9133b0563631STom Van Eyck     }
9134b0563631STom Van Eyck 
9135b0563631STom Van Eyck #if defined(MBEDTLS_TEST_HOOKS)
9136b0563631STom Van Eyck     if (psa_output_post_copy_hook != NULL) {
9137b0563631STom Van Eyck         psa_output_post_copy_hook(output, output_len);
9138b0563631STom Van Eyck     }
9139b0563631STom Van Eyck #endif
9140b0563631STom Van Eyck 
9141b0563631STom Van Eyck     return PSA_SUCCESS;
9142b0563631STom Van Eyck }
9143b0563631STom Van Eyck 
9144b0563631STom Van Eyck psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,
9145b0563631STom Van Eyck                                           psa_crypto_local_input_t *local_input)
9146b0563631STom Van Eyck {
9147b0563631STom Van Eyck     psa_status_t status;
9148b0563631STom Van Eyck 
9149b0563631STom Van Eyck     *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT;
9150b0563631STom Van Eyck 
9151b0563631STom Van Eyck     if (input_len == 0) {
9152b0563631STom Van Eyck         return PSA_SUCCESS;
9153b0563631STom Van Eyck     }
9154b0563631STom Van Eyck 
9155b0563631STom Van Eyck     local_input->buffer = mbedtls_calloc(input_len, 1);
9156b0563631STom Van Eyck     if (local_input->buffer == NULL) {
9157b0563631STom Van Eyck         /* Since we dealt with the zero-length case above, we know that
9158b0563631STom Van Eyck          * a NULL return value means a failure of allocation. */
9159b0563631STom Van Eyck         return PSA_ERROR_INSUFFICIENT_MEMORY;
9160b0563631STom Van Eyck     }
9161b0563631STom Van Eyck     /* From now on, we must free local_input->buffer on error. */
9162b0563631STom Van Eyck 
9163b0563631STom Van Eyck     local_input->length = input_len;
9164b0563631STom Van Eyck 
9165b0563631STom Van Eyck     status = psa_crypto_copy_input(input, input_len,
9166b0563631STom Van Eyck                                    local_input->buffer, local_input->length);
9167b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
9168b0563631STom Van Eyck         goto error;
9169b0563631STom Van Eyck     }
9170b0563631STom Van Eyck 
9171b0563631STom Van Eyck     return PSA_SUCCESS;
9172b0563631STom Van Eyck 
9173b0563631STom Van Eyck error:
9174b0563631STom Van Eyck     mbedtls_free(local_input->buffer);
9175b0563631STom Van Eyck     local_input->buffer = NULL;
9176b0563631STom Van Eyck     local_input->length = 0;
9177b0563631STom Van Eyck     return status;
9178b0563631STom Van Eyck }
9179b0563631STom Van Eyck 
9180b0563631STom Van Eyck void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input)
9181b0563631STom Van Eyck {
9182b0563631STom Van Eyck     mbedtls_free(local_input->buffer);
9183b0563631STom Van Eyck     local_input->buffer = NULL;
9184b0563631STom Van Eyck     local_input->length = 0;
9185b0563631STom Van Eyck }
9186b0563631STom Van Eyck 
9187b0563631STom Van Eyck psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,
9188b0563631STom Van Eyck                                            psa_crypto_local_output_t *local_output)
9189b0563631STom Van Eyck {
9190b0563631STom Van Eyck     *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT;
9191b0563631STom Van Eyck 
9192b0563631STom Van Eyck     if (output_len == 0) {
9193b0563631STom Van Eyck         return PSA_SUCCESS;
9194b0563631STom Van Eyck     }
9195b0563631STom Van Eyck     local_output->buffer = mbedtls_calloc(output_len, 1);
9196b0563631STom Van Eyck     if (local_output->buffer == NULL) {
9197b0563631STom Van Eyck         /* Since we dealt with the zero-length case above, we know that
9198b0563631STom Van Eyck          * a NULL return value means a failure of allocation. */
9199b0563631STom Van Eyck         return PSA_ERROR_INSUFFICIENT_MEMORY;
9200b0563631STom Van Eyck     }
9201b0563631STom Van Eyck     local_output->length = output_len;
9202b0563631STom Van Eyck     local_output->original = output;
9203b0563631STom Van Eyck 
9204b0563631STom Van Eyck     return PSA_SUCCESS;
9205b0563631STom Van Eyck }
9206b0563631STom Van Eyck 
9207b0563631STom Van Eyck psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output)
9208b0563631STom Van Eyck {
9209b0563631STom Van Eyck     psa_status_t status;
9210b0563631STom Van Eyck 
9211b0563631STom Van Eyck     if (local_output->buffer == NULL) {
9212b0563631STom Van Eyck         local_output->length = 0;
9213b0563631STom Van Eyck         return PSA_SUCCESS;
9214b0563631STom Van Eyck     }
9215b0563631STom Van Eyck     if (local_output->original == NULL) {
9216b0563631STom Van Eyck         /* We have an internal copy but nothing to copy back to. */
9217b0563631STom Van Eyck         return PSA_ERROR_CORRUPTION_DETECTED;
9218b0563631STom Van Eyck     }
9219b0563631STom Van Eyck 
9220b0563631STom Van Eyck     status = psa_crypto_copy_output(local_output->buffer, local_output->length,
9221b0563631STom Van Eyck                                     local_output->original, local_output->length);
9222b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
9223b0563631STom Van Eyck         return status;
9224b0563631STom Van Eyck     }
9225b0563631STom Van Eyck 
9226b0563631STom Van Eyck     mbedtls_free(local_output->buffer);
9227b0563631STom Van Eyck     local_output->buffer = NULL;
9228b0563631STom Van Eyck     local_output->length = 0;
9229b0563631STom Van Eyck 
9230b0563631STom Van Eyck     return PSA_SUCCESS;
9231b0563631STom Van Eyck }
9232b0563631STom Van Eyck 
9233b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_C */
9234