blob: 0694ae6731dd24052f9afb4d14e83584821a69bc [file] [log] [blame]
Antonio de Angelis8908f472018-08-31 15:44:25 +01001/*
Summer Qina5448d62020-12-07 14:03:37 +08002 * Copyright (c) 2018-2021, 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"
30#endif /* CRYPTO_HW_ACCLERATOR */
31
Antonio de Angelis4743e672019-04-11 11:38:48 +010032#ifdef TFM_PSA_API
Jamie Foxcc31d402019-01-28 17:13:52 +000033#include "psa/service.h"
Edison Aicc4c6162019-06-21 13:52:49 +080034#include "psa_manifest/tfm_crypto.h"
David Hu49a28eb2019-08-14 18:18:15 +080035#include "tfm_memory_utils.h"
Antonio de Angelis4743e672019-04-11 11:38:48 +010036
37/**
38 * \brief Table containing all the Uniform Signature API exposed
39 * by the TF-M Crypto partition
40 */
Edison Ai080b2e22019-04-17 16:27:21 +080041static const tfm_crypto_us_t sfid_func_table[TFM_CRYPTO_SID_MAX] = {
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +010042#define X(api_name) api_name,
43LIST_TFM_CRYPTO_UNIFORM_SIGNATURE_API
44#undef X
Antonio de Angelis4743e672019-04-11 11:38:48 +010045};
46
47/**
48 * \brief Aligns a value x up to an alignment a.
49 */
50#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
51
52/**
53 * \brief Maximum alignment required by any iovec parameters to the TF-M Crypto
54 * partition.
55 */
56#define TFM_CRYPTO_IOVEC_ALIGNMENT (4u)
57
58/**
59 * \brief Default size of the internal scratch buffer used for IOVec allocations
60 * in bytes
61 */
62#ifndef TFM_CRYPTO_IOVEC_BUFFER_SIZE
Soby Mathew7740b602020-10-07 12:08:28 +010063#error TFM_CRYPTO_IOVEC_BUFFER_SIZE is not defined
Antonio de Angelis4743e672019-04-11 11:38:48 +010064#endif
65
66/**
67 * \brief Internal scratch used for IOVec allocations
68 *
69 */
70static struct tfm_crypto_scratch {
71 __attribute__((__aligned__(TFM_CRYPTO_IOVEC_ALIGNMENT)))
72 uint8_t buf[TFM_CRYPTO_IOVEC_BUFFER_SIZE];
73 uint32_t alloc_index;
Antonio de Angelis60a6fe62019-06-18 15:27:34 +010074 int32_t owner;
Antonio de Angelis4743e672019-04-11 11:38:48 +010075} scratch = {.buf = {0}, .alloc_index = 0};
76
Antonio de Angelis60a6fe62019-06-18 15:27:34 +010077static psa_status_t tfm_crypto_set_scratch_owner(int32_t id)
78{
79 scratch.owner = id;
80 return PSA_SUCCESS;
81}
82
83static psa_status_t tfm_crypto_get_scratch_owner(int32_t *id)
84{
85 *id = scratch.owner;
86 return PSA_SUCCESS;
87}
88
Antonio de Angelis4743e672019-04-11 11:38:48 +010089static psa_status_t tfm_crypto_alloc_scratch(size_t requested_size, void **buf)
90{
91 /* Ensure alloc_index remains aligned to the required iovec alignment */
92 requested_size = ALIGN(requested_size, TFM_CRYPTO_IOVEC_ALIGNMENT);
93
94 if (requested_size > (sizeof(scratch.buf) - scratch.alloc_index)) {
95 return PSA_ERROR_INSUFFICIENT_MEMORY;
96 }
97
98 /* Compute the pointer to the allocated space */
99 *buf = (void *)&scratch.buf[scratch.alloc_index];
100
101 /* Increase the allocated size */
102 scratch.alloc_index += requested_size;
103
104 return PSA_SUCCESS;
105}
106
Summer Qin0a9e5372020-11-27 16:04:05 +0800107void tfm_crypto_clear_scratch(void)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100108{
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100109 scratch.owner = 0;
Summer Qin0a9e5372020-11-27 16:04:05 +0800110 (void)tfm_memset(scratch.buf, 0, scratch.alloc_index);
111 scratch.alloc_index = 0;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100112}
113
114static psa_status_t tfm_crypto_call_sfn(psa_msg_t *msg,
115 struct tfm_crypto_pack_iovec *iov,
116 const uint32_t sfn_id)
117{
118 psa_status_t status = PSA_SUCCESS;
TTornblomfaf74f52020-03-04 17:56:27 +0100119 size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, i;
Soby Mathewd8abdfd2020-10-14 10:28:01 +0100120 psa_invec in_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
121 psa_outvec out_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
Antonio de Angelis4743e672019-04-11 11:38:48 +0100122 void *alloc_buf_ptr = NULL;
123
124 /* Check the number of in_vec filled */
Jamie Fox9a234e22019-04-30 11:12:05 +0100125 while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
126 in_len--;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100127 }
128
129 /* There will always be a tfm_crypto_pack_iovec in the first iovec */
130 if (in_len < 1) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100131 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100132 }
133 /* Initialise the first iovec with the IOV read when parsing */
134 in_vec[0].base = iov;
135 in_vec[0].len = sizeof(struct tfm_crypto_pack_iovec);
136
137 /* Alloc/read from the second element as the first is read when parsing */
138 for (i = 1; i < in_len; i++) {
139 /* Allocate necessary space in the internal scratch */
140 status = tfm_crypto_alloc_scratch(msg->in_size[i], &alloc_buf_ptr);
141 if (status != PSA_SUCCESS) {
Summer Qin0a9e5372020-11-27 16:04:05 +0800142 tfm_crypto_clear_scratch();
Antonio de Angelis4743e672019-04-11 11:38:48 +0100143 return status;
144 }
145 /* Read from the IPC framework inputs into the scratch */
TTornblomfaf74f52020-03-04 17:56:27 +0100146 (void) psa_read(msg->handle, i, alloc_buf_ptr, msg->in_size[i]);
Antonio de Angelis4743e672019-04-11 11:38:48 +0100147 /* Populate the fields of the input to the secure function */
148 in_vec[i].base = alloc_buf_ptr;
149 in_vec[i].len = msg->in_size[i];
150 }
151
152 /* Check the number of out_vec filled */
Jamie Fox9a234e22019-04-30 11:12:05 +0100153 while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
154 out_len--;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100155 }
156
157 for (i = 0; i < out_len; i++) {
158 /* Allocate necessary space for the output in the internal scratch */
159 status = tfm_crypto_alloc_scratch(msg->out_size[i], &alloc_buf_ptr);
160 if (status != PSA_SUCCESS) {
Summer Qin0a9e5372020-11-27 16:04:05 +0800161 tfm_crypto_clear_scratch();
Antonio de Angelis4743e672019-04-11 11:38:48 +0100162 return status;
163 }
164 /* Populate the fields of the output to the secure function */
165 out_vec[i].base = alloc_buf_ptr;
166 out_vec[i].len = msg->out_size[i];
167 }
168
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100169 /* Set the owner of the data in the scratch */
170 (void)tfm_crypto_set_scratch_owner(msg->client_id);
171
Antonio de Angelis4743e672019-04-11 11:38:48 +0100172 /* Call the uniform signature API */
173 status = sfid_func_table[sfn_id](in_vec, in_len, out_vec, out_len);
174
175 /* Write into the IPC framework outputs from the scratch */
176 for (i = 0; i < out_len; i++) {
177 psa_write(msg->handle, i, out_vec[i].base, out_vec[i].len);
178 }
179
180 /* Clear the allocated internal scratch before returning */
Summer Qin0a9e5372020-11-27 16:04:05 +0800181 tfm_crypto_clear_scratch();
Antonio de Angelis4743e672019-04-11 11:38:48 +0100182
183 return status;
184}
185
186static psa_status_t tfm_crypto_parse_msg(psa_msg_t *msg,
187 struct tfm_crypto_pack_iovec *iov,
188 uint32_t *sfn_id_p)
189{
190 size_t read_size;
191
192 /* Read the in_vec[0] which holds the IOVEC always */
193 read_size = psa_read(msg->handle,
194 0,
195 iov,
196 sizeof(struct tfm_crypto_pack_iovec));
197
198 if (read_size != sizeof(struct tfm_crypto_pack_iovec)) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100199 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100200 }
201
Edison Ai080b2e22019-04-17 16:27:21 +0800202 if (iov->sfn_id >= TFM_CRYPTO_SID_MAX) {
203 *sfn_id_p = TFM_CRYPTO_SID_INVALID;
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100204 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100205 }
206
207 *sfn_id_p = iov->sfn_id;
208
209 return PSA_SUCCESS;
210}
211
212static void tfm_crypto_ipc_handler(void)
213{
214 psa_signal_t signals = 0;
215 psa_msg_t msg;
216 psa_status_t status = PSA_SUCCESS;
Edison Ai080b2e22019-04-17 16:27:21 +0800217 uint32_t sfn_id = TFM_CRYPTO_SID_INVALID;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100218 struct tfm_crypto_pack_iovec iov = {0};
219
220 while (1) {
221 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
Edison Ai45b22552019-10-12 11:05:57 +0800222 if (signals & TFM_CRYPTO_SIGNAL) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100223 /* Extract the message */
Edison Ai45b22552019-10-12 11:05:57 +0800224 if (psa_get(TFM_CRYPTO_SIGNAL, &msg) != PSA_SUCCESS) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100225 /* FIXME: Should be replaced by TF-M error handling */
226 while (1) {
227 ;
228 }
229 }
230
231 /* Process the message type */
232 switch (msg.type) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100233 case PSA_IPC_CALL:
234 /* Parse the message */
235 status = tfm_crypto_parse_msg(&msg, &iov, &sfn_id);
Edison Ai080b2e22019-04-17 16:27:21 +0800236 /* Call the dispatcher based on the SID passed as type */
237 if (sfn_id != TFM_CRYPTO_SID_INVALID) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100238 status = tfm_crypto_call_sfn(&msg, &iov, sfn_id);
239 } else {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100240 status = PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100241 }
242 psa_reply(msg.handle, status);
243 break;
244 default:
245 /* FIXME: Should be replaced by TF-M error handling */
246 while (1) {
247 ;
248 }
249 }
250 } else {
251 /* FIXME: Should be replaced by TF-M error handling */
252 while (1) {
253 ;
254 }
255 }
256 }
257
TTornblomfaf74f52020-03-04 17:56:27 +0100258 /* NOTREACHED */
Antonio de Angelis4743e672019-04-11 11:38:48 +0100259 return;
260}
261#endif /* TFM_PSA_API */
262
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100263/**
264 * \brief Default value for the size of the static buffer used by Mbed
265 * Crypto for its dynamic allocations
266 */
267#ifndef TFM_CRYPTO_ENGINE_BUF_SIZE
Soby Mathew7740b602020-10-07 12:08:28 +0100268#error TFM_CRYPTO_ENGINE_BUF_SIZE is not defined
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100269#endif
270
271/**
272 * \brief Static buffer to be used by Mbed Crypto for memory allocations
273 *
274 */
275static uint8_t mbedtls_mem_buf[TFM_CRYPTO_ENGINE_BUF_SIZE] = {0};
276
277static psa_status_t tfm_crypto_engine_init(void)
278{
Raef Coles618fc152021-06-18 09:26:46 +0100279
280#ifdef CRYPTO_NV_SEED
281#ifdef TFM_PSA_API
282 if (tfm_plat_crypto_provision_entropy_seed() != TFM_CRYPTO_NV_SEED_SUCCESS) {
Summer Qina5448d62020-12-07 14:03:37 +0800283 return PSA_ERROR_GENERIC_ERROR;
284 }
Raef Coles618fc152021-06-18 09:26:46 +0100285#else
286 LOG_INFFMT("\033[1;31m[Crypto] ");
287 LOG_INFFMT("TF-M in library mode uses a dummy NV seed. ");
288 LOG_INFFMT("This is not suitable for production! ");
289 LOG_INFFMT("This device is \033[1;1mNOT SECURE");
290 LOG_INFFMT("\033[0m\r\n");
291#endif /* TFM_PSA_API */
292#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +0800293
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100294 /* Initialise the Mbed Crypto memory allocator to use static
295 * memory allocation from the provided buffer instead of using
296 * the heap
297 */
298 mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf,
299 TFM_CRYPTO_ENGINE_BUF_SIZE);
300
Raef Colesd2485af2019-10-30 10:15:33 +0000301 /* Initialise the crypto accelerator if one is enabled */
302#ifdef CRYPTO_HW_ACCELERATOR
303 if (crypto_hw_accelerator_init() != 0) {
304 return PSA_ERROR_HARDWARE_FAILURE;
305 }
306#endif /* CRYPTO_HW_ACCELERATOR */
307
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100308 /* Previous function does not return any value, so just call the
309 * initialisation function of the Mbed Crypto layer
310 */
311 return psa_crypto_init();
312}
313
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000314static psa_status_t tfm_crypto_module_init(void)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100315{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100316 /* Init the Alloc module */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000317 return tfm_crypto_init_alloc();
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100318}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100319
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100320psa_status_t tfm_crypto_get_caller_id(int32_t *id)
321{
322#ifdef TFM_PSA_API
323 return tfm_crypto_get_scratch_owner(id);
324#else
325 int32_t res;
326
327 res = tfm_core_get_caller_client_id(id);
328 if (res != TFM_SUCCESS) {
329 return PSA_ERROR_NOT_PERMITTED;
330 } else {
331 return PSA_SUCCESS;
332 }
333#endif
334}
335
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000336psa_status_t tfm_crypto_init(void)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100337{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100338 psa_status_t status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100339
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100340 /* Initialise other modules of the service */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000341 status = tfm_crypto_module_init();
342 if (status != PSA_SUCCESS) {
343 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100344 }
345
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100346 /* Initialise the engine layer */
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100347 status = tfm_crypto_engine_init();
348 if (status != PSA_SUCCESS) {
Antonio de Angelis4743e672019-04-11 11:38:48 +0100349 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100350 }
Antonio de Angelis8908f472018-08-31 15:44:25 +0100351
Antonio de Angelis4743e672019-04-11 11:38:48 +0100352#ifdef TFM_PSA_API
353 /* Should not return in normal operations */
354 tfm_crypto_ipc_handler();
355#endif
356
357 return status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100358}