blob: 031e3bab23cdab01759200d08fe3eac29cf94de5 [file] [log] [blame]
Antonio de Angelis8908f472018-08-31 15:44:25 +01001/*
Antonio de Angelis01a93bc2023-01-20 11:17:14 +00002 * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
Antonio de Angelis8908f472018-08-31 15:44:25 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
Antonio de Angelis202425a2022-04-06 11:13:15 +01007#include <stdbool.h>
Antonio de Angelis8908f472018-08-31 15:44:25 +01008
David Hu6d1a9b62023-02-22 16:54:04 +08009#include "config_tfm.h"
10#include "config_crypto_check.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010011#include "tfm_mbedcrypto_include.h"
12
Antonio de Angelis8908f472018-08-31 15:44:25 +010013#include "tfm_crypto_api.h"
Antonio de Angelis7557e682022-11-30 15:37:51 +000014#include "tfm_crypto_key.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010015#include "tfm_crypto_defs.h"
Summer Qinc737ece2020-08-28 10:47:26 +080016#include "tfm_sp_log.h"
Summer Qinca6c1522022-06-17 14:25:55 +080017#include "crypto_check_config.h"
Raef Coles79809c72022-03-02 13:48:20 +000018#include "tfm_plat_crypto_keys.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010019
Antonio de Angelis8f7db7d2022-12-01 12:09:16 +000020#include "crypto_library.h"
21
Xinyu Zhangd755b822022-10-25 11:18:09 +080022#if CRYPTO_NV_SEED
Raef Coles618fc152021-06-18 09:26:46 +010023#include "tfm_plat_crypto_nv_seed.h"
24#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +080025
Raef Colesd2485af2019-10-30 10:15:33 +000026#ifdef CRYPTO_HW_ACCELERATOR
27#include "crypto_hw.h"
Michel Jaouenf41c6422021-10-07 14:38:08 +020028#endif /* CRYPTO_HW_ACCELERATOR */
Raef Colesd2485af2019-10-30 10:15:33 +000029
Ken Liub671d682022-05-12 20:39:29 +080030#include <string.h>
Kevin Pengfe730cc2022-04-11 17:48:42 +080031#include "psa/framework_feature.h"
Jamie Foxcc31d402019-01-28 17:13:52 +000032#include "psa/service.h"
Edison Aicc4c6162019-06-21 13:52:49 +080033#include "psa_manifest/tfm_crypto.h"
Antonio de Angelis4743e672019-04-11 11:38:48 +010034
35/**
Antonio de Angelis4743e672019-04-11 11:38:48 +010036 * \brief Aligns a value x up to an alignment a.
37 */
38#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
39
40/**
41 * \brief Maximum alignment required by any iovec parameters to the TF-M Crypto
42 * partition.
43 */
44#define TFM_CRYPTO_IOVEC_ALIGNMENT (4u)
45
Kevin Pengfe730cc2022-04-11 17:48:42 +080046#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
47static int32_t g_client_id;
48
49static void tfm_crypto_set_caller_id(int32_t id)
50{
51 g_client_id = id;
52}
53
54psa_status_t tfm_crypto_get_caller_id(int32_t *id)
55{
56 *id = g_client_id;
57 return PSA_SUCCESS;
58}
59
60static psa_status_t tfm_crypto_init_iovecs(const psa_msg_t *msg,
61 psa_invec in_vec[],
62 size_t in_len,
63 psa_outvec out_vec[],
64 size_t out_len)
65{
66 uint32_t i;
67
68 /* Map from the second element as the first is read when parsing */
69 for (i = 1; i < in_len; i++) {
70 in_vec[i].len = msg->in_size[i];
71 if (in_vec[i].len != 0) {
72 in_vec[i].base = psa_map_invec(msg->handle, i);
73 } else {
74 in_vec[i].base = NULL;
75 }
76 }
77
78 for (i = 0; i < out_len; i++) {
79 out_vec[i].len = msg->out_size[i];
80 if (out_vec[i].len != 0) {
81 out_vec[i].base = psa_map_outvec(msg->handle, i);
82 } else {
83 out_vec[i].base = NULL;
84 }
85 }
86
87 return PSA_SUCCESS;
88}
89#else /* PSA_FRAMEWORK_HAS_MM_IOVEC == 1 */
Antonio de Angelis4743e672019-04-11 11:38:48 +010090/**
Antonio de Angelis4743e672019-04-11 11:38:48 +010091 * \brief Internal scratch used for IOVec allocations
92 *
93 */
94static struct tfm_crypto_scratch {
95 __attribute__((__aligned__(TFM_CRYPTO_IOVEC_ALIGNMENT)))
Xinyu Zhangd755b822022-10-25 11:18:09 +080096 uint8_t buf[CRYPTO_IOVEC_BUFFER_SIZE];
Antonio de Angelis4743e672019-04-11 11:38:48 +010097 uint32_t alloc_index;
Antonio de Angelis60a6fe62019-06-18 15:27:34 +010098 int32_t owner;
Antonio de Angelis4743e672019-04-11 11:38:48 +010099} scratch = {.buf = {0}, .alloc_index = 0};
100
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100101static psa_status_t tfm_crypto_set_scratch_owner(int32_t id)
102{
103 scratch.owner = id;
104 return PSA_SUCCESS;
105}
106
107static psa_status_t tfm_crypto_get_scratch_owner(int32_t *id)
108{
109 *id = scratch.owner;
110 return PSA_SUCCESS;
111}
112
Antonio de Angelis4743e672019-04-11 11:38:48 +0100113static psa_status_t tfm_crypto_alloc_scratch(size_t requested_size, void **buf)
114{
Antonio de Angelisfc289ce2024-07-05 11:02:25 +0200115 /* Prevent ALIGN() from overflowing */
116 if (requested_size > SIZE_MAX - (TFM_CRYPTO_IOVEC_ALIGNMENT - 1)) {
117 return PSA_ERROR_INSUFFICIENT_MEMORY;
118 }
119
Antonio de Angelis4743e672019-04-11 11:38:48 +0100120 /* Ensure alloc_index remains aligned to the required iovec alignment */
121 requested_size = ALIGN(requested_size, TFM_CRYPTO_IOVEC_ALIGNMENT);
122
123 if (requested_size > (sizeof(scratch.buf) - scratch.alloc_index)) {
124 return PSA_ERROR_INSUFFICIENT_MEMORY;
125 }
126
127 /* Compute the pointer to the allocated space */
128 *buf = (void *)&scratch.buf[scratch.alloc_index];
129
130 /* Increase the allocated size */
131 scratch.alloc_index += requested_size;
132
133 return PSA_SUCCESS;
134}
135
Kevin Pengfe730cc2022-04-11 17:48:42 +0800136static void tfm_crypto_clear_scratch(void)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100137{
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100138 scratch.owner = 0;
Ken Liub671d682022-05-12 20:39:29 +0800139 (void)memset(scratch.buf, 0, scratch.alloc_index);
Summer Qin0a9e5372020-11-27 16:04:05 +0800140 scratch.alloc_index = 0;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100141}
142
Kevin Pengfe730cc2022-04-11 17:48:42 +0800143static void tfm_crypto_set_caller_id(int32_t id)
144{
145 /* Set the owner of the data in the scratch */
146 (void)tfm_crypto_set_scratch_owner(id);
147}
148
149psa_status_t tfm_crypto_get_caller_id(int32_t *id)
150{
151 return tfm_crypto_get_scratch_owner(id);
152}
153
154static psa_status_t tfm_crypto_init_iovecs(const psa_msg_t *msg,
155 psa_invec in_vec[],
156 size_t in_len,
157 psa_outvec out_vec[],
158 size_t out_len)
159{
160 uint32_t i;
161 void *alloc_buf_ptr = NULL;
162 psa_status_t status;
163
164 /* Alloc/read from the second element as the first is read when parsing */
165 for (i = 1; i < in_len; i++) {
166 /* Allocate necessary space in the internal scratch */
167 status = tfm_crypto_alloc_scratch(msg->in_size[i], &alloc_buf_ptr);
168 if (status != PSA_SUCCESS) {
169 tfm_crypto_clear_scratch();
170 return status;
171 }
172 /* Read from the IPC framework inputs into the scratch */
173 in_vec[i].len =
174 psa_read(msg->handle, i, alloc_buf_ptr, msg->in_size[i]);
175 /* Populate the fields of the input to the secure function */
176 in_vec[i].base = alloc_buf_ptr;
177 }
178
179 for (i = 0; i < out_len; i++) {
180 /* Allocate necessary space for the output in the internal scratch */
181 status = tfm_crypto_alloc_scratch(msg->out_size[i], &alloc_buf_ptr);
182 if (status != PSA_SUCCESS) {
183 tfm_crypto_clear_scratch();
184 return status;
185 }
186 /* Populate the fields of the output to the secure function */
187 out_vec[i].base = alloc_buf_ptr;
188 out_vec[i].len = msg->out_size[i];
189 }
190
191 return PSA_SUCCESS;
192}
193#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC == 1 */
194
Antonio de Angelisdba631b2024-04-22 22:33:04 +0100195static psa_status_t tfm_crypto_api_dispatcher(psa_invec in_vec[],
196 size_t in_len,
197 psa_outvec out_vec[],
198 size_t out_len)
199{
200 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
201 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
202 int32_t caller_id = 0;
203 struct tfm_crypto_key_id_s encoded_key = TFM_CRYPTO_KEY_ID_S_INIT;
204 bool is_key_required = false;
205 enum tfm_crypto_group_id_t group_id;
206
207 if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
208 return PSA_ERROR_PROGRAMMER_ERROR;
209 }
210
211 group_id = TFM_CRYPTO_GET_GROUP_ID(iov->function_id);
212
213 is_key_required = !((group_id == TFM_CRYPTO_GROUP_ID_HASH) ||
214 (group_id == TFM_CRYPTO_GROUP_ID_RANDOM));
215
216 if (is_key_required) {
217 status = tfm_crypto_get_caller_id(&caller_id);
218 if (status != PSA_SUCCESS) {
219 return status;
220 }
221 /* The caller_id being set in the owner field is the partition ID
222 * of the calling partition
223 */
224 encoded_key.key_id = iov->key_id;
225 encoded_key.owner = caller_id;
226 }
227
228 /* Dispatch to each sub-module based on the Group ID */
229 switch (group_id) {
230 case TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT:
231 return tfm_crypto_key_management_interface(in_vec, out_vec,
232 &encoded_key);
233 case TFM_CRYPTO_GROUP_ID_HASH:
234 return tfm_crypto_hash_interface(in_vec, out_vec);
235 case TFM_CRYPTO_GROUP_ID_MAC:
236 return tfm_crypto_mac_interface(in_vec, out_vec, &encoded_key);
237 case TFM_CRYPTO_GROUP_ID_CIPHER:
238 return tfm_crypto_cipher_interface(in_vec, out_vec, &encoded_key);
239 case TFM_CRYPTO_GROUP_ID_AEAD:
240 return tfm_crypto_aead_interface(in_vec, out_vec, &encoded_key);
241 case TFM_CRYPTO_GROUP_ID_ASYM_SIGN:
242 return tfm_crypto_asymmetric_sign_interface(in_vec, out_vec,
243 &encoded_key);
244 case TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT:
245 return tfm_crypto_asymmetric_encrypt_interface(in_vec, out_vec,
246 &encoded_key);
247 case TFM_CRYPTO_GROUP_ID_KEY_DERIVATION:
248 return tfm_crypto_key_derivation_interface(in_vec, out_vec,
249 &encoded_key);
250 case TFM_CRYPTO_GROUP_ID_RANDOM:
251 return tfm_crypto_random_interface(in_vec, out_vec);
252 default:
253 LOG_ERRFMT("[ERR][Crypto] Unsupported request!\r\n");
254 return PSA_ERROR_NOT_SUPPORTED;
255 }
Antonio de Angelisdba631b2024-04-22 22:33:04 +0100256}
257
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800258static psa_status_t tfm_crypto_call_srv(const psa_msg_t *msg)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100259{
260 psa_status_t status = PSA_SUCCESS;
TTornblomfaf74f52020-03-04 17:56:27 +0100261 size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, i;
Soby Mathewd8abdfd2020-10-14 10:28:01 +0100262 psa_invec in_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
263 psa_outvec out_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800264 struct tfm_crypto_pack_iovec iov = {0};
Antonio de Angelis4743e672019-04-11 11:38:48 +0100265
266 /* Check the number of in_vec filled */
Jamie Fox9a234e22019-04-30 11:12:05 +0100267 while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
268 in_len--;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100269 }
270
Kevin Pengfe730cc2022-04-11 17:48:42 +0800271 /* Check the number of out_vec filled */
272 while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
273 out_len--;
274 }
275
Antonio de Angelis4743e672019-04-11 11:38:48 +0100276 /* There will always be a tfm_crypto_pack_iovec in the first iovec */
277 if (in_len < 1) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100278 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100279 }
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800280
281 if (psa_read(msg->handle, 0, &iov, sizeof(iov)) != sizeof(iov)) {
282 return PSA_ERROR_GENERIC_ERROR;
283 }
284
Antonio de Angelis4743e672019-04-11 11:38:48 +0100285 /* Initialise the first iovec with the IOV read when parsing */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800286 in_vec[0].base = &iov;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100287 in_vec[0].len = sizeof(struct tfm_crypto_pack_iovec);
288
Kevin Pengfe730cc2022-04-11 17:48:42 +0800289 status = tfm_crypto_init_iovecs(msg, in_vec, in_len, out_vec, out_len);
290 if (status != PSA_SUCCESS) {
291 return status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100292 }
293
Kevin Pengfe730cc2022-04-11 17:48:42 +0800294 tfm_crypto_set_caller_id(msg->client_id);
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100295
Antonio de Angelis202425a2022-04-06 11:13:15 +0100296 /* Call the dispatcher to the functions that implement the PSA Crypto API */
297 status = tfm_crypto_api_dispatcher(in_vec, in_len, out_vec, out_len);
Antonio de Angelis4743e672019-04-11 11:38:48 +0100298
Kevin Pengfe730cc2022-04-11 17:48:42 +0800299#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
300 for (i = 0; i < out_len; i++) {
301 if (out_vec[i].base != NULL) {
302 psa_unmap_outvec(msg->handle, i, out_vec[i].len);
303 }
304 }
Nicola Mazzucato9d4a1ad2024-11-27 13:11:46 +0000305
306 /*
307 * Unmap from the second element because the first element is read when
308 * parsing the message, hence it is never mapped.
309 */
310 for (i = 1; i < in_len; i++) {
311 if (in_vec[i].base != NULL) {
312 psa_unmap_invec(msg->handle, i);
313 }
314 }
Kevin Pengfe730cc2022-04-11 17:48:42 +0800315#else
Antonio de Angelis4743e672019-04-11 11:38:48 +0100316 /* Write into the IPC framework outputs from the scratch */
317 for (i = 0; i < out_len; i++) {
318 psa_write(msg->handle, i, out_vec[i].base, out_vec[i].len);
319 }
320
321 /* Clear the allocated internal scratch before returning */
Summer Qin0a9e5372020-11-27 16:04:05 +0800322 tfm_crypto_clear_scratch();
Kevin Pengfe730cc2022-04-11 17:48:42 +0800323#endif
Antonio de Angelis4743e672019-04-11 11:38:48 +0100324
325 return status;
326}
Antonio de Angelis4743e672019-04-11 11:38:48 +0100327
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100328static psa_status_t tfm_crypto_engine_init(void)
329{
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000330 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis8f7db7d2022-12-01 12:09:16 +0000331 char *library_info = NULL;
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000332
Xinyu Zhangd755b822022-10-25 11:18:09 +0800333#if CRYPTO_NV_SEED
Antonio de Angelisf98fa332024-04-18 11:54:13 +0100334 LOG_INFFMT("[INF][Crypto] Provision entropy seed...\r\n");
Raef Coles618fc152021-06-18 09:26:46 +0100335 if (tfm_plat_crypto_provision_entropy_seed() != TFM_CRYPTO_NV_SEED_SUCCESS) {
Summer Qina5448d62020-12-07 14:03:37 +0800336 return PSA_ERROR_GENERIC_ERROR;
337 }
Antonio de Angelisf98fa332024-04-18 11:54:13 +0100338 LOG_INFFMT("[INF][Crypto] Provision entropy seed... \033[0;32mcomplete\033[0m.\r\n");
Raef Coles618fc152021-06-18 09:26:46 +0100339#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +0800340
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000341 /* Initialise the underlying Cryptographic library that provides the
342 * PSA Crypto core layer
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100343 */
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000344 library_info = tfm_crypto_library_get_info();
Antonio de Angelisf98fa332024-04-18 11:54:13 +0100345 LOG_DBGFMT("[DBG][Crypto] Init \033[0;32m%s\033[0m...\r\n", library_info);
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000346 status = tfm_crypto_core_library_init();
347 if (status != PSA_SUCCESS) {
348 return status;
349 }
Antonio de Angelisf98fa332024-04-18 11:54:13 +0100350 LOG_DBGFMT("[DBG][Crypto] Init \033[0;32m%s\033[0m... \033[0;32mcomplete\033[0m.\r\n", library_info);
Sherry Zhange1524982022-06-08 16:57:59 +0800351
Antonio de Angelis695d75b2022-08-22 15:06:24 +0100352 /* Initialise the crypto accelerator if one is enabled. If the driver API is
353 * the one defined by the PSA Unified Driver interface, the initialisation is
354 * performed directly through psa_crypto_init() while the PSA subsystem is
355 * initialised
356 */
Michel Jaouene991ffb2023-02-20 12:08:43 +0100357#if defined(CRYPTO_HW_ACCELERATOR) && defined(LEGACY_DRIVER_API_ENABLED)
Antonio de Angelisf98fa332024-04-18 11:54:13 +0100358 LOG_INFFMT("[INF][Crypto] Init HW accelerator...\r\n");
Raef Colesd2485af2019-10-30 10:15:33 +0000359 if (crypto_hw_accelerator_init() != 0) {
360 return PSA_ERROR_HARDWARE_FAILURE;
361 }
Antonio de Angelisf98fa332024-04-18 11:54:13 +0100362 LOG_INFFMT("[INF][Crypto] Init HW accelerator... \033[0;32mcomplete\033[0m.\r\n");
Raef Colesd2485af2019-10-30 10:15:33 +0000363#endif /* CRYPTO_HW_ACCELERATOR */
364
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000365 /* Perform the initialisation of the PSA subsystem available through the chosen
366 * Cryptographic library. If a driver is built using the PSA Driver interface,
367 * the function below will perform also the same operations done by the HAL init
368 * crypto_hw_accelerator_init()
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100369 */
370 return psa_crypto_init();
371}
372
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000373static psa_status_t tfm_crypto_module_init(void)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100374{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100375 /* Init the Alloc module */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000376 return tfm_crypto_init_alloc();
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100377}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100378
Antonio de Angelisdba631b2024-04-22 22:33:04 +0100379/*!
380 * \defgroup init This group implements the partition initilisation
381 * function to be called during TF-M boot, and the SFN
382 * servicing call to be called when a SFN request needs
383 * to be handled by the SPM. When built in IPC mode, the
384 * SPM directly provides a scheduling handler that deals
385 * with messages and calls the SFN entry point below just
386 * when needed, i.e. no need for a dedicated message handler
387 * needs to be implemented here
388 */
389
390/*!@{*/
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000391psa_status_t tfm_crypto_init(void)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100392{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100393 psa_status_t status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100394
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100395 /* Initialise other modules of the service */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000396 status = tfm_crypto_module_init();
397 if (status != PSA_SUCCESS) {
398 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100399 }
400
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100401 /* Initialise the engine layer */
Raef Coles79809c72022-03-02 13:48:20 +0000402 status = tfm_crypto_engine_init();
403 if (status != PSA_SUCCESS) {
404 return status;
405 }
406
Raef Coles79809c72022-03-02 13:48:20 +0000407 return PSA_SUCCESS;
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800408}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100409
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800410psa_status_t tfm_crypto_sfn(const psa_msg_t *msg)
411{
412 /* Process the message type */
413 switch (msg->type) {
414 case PSA_IPC_CALL:
415 return tfm_crypto_call_srv(msg);
416 default:
417 return PSA_ERROR_NOT_SUPPORTED;
418 }
Antonio de Angelis8908f472018-08-31 15:44:25 +0100419}
Antonio de Angelisdba631b2024-04-22 22:33:04 +0100420/*!@}*/