blob: 476bea5212a4530d764382bc4cd6ef0bc34a35a3 [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 */
7
Jamie Fox0e54ebc2019-04-09 14:21:04 +01008#include "tfm_mbedcrypto_include.h"
9
Antonio de Angelis8908f472018-08-31 15:44:25 +010010#include "tfm_crypto_api.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010011#include "tfm_crypto_defs.h"
Summer Qinc737ece2020-08-28 10:47:26 +080012#include "tfm_sp_log.h"
Jamie Fox0e54ebc2019-04-09 14:21:04 +010013
14/*
15 * \brief This Mbed TLS include is needed to initialise the memory allocator
16 * inside the Mbed TLS layer of Mbed Crypto
17 */
18#include "mbedtls/memory_buffer_alloc.h"
Antonio de Angelis8908f472018-08-31 15:44:25 +010019
Raef Coles618fc152021-06-18 09:26:46 +010020#ifdef CRYPTO_NV_SEED
21#include "tfm_plat_crypto_nv_seed.h"
22#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +080023
Antonio de Angelis60a6fe62019-06-18 15:27:34 +010024#ifndef TFM_PSA_API
25#include "tfm_secure_api.h"
26#endif
27
Raef Colesd2485af2019-10-30 10:15:33 +000028#ifdef CRYPTO_HW_ACCELERATOR
29#include "crypto_hw.h"
Michel Jaouenf41c6422021-10-07 14:38:08 +020030#endif /* CRYPTO_HW_ACCELERATOR */
Raef Colesd2485af2019-10-30 10:15:33 +000031
Antonio de Angelis4743e672019-04-11 11:38:48 +010032#ifdef TFM_PSA_API
Ken Liub671d682022-05-12 20:39:29 +080033#include <string.h>
Kevin Pengfe730cc2022-04-11 17:48:42 +080034#include "psa/framework_feature.h"
Jamie Foxcc31d402019-01-28 17:13:52 +000035#include "psa/service.h"
Edison Aicc4c6162019-06-21 13:52:49 +080036#include "psa_manifest/tfm_crypto.h"
Antonio de Angelis4743e672019-04-11 11:38:48 +010037
38/**
39 * \brief Table containing all the Uniform Signature API exposed
40 * by the TF-M Crypto partition
41 */
Edison Ai080b2e22019-04-17 16:27:21 +080042static const tfm_crypto_us_t sfid_func_table[TFM_CRYPTO_SID_MAX] = {
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +010043#define X(api_name) api_name,
44LIST_TFM_CRYPTO_UNIFORM_SIGNATURE_API
45#undef X
Antonio de Angelis4743e672019-04-11 11:38:48 +010046};
47
48/**
49 * \brief Aligns a value x up to an alignment a.
50 */
51#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
52
53/**
54 * \brief Maximum alignment required by any iovec parameters to the TF-M Crypto
55 * partition.
56 */
57#define TFM_CRYPTO_IOVEC_ALIGNMENT (4u)
58
Kevin Pengfe730cc2022-04-11 17:48:42 +080059#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
60static int32_t g_client_id;
61
62static void tfm_crypto_set_caller_id(int32_t id)
63{
64 g_client_id = id;
65}
66
67psa_status_t tfm_crypto_get_caller_id(int32_t *id)
68{
69 *id = g_client_id;
70 return PSA_SUCCESS;
71}
72
73static psa_status_t tfm_crypto_init_iovecs(const psa_msg_t *msg,
74 psa_invec in_vec[],
75 size_t in_len,
76 psa_outvec out_vec[],
77 size_t out_len)
78{
79 uint32_t i;
80
81 /* Map from the second element as the first is read when parsing */
82 for (i = 1; i < in_len; i++) {
83 in_vec[i].len = msg->in_size[i];
84 if (in_vec[i].len != 0) {
85 in_vec[i].base = psa_map_invec(msg->handle, i);
86 } else {
87 in_vec[i].base = NULL;
88 }
89 }
90
91 for (i = 0; i < out_len; i++) {
92 out_vec[i].len = msg->out_size[i];
93 if (out_vec[i].len != 0) {
94 out_vec[i].base = psa_map_outvec(msg->handle, i);
95 } else {
96 out_vec[i].base = NULL;
97 }
98 }
99
100 return PSA_SUCCESS;
101}
102#else /* PSA_FRAMEWORK_HAS_MM_IOVEC == 1 */
Antonio de Angelis4743e672019-04-11 11:38:48 +0100103/**
104 * \brief Default size of the internal scratch buffer used for IOVec allocations
105 * in bytes
106 */
107#ifndef TFM_CRYPTO_IOVEC_BUFFER_SIZE
Soby Mathew7740b602020-10-07 12:08:28 +0100108#error TFM_CRYPTO_IOVEC_BUFFER_SIZE is not defined
Antonio de Angelis4743e672019-04-11 11:38:48 +0100109#endif
110
111/**
112 * \brief Internal scratch used for IOVec allocations
113 *
114 */
115static struct tfm_crypto_scratch {
116 __attribute__((__aligned__(TFM_CRYPTO_IOVEC_ALIGNMENT)))
117 uint8_t buf[TFM_CRYPTO_IOVEC_BUFFER_SIZE];
118 uint32_t alloc_index;
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100119 int32_t owner;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100120} scratch = {.buf = {0}, .alloc_index = 0};
121
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100122static psa_status_t tfm_crypto_set_scratch_owner(int32_t id)
123{
124 scratch.owner = id;
125 return PSA_SUCCESS;
126}
127
128static psa_status_t tfm_crypto_get_scratch_owner(int32_t *id)
129{
130 *id = scratch.owner;
131 return PSA_SUCCESS;
132}
133
Antonio de Angelis4743e672019-04-11 11:38:48 +0100134static psa_status_t tfm_crypto_alloc_scratch(size_t requested_size, void **buf)
135{
136 /* Ensure alloc_index remains aligned to the required iovec alignment */
137 requested_size = ALIGN(requested_size, TFM_CRYPTO_IOVEC_ALIGNMENT);
138
139 if (requested_size > (sizeof(scratch.buf) - scratch.alloc_index)) {
140 return PSA_ERROR_INSUFFICIENT_MEMORY;
141 }
142
143 /* Compute the pointer to the allocated space */
144 *buf = (void *)&scratch.buf[scratch.alloc_index];
145
146 /* Increase the allocated size */
147 scratch.alloc_index += requested_size;
148
149 return PSA_SUCCESS;
150}
151
Kevin Pengfe730cc2022-04-11 17:48:42 +0800152static void tfm_crypto_clear_scratch(void)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100153{
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100154 scratch.owner = 0;
Ken Liub671d682022-05-12 20:39:29 +0800155 (void)memset(scratch.buf, 0, scratch.alloc_index);
Summer Qin0a9e5372020-11-27 16:04:05 +0800156 scratch.alloc_index = 0;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100157}
158
Kevin Pengfe730cc2022-04-11 17:48:42 +0800159static void tfm_crypto_set_caller_id(int32_t id)
160{
161 /* Set the owner of the data in the scratch */
162 (void)tfm_crypto_set_scratch_owner(id);
163}
164
165psa_status_t tfm_crypto_get_caller_id(int32_t *id)
166{
167 return tfm_crypto_get_scratch_owner(id);
168}
169
170static psa_status_t tfm_crypto_init_iovecs(const psa_msg_t *msg,
171 psa_invec in_vec[],
172 size_t in_len,
173 psa_outvec out_vec[],
174 size_t out_len)
175{
176 uint32_t i;
177 void *alloc_buf_ptr = NULL;
178 psa_status_t status;
179
180 /* Alloc/read from the second element as the first is read when parsing */
181 for (i = 1; i < in_len; i++) {
182 /* Allocate necessary space in the internal scratch */
183 status = tfm_crypto_alloc_scratch(msg->in_size[i], &alloc_buf_ptr);
184 if (status != PSA_SUCCESS) {
185 tfm_crypto_clear_scratch();
186 return status;
187 }
188 /* Read from the IPC framework inputs into the scratch */
189 in_vec[i].len =
190 psa_read(msg->handle, i, alloc_buf_ptr, msg->in_size[i]);
191 /* Populate the fields of the input to the secure function */
192 in_vec[i].base = alloc_buf_ptr;
193 }
194
195 for (i = 0; i < out_len; i++) {
196 /* Allocate necessary space for the output in the internal scratch */
197 status = tfm_crypto_alloc_scratch(msg->out_size[i], &alloc_buf_ptr);
198 if (status != PSA_SUCCESS) {
199 tfm_crypto_clear_scratch();
200 return status;
201 }
202 /* Populate the fields of the output to the secure function */
203 out_vec[i].base = alloc_buf_ptr;
204 out_vec[i].len = msg->out_size[i];
205 }
206
207 return PSA_SUCCESS;
208}
209#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC == 1 */
210
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800211static psa_status_t tfm_crypto_call_srv(const psa_msg_t *msg)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100212{
213 psa_status_t status = PSA_SUCCESS;
TTornblomfaf74f52020-03-04 17:56:27 +0100214 size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, i;
Soby Mathewd8abdfd2020-10-14 10:28:01 +0100215 psa_invec in_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
216 psa_outvec out_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800217 struct tfm_crypto_pack_iovec iov = {0};
Antonio de Angelis4743e672019-04-11 11:38:48 +0100218
219 /* Check the number of in_vec filled */
Jamie Fox9a234e22019-04-30 11:12:05 +0100220 while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
221 in_len--;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100222 }
223
Kevin Pengfe730cc2022-04-11 17:48:42 +0800224 /* Check the number of out_vec filled */
225 while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
226 out_len--;
227 }
228
Antonio de Angelis4743e672019-04-11 11:38:48 +0100229 /* There will always be a tfm_crypto_pack_iovec in the first iovec */
230 if (in_len < 1) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100231 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100232 }
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800233
234 if (psa_read(msg->handle, 0, &iov, sizeof(iov)) != sizeof(iov)) {
235 return PSA_ERROR_GENERIC_ERROR;
236 }
237
238 if (iov.srv_id >= TFM_CRYPTO_SID_MAX) {
239 return PSA_ERROR_GENERIC_ERROR;
240 }
241
Antonio de Angelis4743e672019-04-11 11:38:48 +0100242 /* Initialise the first iovec with the IOV read when parsing */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800243 in_vec[0].base = &iov;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100244 in_vec[0].len = sizeof(struct tfm_crypto_pack_iovec);
245
Kevin Pengfe730cc2022-04-11 17:48:42 +0800246 status = tfm_crypto_init_iovecs(msg, in_vec, in_len, out_vec, out_len);
247 if (status != PSA_SUCCESS) {
248 return status;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100249 }
250
Kevin Pengfe730cc2022-04-11 17:48:42 +0800251 tfm_crypto_set_caller_id(msg->client_id);
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100252
Antonio de Angelis4743e672019-04-11 11:38:48 +0100253 /* Call the uniform signature API */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800254 status = sfid_func_table[iov.srv_id](in_vec, in_len, out_vec, out_len);
Antonio de Angelis4743e672019-04-11 11:38:48 +0100255
Kevin Pengfe730cc2022-04-11 17:48:42 +0800256#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
257 for (i = 0; i < out_len; i++) {
258 if (out_vec[i].base != NULL) {
259 psa_unmap_outvec(msg->handle, i, out_vec[i].len);
260 }
261 }
262#else
Antonio de Angelis4743e672019-04-11 11:38:48 +0100263 /* Write into the IPC framework outputs from the scratch */
264 for (i = 0; i < out_len; i++) {
265 psa_write(msg->handle, i, out_vec[i].base, out_vec[i].len);
266 }
267
268 /* Clear the allocated internal scratch before returning */
Summer Qin0a9e5372020-11-27 16:04:05 +0800269 tfm_crypto_clear_scratch();
Kevin Pengfe730cc2022-04-11 17:48:42 +0800270#endif
Antonio de Angelis4743e672019-04-11 11:38:48 +0100271
272 return status;
273}
Kevin Pengfe730cc2022-04-11 17:48:42 +0800274#else /* TFM_PSA_API */
275psa_status_t tfm_crypto_get_caller_id(int32_t *id)
276{
277 int32_t res;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100278
Kevin Pengfe730cc2022-04-11 17:48:42 +0800279 res = tfm_core_get_caller_client_id(id);
280 if (res != TFM_SUCCESS) {
281 return PSA_ERROR_NOT_PERMITTED;
282 } else {
283 return PSA_SUCCESS;
284 }
285}
Antonio de Angelis4743e672019-04-11 11:38:48 +0100286#endif /* TFM_PSA_API */
287
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100288/**
289 * \brief Default value for the size of the static buffer used by Mbed
290 * Crypto for its dynamic allocations
291 */
292#ifndef TFM_CRYPTO_ENGINE_BUF_SIZE
Soby Mathew7740b602020-10-07 12:08:28 +0100293#error TFM_CRYPTO_ENGINE_BUF_SIZE is not defined
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100294#endif
295
296/**
297 * \brief Static buffer to be used by Mbed Crypto for memory allocations
298 *
299 */
300static uint8_t mbedtls_mem_buf[TFM_CRYPTO_ENGINE_BUF_SIZE] = {0};
301
302static psa_status_t tfm_crypto_engine_init(void)
303{
Raef Coles618fc152021-06-18 09:26:46 +0100304
305#ifdef CRYPTO_NV_SEED
306#ifdef TFM_PSA_API
307 if (tfm_plat_crypto_provision_entropy_seed() != TFM_CRYPTO_NV_SEED_SUCCESS) {
Summer Qina5448d62020-12-07 14:03:37 +0800308 return PSA_ERROR_GENERIC_ERROR;
309 }
Raef Coles618fc152021-06-18 09:26:46 +0100310#else
311 LOG_INFFMT("\033[1;31m[Crypto] ");
312 LOG_INFFMT("TF-M in library mode uses a dummy NV seed. ");
313 LOG_INFFMT("This is not suitable for production! ");
314 LOG_INFFMT("This device is \033[1;1mNOT SECURE");
315 LOG_INFFMT("\033[0m\r\n");
316#endif /* TFM_PSA_API */
317#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +0800318
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100319 /* Initialise the Mbed Crypto memory allocator to use static
320 * memory allocation from the provided buffer instead of using
321 * the heap
322 */
323 mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf,
324 TFM_CRYPTO_ENGINE_BUF_SIZE);
325
Raef Colesd2485af2019-10-30 10:15:33 +0000326 /* Initialise the crypto accelerator if one is enabled */
327#ifdef CRYPTO_HW_ACCELERATOR
328 if (crypto_hw_accelerator_init() != 0) {
329 return PSA_ERROR_HARDWARE_FAILURE;
330 }
331#endif /* CRYPTO_HW_ACCELERATOR */
332
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100333 /* Previous function does not return any value, so just call the
334 * initialisation function of the Mbed Crypto layer
335 */
336 return psa_crypto_init();
337}
338
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000339static psa_status_t tfm_crypto_module_init(void)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100340{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100341 /* Init the Alloc module */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000342 return tfm_crypto_init_alloc();
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100343}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100344
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000345psa_status_t tfm_crypto_init(void)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100346{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100347 psa_status_t status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100348
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100349 /* Initialise other modules of the service */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000350 status = tfm_crypto_module_init();
351 if (status != PSA_SUCCESS) {
352 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100353 }
354
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100355 /* Initialise the engine layer */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800356 return tfm_crypto_engine_init();
357}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100358
Antonio de Angelis4743e672019-04-11 11:38:48 +0100359#ifdef TFM_PSA_API
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800360psa_status_t tfm_crypto_sfn(const psa_msg_t *msg)
361{
362 /* Process the message type */
363 switch (msg->type) {
364 case PSA_IPC_CALL:
365 return tfm_crypto_call_srv(msg);
366 default:
367 return PSA_ERROR_NOT_SUPPORTED;
368 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100369
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800370 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100371}
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800372#endif