blob: 741a5f6f1bd9d6d3934a7dd3a6e7d37d0f16b04a [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
Xinyu Zhangd755b822022-10-25 11:18:09 +08009#include "config_crypto.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010010#include "tfm_mbedcrypto_include.h"
11
Antonio de Angelis8908f472018-08-31 15:44:25 +010012#include "tfm_crypto_api.h"
Antonio de Angelis7557e682022-11-30 15:37:51 +000013#include "tfm_crypto_key.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010014#include "tfm_crypto_defs.h"
Summer Qinc737ece2020-08-28 10:47:26 +080015#include "tfm_sp_log.h"
Summer Qinca6c1522022-06-17 14:25:55 +080016#include "crypto_check_config.h"
Raef Coles79809c72022-03-02 13:48:20 +000017#include "tfm_plat_crypto_keys.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010018
Antonio de Angelis8f7db7d2022-12-01 12:09:16 +000019#include "crypto_library.h"
20
Xinyu Zhangd755b822022-10-25 11:18:09 +080021#if CRYPTO_NV_SEED
Raef Coles618fc152021-06-18 09:26:46 +010022#include "tfm_plat_crypto_nv_seed.h"
23#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +080024
Raef Colesd2485af2019-10-30 10:15:33 +000025#ifdef CRYPTO_HW_ACCELERATOR
26#include "crypto_hw.h"
Michel Jaouenf41c6422021-10-07 14:38:08 +020027#endif /* CRYPTO_HW_ACCELERATOR */
Raef Colesd2485af2019-10-30 10:15:33 +000028
Ken Liub671d682022-05-12 20:39:29 +080029#include <string.h>
Kevin Pengfe730cc2022-04-11 17:48:42 +080030#include "psa/framework_feature.h"
Jamie Foxcc31d402019-01-28 17:13:52 +000031#include "psa/service.h"
Edison Aicc4c6162019-06-21 13:52:49 +080032#include "psa_manifest/tfm_crypto.h"
Antonio de Angelis4743e672019-04-11 11:38:48 +010033
34/**
Antonio de Angelis4743e672019-04-11 11:38:48 +010035 * \brief Aligns a value x up to an alignment a.
36 */
37#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
38
39/**
40 * \brief Maximum alignment required by any iovec parameters to the TF-M Crypto
41 * partition.
42 */
43#define TFM_CRYPTO_IOVEC_ALIGNMENT (4u)
44
Kevin Pengfe730cc2022-04-11 17:48:42 +080045#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
46static int32_t g_client_id;
47
48static void tfm_crypto_set_caller_id(int32_t id)
49{
50 g_client_id = id;
51}
52
53psa_status_t tfm_crypto_get_caller_id(int32_t *id)
54{
55 *id = g_client_id;
56 return PSA_SUCCESS;
57}
58
59static psa_status_t tfm_crypto_init_iovecs(const psa_msg_t *msg,
60 psa_invec in_vec[],
61 size_t in_len,
62 psa_outvec out_vec[],
63 size_t out_len)
64{
65 uint32_t i;
66
67 /* Map from the second element as the first is read when parsing */
68 for (i = 1; i < in_len; i++) {
69 in_vec[i].len = msg->in_size[i];
70 if (in_vec[i].len != 0) {
71 in_vec[i].base = psa_map_invec(msg->handle, i);
72 } else {
73 in_vec[i].base = NULL;
74 }
75 }
76
77 for (i = 0; i < out_len; i++) {
78 out_vec[i].len = msg->out_size[i];
79 if (out_vec[i].len != 0) {
80 out_vec[i].base = psa_map_outvec(msg->handle, i);
81 } else {
82 out_vec[i].base = NULL;
83 }
84 }
85
86 return PSA_SUCCESS;
87}
88#else /* PSA_FRAMEWORK_HAS_MM_IOVEC == 1 */
Antonio de Angelis4743e672019-04-11 11:38:48 +010089/**
Antonio de Angelis4743e672019-04-11 11:38:48 +010090 * \brief Internal scratch used for IOVec allocations
91 *
92 */
93static struct tfm_crypto_scratch {
94 __attribute__((__aligned__(TFM_CRYPTO_IOVEC_ALIGNMENT)))
Xinyu Zhangd755b822022-10-25 11:18:09 +080095 uint8_t buf[CRYPTO_IOVEC_BUFFER_SIZE];
Antonio de Angelis4743e672019-04-11 11:38:48 +010096 uint32_t alloc_index;
Antonio de Angelis60a6fe62019-06-18 15:27:34 +010097 int32_t owner;
Antonio de Angelis4743e672019-04-11 11:38:48 +010098} scratch = {.buf = {0}, .alloc_index = 0};
99
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100100static psa_status_t tfm_crypto_set_scratch_owner(int32_t id)
101{
102 scratch.owner = id;
103 return PSA_SUCCESS;
104}
105
106static psa_status_t tfm_crypto_get_scratch_owner(int32_t *id)
107{
108 *id = scratch.owner;
109 return PSA_SUCCESS;
110}
111
Antonio de Angelis4743e672019-04-11 11:38:48 +0100112static psa_status_t tfm_crypto_alloc_scratch(size_t requested_size, void **buf)
113{
114 /* Ensure alloc_index remains aligned to the required iovec alignment */
115 requested_size = ALIGN(requested_size, TFM_CRYPTO_IOVEC_ALIGNMENT);
116
117 if (requested_size > (sizeof(scratch.buf) - scratch.alloc_index)) {
118 return PSA_ERROR_INSUFFICIENT_MEMORY;
119 }
120
121 /* Compute the pointer to the allocated space */
122 *buf = (void *)&scratch.buf[scratch.alloc_index];
123
124 /* Increase the allocated size */
125 scratch.alloc_index += requested_size;
126
127 return PSA_SUCCESS;
128}
129
Kevin Pengfe730cc2022-04-11 17:48:42 +0800130static void tfm_crypto_clear_scratch(void)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100131{
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100132 scratch.owner = 0;
Ken Liub671d682022-05-12 20:39:29 +0800133 (void)memset(scratch.buf, 0, scratch.alloc_index);
Summer Qin0a9e5372020-11-27 16:04:05 +0800134 scratch.alloc_index = 0;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100135}
136
Kevin Pengfe730cc2022-04-11 17:48:42 +0800137static void tfm_crypto_set_caller_id(int32_t id)
138{
139 /* Set the owner of the data in the scratch */
140 (void)tfm_crypto_set_scratch_owner(id);
141}
142
143psa_status_t tfm_crypto_get_caller_id(int32_t *id)
144{
145 return tfm_crypto_get_scratch_owner(id);
146}
147
148static psa_status_t tfm_crypto_init_iovecs(const psa_msg_t *msg,
149 psa_invec in_vec[],
150 size_t in_len,
151 psa_outvec out_vec[],
152 size_t out_len)
153{
154 uint32_t i;
155 void *alloc_buf_ptr = NULL;
156 psa_status_t status;
157
158 /* Alloc/read from the second element as the first is read when parsing */
159 for (i = 1; i < in_len; i++) {
160 /* Allocate necessary space in the internal scratch */
161 status = tfm_crypto_alloc_scratch(msg->in_size[i], &alloc_buf_ptr);
162 if (status != PSA_SUCCESS) {
163 tfm_crypto_clear_scratch();
164 return status;
165 }
166 /* Read from the IPC framework inputs into the scratch */
167 in_vec[i].len =
168 psa_read(msg->handle, i, alloc_buf_ptr, msg->in_size[i]);
169 /* Populate the fields of the input to the secure function */
170 in_vec[i].base = alloc_buf_ptr;
171 }
172
173 for (i = 0; i < out_len; i++) {
174 /* Allocate necessary space for the output in the internal scratch */
175 status = tfm_crypto_alloc_scratch(msg->out_size[i], &alloc_buf_ptr);
176 if (status != PSA_SUCCESS) {
177 tfm_crypto_clear_scratch();
178 return status;
179 }
180 /* Populate the fields of the output to the secure function */
181 out_vec[i].base = alloc_buf_ptr;
182 out_vec[i].len = msg->out_size[i];
183 }
184
185 return PSA_SUCCESS;
186}
187#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC == 1 */
188
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800189static psa_status_t tfm_crypto_call_srv(const psa_msg_t *msg)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100190{
191 psa_status_t status = PSA_SUCCESS;
TTornblomfaf74f52020-03-04 17:56:27 +0100192 size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, i;
Soby Mathewd8abdfd2020-10-14 10:28:01 +0100193 psa_invec in_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
194 psa_outvec out_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800195 struct tfm_crypto_pack_iovec iov = {0};
Antonio de Angelis4743e672019-04-11 11:38:48 +0100196
197 /* Check the number of in_vec filled */
Jamie Fox9a234e22019-04-30 11:12:05 +0100198 while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
199 in_len--;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100200 }
201
Kevin Pengfe730cc2022-04-11 17:48:42 +0800202 /* Check the number of out_vec filled */
203 while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
204 out_len--;
205 }
206
Antonio de Angelis4743e672019-04-11 11:38:48 +0100207 /* There will always be a tfm_crypto_pack_iovec in the first iovec */
208 if (in_len < 1) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100209 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100210 }
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800211
212 if (psa_read(msg->handle, 0, &iov, sizeof(iov)) != sizeof(iov)) {
213 return PSA_ERROR_GENERIC_ERROR;
214 }
215
Antonio de Angelis4743e672019-04-11 11:38:48 +0100216 /* Initialise the first iovec with the IOV read when parsing */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800217 in_vec[0].base = &iov;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100218 in_vec[0].len = sizeof(struct tfm_crypto_pack_iovec);
219
Kevin Pengfe730cc2022-04-11 17:48:42 +0800220 status = tfm_crypto_init_iovecs(msg, in_vec, in_len, out_vec, out_len);
221 if (status != PSA_SUCCESS) {
222 return status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100223 }
224
Kevin Pengfe730cc2022-04-11 17:48:42 +0800225 tfm_crypto_set_caller_id(msg->client_id);
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100226
Antonio de Angelis202425a2022-04-06 11:13:15 +0100227 /* Call the dispatcher to the functions that implement the PSA Crypto API */
228 status = tfm_crypto_api_dispatcher(in_vec, in_len, out_vec, out_len);
Antonio de Angelis4743e672019-04-11 11:38:48 +0100229
Kevin Pengfe730cc2022-04-11 17:48:42 +0800230#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
231 for (i = 0; i < out_len; i++) {
232 if (out_vec[i].base != NULL) {
233 psa_unmap_outvec(msg->handle, i, out_vec[i].len);
234 }
235 }
236#else
Antonio de Angelis4743e672019-04-11 11:38:48 +0100237 /* Write into the IPC framework outputs from the scratch */
238 for (i = 0; i < out_len; i++) {
239 psa_write(msg->handle, i, out_vec[i].base, out_vec[i].len);
240 }
241
242 /* Clear the allocated internal scratch before returning */
Summer Qin0a9e5372020-11-27 16:04:05 +0800243 tfm_crypto_clear_scratch();
Kevin Pengfe730cc2022-04-11 17:48:42 +0800244#endif
Antonio de Angelis4743e672019-04-11 11:38:48 +0100245
246 return status;
247}
Antonio de Angelis4743e672019-04-11 11:38:48 +0100248
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100249static psa_status_t tfm_crypto_engine_init(void)
250{
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000251 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis8f7db7d2022-12-01 12:09:16 +0000252 char *library_info = NULL;
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000253
Xinyu Zhangd755b822022-10-25 11:18:09 +0800254#if CRYPTO_NV_SEED
Antonio de Angelis202425a2022-04-06 11:13:15 +0100255 LOG_INFFMT("[INF][Crypto] ");
Antonio de Angelis202425a2022-04-06 11:13:15 +0100256 LOG_INFFMT("Provisioning entropy seed... ");
Raef Coles618fc152021-06-18 09:26:46 +0100257 if (tfm_plat_crypto_provision_entropy_seed() != TFM_CRYPTO_NV_SEED_SUCCESS) {
Summer Qina5448d62020-12-07 14:03:37 +0800258 return PSA_ERROR_GENERIC_ERROR;
259 }
Antonio de Angelis202425a2022-04-06 11:13:15 +0100260 LOG_INFFMT("\033[0;32mcomplete.\033[0m\r\n");
Raef Coles618fc152021-06-18 09:26:46 +0100261#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +0800262
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000263 /* Initialise the underlying Cryptographic library that provides the
264 * PSA Crypto core layer
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100265 */
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000266 library_info = tfm_crypto_library_get_info();
267 LOG_DBGFMT("[DBG][Crypto] Initialising \033[0;32m%s\033[0m as PSA Crypto backend library... ", library_info);
268 status = tfm_crypto_core_library_init();
269 if (status != PSA_SUCCESS) {
270 return status;
271 }
272 LOG_DBGFMT("\033[0;32mcomplete.\033[0m\r\n");
Sherry Zhange1524982022-06-08 16:57:59 +0800273
Antonio de Angelis695d75b2022-08-22 15:06:24 +0100274 /* Initialise the crypto accelerator if one is enabled. If the driver API is
275 * the one defined by the PSA Unified Driver interface, the initialisation is
276 * performed directly through psa_crypto_init() while the PSA subsystem is
277 * initialised
278 */
279#if defined(CRYPTO_HW_ACCELERATOR) && defined(CC312_LEGACY_DRIVER_API_ENABLED)
Antonio de Angelis202425a2022-04-06 11:13:15 +0100280 LOG_INFFMT("[INF][Crypto] Initialising HW accelerator... ");
Raef Colesd2485af2019-10-30 10:15:33 +0000281 if (crypto_hw_accelerator_init() != 0) {
282 return PSA_ERROR_HARDWARE_FAILURE;
283 }
Antonio de Angelis202425a2022-04-06 11:13:15 +0100284 LOG_INFFMT("\033[0;32mcomplete.\033[0m\r\n");
Raef Colesd2485af2019-10-30 10:15:33 +0000285#endif /* CRYPTO_HW_ACCELERATOR */
286
Antonio de Angelisedbafb62022-12-01 13:52:15 +0000287 /* Perform the initialisation of the PSA subsystem available through the chosen
288 * Cryptographic library. If a driver is built using the PSA Driver interface,
289 * the function below will perform also the same operations done by the HAL init
290 * crypto_hw_accelerator_init()
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100291 */
292 return psa_crypto_init();
293}
294
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000295static psa_status_t tfm_crypto_module_init(void)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100296{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100297 /* Init the Alloc module */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000298 return tfm_crypto_init_alloc();
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100299}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100300
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000301psa_status_t tfm_crypto_init(void)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100302{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100303 psa_status_t status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100304
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100305 /* Initialise other modules of the service */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000306 status = tfm_crypto_module_init();
307 if (status != PSA_SUCCESS) {
308 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100309 }
310
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100311 /* Initialise the engine layer */
Raef Coles79809c72022-03-02 13:48:20 +0000312 status = tfm_crypto_engine_init();
313 if (status != PSA_SUCCESS) {
314 return status;
315 }
316
Raef Coles79809c72022-03-02 13:48:20 +0000317 return PSA_SUCCESS;
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800318}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100319
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800320psa_status_t tfm_crypto_sfn(const psa_msg_t *msg)
321{
322 /* Process the message type */
323 switch (msg->type) {
324 case PSA_IPC_CALL:
325 return tfm_crypto_call_srv(msg);
326 default:
327 return PSA_ERROR_NOT_SUPPORTED;
328 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100329
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800330 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100331}
Antonio de Angelis202425a2022-04-06 11:13:15 +0100332
333psa_status_t tfm_crypto_api_dispatcher(psa_invec in_vec[],
334 size_t in_len,
335 psa_outvec out_vec[],
336 size_t out_len)
337{
338 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
339 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
340 int32_t caller_id = 0;
Antonio de Angelis7557e682022-11-30 15:37:51 +0000341 struct tfm_crypto_key_id_s encoded_key = TFM_CRYPTO_KEY_ID_S_INIT;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100342 bool is_key_required = false;
David Huc9679cc2022-06-21 13:09:34 +0800343 enum tfm_crypto_group_id group_id;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100344
345 if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
346 return PSA_ERROR_PROGRAMMER_ERROR;
347 }
348
David Huc9679cc2022-06-21 13:09:34 +0800349 group_id = TFM_CRYPTO_GET_GROUP_ID(iov->function_id);
350
351 is_key_required = !((group_id == TFM_CRYPTO_GROUP_ID_HASH) ||
352 (group_id == TFM_CRYPTO_GROUP_ID_RANDOM));
Antonio de Angelis202425a2022-04-06 11:13:15 +0100353
354 if (is_key_required) {
355 status = tfm_crypto_get_caller_id(&caller_id);
356 if (status != PSA_SUCCESS) {
357 return status;
358 }
359 /* The caller_id being set in the owner field is the partition ID
360 * of the calling partition
361 */
Antonio de Angelis7557e682022-11-30 15:37:51 +0000362 encoded_key.key_id = iov->key_id;
363 encoded_key.owner = caller_id;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100364 }
365
366 /* Dispatch to each sub-module based on the Group ID */
David Huc9679cc2022-06-21 13:09:34 +0800367 switch (group_id) {
368 case TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT:
369 return tfm_crypto_key_management_interface(in_vec, out_vec,
370 &encoded_key);
371 case TFM_CRYPTO_GROUP_ID_HASH:
372 return tfm_crypto_hash_interface(in_vec, out_vec);
373 case TFM_CRYPTO_GROUP_ID_MAC:
374 return tfm_crypto_mac_interface(in_vec, out_vec, &encoded_key);
375 case TFM_CRYPTO_GROUP_ID_CIPHER:
376 return tfm_crypto_cipher_interface(in_vec, out_vec, &encoded_key);
377 case TFM_CRYPTO_GROUP_ID_AEAD:
378 return tfm_crypto_aead_interface(in_vec, out_vec, &encoded_key);
379 case TFM_CRYPTO_GROUP_ID_ASYM_SIGN:
380 return tfm_crypto_asymmetric_sign_interface(in_vec, out_vec,
381 &encoded_key);
382 case TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT:
383 return tfm_crypto_asymmetric_encrypt_interface(in_vec, out_vec,
384 &encoded_key);
385 case TFM_CRYPTO_GROUP_ID_KEY_DERIVATION:
386 return tfm_crypto_key_derivation_interface(in_vec, out_vec,
387 &encoded_key);
388 case TFM_CRYPTO_GROUP_ID_RANDOM:
389 return tfm_crypto_random_interface(in_vec, out_vec);
390 default:
Antonio de Angelis202425a2022-04-06 11:13:15 +0100391 LOG_ERRFMT("[ERR][Crypto] Unsupported request!\r\n");
David Huc9679cc2022-06-21 13:09:34 +0800392 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100393 }
394
David Huc9679cc2022-06-21 13:09:34 +0800395 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100396}