blob: d1a3ef5d69933f258aea2a65159da110ba34ee91 [file] [log] [blame]
Antonio de Angelis8908f472018-08-31 15:44:25 +01001/*
Kevin Peng6aa48952022-01-28 15:40:46 +08002 * Copyright (c) 2018-2022, 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
Jamie Fox0e54ebc2019-04-09 14:21:04 +01009#include "tfm_mbedcrypto_include.h"
10
Antonio de Angelis8908f472018-08-31 15:44:25 +010011#include "tfm_crypto_api.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010012#include "tfm_crypto_defs.h"
Summer Qinc737ece2020-08-28 10:47:26 +080013#include "tfm_sp_log.h"
Summer Qinca6c1522022-06-17 14:25:55 +080014#include "crypto_check_config.h"
Raef Coles79809c72022-03-02 13:48:20 +000015#include "tfm_plat_crypto_keys.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010016
17/*
18 * \brief This Mbed TLS include is needed to initialise the memory allocator
Antonio de Angelis202425a2022-04-06 11:13:15 +010019 * of the library used for internal allocations
Jamie Fox0e54ebc2019-04-09 14:21:04 +010020 */
21#include "mbedtls/memory_buffer_alloc.h"
Antonio de Angelis8908f472018-08-31 15:44:25 +010022
Sherry Zhange1524982022-06-08 16:57:59 +080023#include "mbedtls/platform.h"
24
Raef Coles618fc152021-06-18 09:26:46 +010025#ifdef CRYPTO_NV_SEED
26#include "tfm_plat_crypto_nv_seed.h"
27#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +080028
Raef Colesd2485af2019-10-30 10:15:33 +000029#ifdef CRYPTO_HW_ACCELERATOR
30#include "crypto_hw.h"
Michel Jaouenf41c6422021-10-07 14:38:08 +020031#endif /* CRYPTO_HW_ACCELERATOR */
Raef Colesd2485af2019-10-30 10:15:33 +000032
Antonio de Angelis202425a2022-04-06 11:13:15 +010033#ifndef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
34#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER must be selected in Mbed TLS config file"
35#endif
36
Ken Liub671d682022-05-12 20:39:29 +080037#include <string.h>
Kevin Pengfe730cc2022-04-11 17:48:42 +080038#include "psa/framework_feature.h"
Jamie Foxcc31d402019-01-28 17:13:52 +000039#include "psa/service.h"
Edison Aicc4c6162019-06-21 13:52:49 +080040#include "psa_manifest/tfm_crypto.h"
Antonio de Angelis4743e672019-04-11 11:38:48 +010041
42/**
Antonio de Angelis4743e672019-04-11 11:38:48 +010043 * \brief Aligns a value x up to an alignment a.
44 */
45#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
46
47/**
48 * \brief Maximum alignment required by any iovec parameters to the TF-M Crypto
49 * partition.
50 */
51#define TFM_CRYPTO_IOVEC_ALIGNMENT (4u)
52
Kevin Pengfe730cc2022-04-11 17:48:42 +080053#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
54static int32_t g_client_id;
55
56static void tfm_crypto_set_caller_id(int32_t id)
57{
58 g_client_id = id;
59}
60
61psa_status_t tfm_crypto_get_caller_id(int32_t *id)
62{
63 *id = g_client_id;
64 return PSA_SUCCESS;
65}
66
67static psa_status_t tfm_crypto_init_iovecs(const psa_msg_t *msg,
68 psa_invec in_vec[],
69 size_t in_len,
70 psa_outvec out_vec[],
71 size_t out_len)
72{
73 uint32_t i;
74
75 /* Map from the second element as the first is read when parsing */
76 for (i = 1; i < in_len; i++) {
77 in_vec[i].len = msg->in_size[i];
78 if (in_vec[i].len != 0) {
79 in_vec[i].base = psa_map_invec(msg->handle, i);
80 } else {
81 in_vec[i].base = NULL;
82 }
83 }
84
85 for (i = 0; i < out_len; i++) {
86 out_vec[i].len = msg->out_size[i];
87 if (out_vec[i].len != 0) {
88 out_vec[i].base = psa_map_outvec(msg->handle, i);
89 } else {
90 out_vec[i].base = NULL;
91 }
92 }
93
94 return PSA_SUCCESS;
95}
96#else /* PSA_FRAMEWORK_HAS_MM_IOVEC == 1 */
Antonio de Angelis4743e672019-04-11 11:38:48 +010097/**
Antonio de Angelis4743e672019-04-11 11:38:48 +010098 * \brief Internal scratch used for IOVec allocations
99 *
100 */
101static struct tfm_crypto_scratch {
102 __attribute__((__aligned__(TFM_CRYPTO_IOVEC_ALIGNMENT)))
103 uint8_t buf[TFM_CRYPTO_IOVEC_BUFFER_SIZE];
104 uint32_t alloc_index;
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100105 int32_t owner;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100106} scratch = {.buf = {0}, .alloc_index = 0};
107
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100108static psa_status_t tfm_crypto_set_scratch_owner(int32_t id)
109{
110 scratch.owner = id;
111 return PSA_SUCCESS;
112}
113
114static psa_status_t tfm_crypto_get_scratch_owner(int32_t *id)
115{
116 *id = scratch.owner;
117 return PSA_SUCCESS;
118}
119
Antonio de Angelis4743e672019-04-11 11:38:48 +0100120static psa_status_t tfm_crypto_alloc_scratch(size_t requested_size, void **buf)
121{
122 /* Ensure alloc_index remains aligned to the required iovec alignment */
123 requested_size = ALIGN(requested_size, TFM_CRYPTO_IOVEC_ALIGNMENT);
124
125 if (requested_size > (sizeof(scratch.buf) - scratch.alloc_index)) {
126 return PSA_ERROR_INSUFFICIENT_MEMORY;
127 }
128
129 /* Compute the pointer to the allocated space */
130 *buf = (void *)&scratch.buf[scratch.alloc_index];
131
132 /* Increase the allocated size */
133 scratch.alloc_index += requested_size;
134
135 return PSA_SUCCESS;
136}
137
Kevin Pengfe730cc2022-04-11 17:48:42 +0800138static void tfm_crypto_clear_scratch(void)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100139{
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100140 scratch.owner = 0;
Ken Liub671d682022-05-12 20:39:29 +0800141 (void)memset(scratch.buf, 0, scratch.alloc_index);
Summer Qin0a9e5372020-11-27 16:04:05 +0800142 scratch.alloc_index = 0;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100143}
144
Kevin Pengfe730cc2022-04-11 17:48:42 +0800145static void tfm_crypto_set_caller_id(int32_t id)
146{
147 /* Set the owner of the data in the scratch */
148 (void)tfm_crypto_set_scratch_owner(id);
149}
150
151psa_status_t tfm_crypto_get_caller_id(int32_t *id)
152{
153 return tfm_crypto_get_scratch_owner(id);
154}
155
156static psa_status_t tfm_crypto_init_iovecs(const psa_msg_t *msg,
157 psa_invec in_vec[],
158 size_t in_len,
159 psa_outvec out_vec[],
160 size_t out_len)
161{
162 uint32_t i;
163 void *alloc_buf_ptr = NULL;
164 psa_status_t status;
165
166 /* Alloc/read from the second element as the first is read when parsing */
167 for (i = 1; i < in_len; i++) {
168 /* Allocate necessary space in the internal scratch */
169 status = tfm_crypto_alloc_scratch(msg->in_size[i], &alloc_buf_ptr);
170 if (status != PSA_SUCCESS) {
171 tfm_crypto_clear_scratch();
172 return status;
173 }
174 /* Read from the IPC framework inputs into the scratch */
175 in_vec[i].len =
176 psa_read(msg->handle, i, alloc_buf_ptr, msg->in_size[i]);
177 /* Populate the fields of the input to the secure function */
178 in_vec[i].base = alloc_buf_ptr;
179 }
180
181 for (i = 0; i < out_len; i++) {
182 /* Allocate necessary space for the output in the internal scratch */
183 status = tfm_crypto_alloc_scratch(msg->out_size[i], &alloc_buf_ptr);
184 if (status != PSA_SUCCESS) {
185 tfm_crypto_clear_scratch();
186 return status;
187 }
188 /* Populate the fields of the output to the secure function */
189 out_vec[i].base = alloc_buf_ptr;
190 out_vec[i].len = msg->out_size[i];
191 }
192
193 return PSA_SUCCESS;
194}
195#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC == 1 */
196
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800197static psa_status_t tfm_crypto_call_srv(const psa_msg_t *msg)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100198{
199 psa_status_t status = PSA_SUCCESS;
TTornblomfaf74f52020-03-04 17:56:27 +0100200 size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, i;
Soby Mathewd8abdfd2020-10-14 10:28:01 +0100201 psa_invec in_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
202 psa_outvec out_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800203 struct tfm_crypto_pack_iovec iov = {0};
Antonio de Angelis4743e672019-04-11 11:38:48 +0100204
205 /* Check the number of in_vec filled */
Jamie Fox9a234e22019-04-30 11:12:05 +0100206 while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
207 in_len--;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100208 }
209
Kevin Pengfe730cc2022-04-11 17:48:42 +0800210 /* Check the number of out_vec filled */
211 while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
212 out_len--;
213 }
214
Antonio de Angelis4743e672019-04-11 11:38:48 +0100215 /* There will always be a tfm_crypto_pack_iovec in the first iovec */
216 if (in_len < 1) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100217 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100218 }
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800219
220 if (psa_read(msg->handle, 0, &iov, sizeof(iov)) != sizeof(iov)) {
221 return PSA_ERROR_GENERIC_ERROR;
222 }
223
Antonio de Angelis4743e672019-04-11 11:38:48 +0100224 /* Initialise the first iovec with the IOV read when parsing */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800225 in_vec[0].base = &iov;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100226 in_vec[0].len = sizeof(struct tfm_crypto_pack_iovec);
227
Kevin Pengfe730cc2022-04-11 17:48:42 +0800228 status = tfm_crypto_init_iovecs(msg, in_vec, in_len, out_vec, out_len);
229 if (status != PSA_SUCCESS) {
230 return status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100231 }
232
Kevin Pengfe730cc2022-04-11 17:48:42 +0800233 tfm_crypto_set_caller_id(msg->client_id);
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100234
Antonio de Angelis202425a2022-04-06 11:13:15 +0100235 /* Call the dispatcher to the functions that implement the PSA Crypto API */
236 status = tfm_crypto_api_dispatcher(in_vec, in_len, out_vec, out_len);
Antonio de Angelis4743e672019-04-11 11:38:48 +0100237
Kevin Pengfe730cc2022-04-11 17:48:42 +0800238#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
239 for (i = 0; i < out_len; i++) {
240 if (out_vec[i].base != NULL) {
241 psa_unmap_outvec(msg->handle, i, out_vec[i].len);
242 }
243 }
244#else
Antonio de Angelis4743e672019-04-11 11:38:48 +0100245 /* Write into the IPC framework outputs from the scratch */
246 for (i = 0; i < out_len; i++) {
247 psa_write(msg->handle, i, out_vec[i].base, out_vec[i].len);
248 }
249
250 /* Clear the allocated internal scratch before returning */
Summer Qin0a9e5372020-11-27 16:04:05 +0800251 tfm_crypto_clear_scratch();
Kevin Pengfe730cc2022-04-11 17:48:42 +0800252#endif
Antonio de Angelis4743e672019-04-11 11:38:48 +0100253
254 return status;
255}
Antonio de Angelis4743e672019-04-11 11:38:48 +0100256
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100257/**
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100258 * \brief Static buffer to be used by Mbed Crypto for memory allocations
259 *
260 */
261static uint8_t mbedtls_mem_buf[TFM_CRYPTO_ENGINE_BUF_SIZE] = {0};
262
263static psa_status_t tfm_crypto_engine_init(void)
264{
Raef Coles618fc152021-06-18 09:26:46 +0100265#ifdef CRYPTO_NV_SEED
Antonio de Angelis202425a2022-04-06 11:13:15 +0100266 LOG_INFFMT("[INF][Crypto] ");
Antonio de Angelis202425a2022-04-06 11:13:15 +0100267 LOG_INFFMT("Provisioning entropy seed... ");
Raef Coles618fc152021-06-18 09:26:46 +0100268 if (tfm_plat_crypto_provision_entropy_seed() != TFM_CRYPTO_NV_SEED_SUCCESS) {
Summer Qina5448d62020-12-07 14:03:37 +0800269 return PSA_ERROR_GENERIC_ERROR;
270 }
Antonio de Angelis202425a2022-04-06 11:13:15 +0100271 LOG_INFFMT("\033[0;32mcomplete.\033[0m\r\n");
Raef Coles618fc152021-06-18 09:26:46 +0100272#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +0800273
Antonio de Angelis202425a2022-04-06 11:13:15 +0100274 /* Initialise the Mbed Crypto memory allocator to use static memory
275 * allocation from the provided buffer instead of using the heap
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100276 */
277 mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf,
278 TFM_CRYPTO_ENGINE_BUF_SIZE);
279
Sherry Zhange1524982022-06-08 16:57:59 +0800280 /* mbedtls_printf is used to print messages including error information. */
281#if (TFM_PARTITION_LOG_LEVEL >= TFM_PARTITION_LOG_LEVEL_ERROR)
Ken Liu53b2e332022-09-29 10:56:16 +0800282 mbedtls_platform_set_printf(printf);
Sherry Zhange1524982022-06-08 16:57:59 +0800283#endif
284
Antonio de Angelis695d75b2022-08-22 15:06:24 +0100285 /* Initialise the crypto accelerator if one is enabled. If the driver API is
286 * the one defined by the PSA Unified Driver interface, the initialisation is
287 * performed directly through psa_crypto_init() while the PSA subsystem is
288 * initialised
289 */
290#if defined(CRYPTO_HW_ACCELERATOR) && defined(CC312_LEGACY_DRIVER_API_ENABLED)
Antonio de Angelis202425a2022-04-06 11:13:15 +0100291 LOG_INFFMT("[INF][Crypto] Initialising HW accelerator... ");
Raef Colesd2485af2019-10-30 10:15:33 +0000292 if (crypto_hw_accelerator_init() != 0) {
293 return PSA_ERROR_HARDWARE_FAILURE;
294 }
Antonio de Angelis202425a2022-04-06 11:13:15 +0100295 LOG_INFFMT("\033[0;32mcomplete.\033[0m\r\n");
Raef Colesd2485af2019-10-30 10:15:33 +0000296#endif /* CRYPTO_HW_ACCELERATOR */
297
Antonio de Angelis695d75b2022-08-22 15:06:24 +0100298 /* Perform the initialisation of the PSA subsystem in the Mbed Crypto
299 * library. If a driver is built using the PSA Driver interface, the function
300 * below will perform also the same operations as crypto_hw_accelerator_init()
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100301 */
302 return psa_crypto_init();
303}
304
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000305static psa_status_t tfm_crypto_module_init(void)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100306{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100307 /* Init the Alloc module */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000308 return tfm_crypto_init_alloc();
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100309}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100310
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000311psa_status_t tfm_crypto_init(void)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100312{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100313 psa_status_t status;
Raef Coles79809c72022-03-02 13:48:20 +0000314 enum tfm_plat_err_t plat_err;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100315
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100316 /* Initialise other modules of the service */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000317 status = tfm_crypto_module_init();
318 if (status != PSA_SUCCESS) {
319 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100320 }
321
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100322 /* Initialise the engine layer */
Raef Coles79809c72022-03-02 13:48:20 +0000323 status = tfm_crypto_engine_init();
324 if (status != PSA_SUCCESS) {
325 return status;
326 }
327
328 plat_err = tfm_plat_load_builtin_keys();
329 if (plat_err != TFM_PLAT_ERR_SUCCESS) {
330 return PSA_ERROR_GENERIC_ERROR;
331 }
332
333 return PSA_SUCCESS;
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800334}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100335
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800336psa_status_t tfm_crypto_sfn(const psa_msg_t *msg)
337{
338 /* Process the message type */
339 switch (msg->type) {
340 case PSA_IPC_CALL:
341 return tfm_crypto_call_srv(msg);
342 default:
343 return PSA_ERROR_NOT_SUPPORTED;
344 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100345
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800346 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100347}
Antonio de Angelis202425a2022-04-06 11:13:15 +0100348
349psa_status_t tfm_crypto_api_dispatcher(psa_invec in_vec[],
350 size_t in_len,
351 psa_outvec out_vec[],
352 size_t out_len)
353{
354 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
355 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
356 int32_t caller_id = 0;
357 mbedtls_svc_key_id_t encoded_key = MBEDTLS_SVC_KEY_ID_INIT;
358 bool is_key_required = false;
David Huc9679cc2022-06-21 13:09:34 +0800359 enum tfm_crypto_group_id group_id;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100360
361 if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
362 return PSA_ERROR_PROGRAMMER_ERROR;
363 }
364
David Huc9679cc2022-06-21 13:09:34 +0800365 group_id = TFM_CRYPTO_GET_GROUP_ID(iov->function_id);
366
367 is_key_required = !((group_id == TFM_CRYPTO_GROUP_ID_HASH) ||
368 (group_id == TFM_CRYPTO_GROUP_ID_RANDOM));
Antonio de Angelis202425a2022-04-06 11:13:15 +0100369
370 if (is_key_required) {
371 status = tfm_crypto_get_caller_id(&caller_id);
372 if (status != PSA_SUCCESS) {
373 return status;
374 }
375 /* The caller_id being set in the owner field is the partition ID
376 * of the calling partition
377 */
378 encoded_key = mbedtls_svc_key_id_make(caller_id, iov->key_id);
379 }
380
381 /* Dispatch to each sub-module based on the Group ID */
David Huc9679cc2022-06-21 13:09:34 +0800382 switch (group_id) {
383 case TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT:
384 return tfm_crypto_key_management_interface(in_vec, out_vec,
385 &encoded_key);
386 case TFM_CRYPTO_GROUP_ID_HASH:
387 return tfm_crypto_hash_interface(in_vec, out_vec);
388 case TFM_CRYPTO_GROUP_ID_MAC:
389 return tfm_crypto_mac_interface(in_vec, out_vec, &encoded_key);
390 case TFM_CRYPTO_GROUP_ID_CIPHER:
391 return tfm_crypto_cipher_interface(in_vec, out_vec, &encoded_key);
392 case TFM_CRYPTO_GROUP_ID_AEAD:
393 return tfm_crypto_aead_interface(in_vec, out_vec, &encoded_key);
394 case TFM_CRYPTO_GROUP_ID_ASYM_SIGN:
395 return tfm_crypto_asymmetric_sign_interface(in_vec, out_vec,
396 &encoded_key);
397 case TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT:
398 return tfm_crypto_asymmetric_encrypt_interface(in_vec, out_vec,
399 &encoded_key);
400 case TFM_CRYPTO_GROUP_ID_KEY_DERIVATION:
401 return tfm_crypto_key_derivation_interface(in_vec, out_vec,
402 &encoded_key);
403 case TFM_CRYPTO_GROUP_ID_RANDOM:
404 return tfm_crypto_random_interface(in_vec, out_vec);
405 default:
Antonio de Angelis202425a2022-04-06 11:13:15 +0100406 LOG_ERRFMT("[ERR][Crypto] Unsupported request!\r\n");
David Huc9679cc2022-06-21 13:09:34 +0800407 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100408 }
409
David Huc9679cc2022-06-21 13:09:34 +0800410 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100411}