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