blob: 0fb8a698b5b051b825de3038f67a5a6717a9abbe [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
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
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800114static psa_status_t tfm_crypto_call_srv(const psa_msg_t *msg)
Antonio de Angelis4743e672019-04-11 11:38:48 +0100115{
116 psa_status_t status = PSA_SUCCESS;
TTornblomfaf74f52020-03-04 17:56:27 +0100117 size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, i;
Soby Mathewd8abdfd2020-10-14 10:28:01 +0100118 psa_invec in_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
119 psa_outvec out_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800120 struct tfm_crypto_pack_iovec iov = {0};
Antonio de Angelis4743e672019-04-11 11:38:48 +0100121 void *alloc_buf_ptr = NULL;
122
123 /* Check the number of in_vec filled */
Jamie Fox9a234e22019-04-30 11:12:05 +0100124 while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
125 in_len--;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100126 }
127
128 /* There will always be a tfm_crypto_pack_iovec in the first iovec */
129 if (in_len < 1) {
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100130 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100131 }
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800132
133 if (psa_read(msg->handle, 0, &iov, sizeof(iov)) != sizeof(iov)) {
134 return PSA_ERROR_GENERIC_ERROR;
135 }
136
137 if (iov.srv_id >= TFM_CRYPTO_SID_MAX) {
138 return PSA_ERROR_GENERIC_ERROR;
139 }
140
Antonio de Angelis4743e672019-04-11 11:38:48 +0100141 /* Initialise the first iovec with the IOV read when parsing */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800142 in_vec[0].base = &iov;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100143 in_vec[0].len = sizeof(struct tfm_crypto_pack_iovec);
144
145 /* Alloc/read from the second element as the first is read when parsing */
146 for (i = 1; i < in_len; i++) {
147 /* Allocate necessary space in the internal scratch */
148 status = tfm_crypto_alloc_scratch(msg->in_size[i], &alloc_buf_ptr);
149 if (status != PSA_SUCCESS) {
Summer Qin0a9e5372020-11-27 16:04:05 +0800150 tfm_crypto_clear_scratch();
Antonio de Angelis4743e672019-04-11 11:38:48 +0100151 return status;
152 }
153 /* Read from the IPC framework inputs into the scratch */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800154 in_vec[i].len =
155 psa_read(msg->handle, i, alloc_buf_ptr, msg->in_size[i]);
Antonio de Angelis4743e672019-04-11 11:38:48 +0100156 /* Populate the fields of the input to the secure function */
157 in_vec[i].base = alloc_buf_ptr;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100158 }
159
160 /* Check the number of out_vec filled */
Jamie Fox9a234e22019-04-30 11:12:05 +0100161 while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
162 out_len--;
Antonio de Angelis4743e672019-04-11 11:38:48 +0100163 }
164
165 for (i = 0; i < out_len; i++) {
166 /* Allocate necessary space for the output in the internal scratch */
167 status = tfm_crypto_alloc_scratch(msg->out_size[i], &alloc_buf_ptr);
168 if (status != PSA_SUCCESS) {
Summer Qin0a9e5372020-11-27 16:04:05 +0800169 tfm_crypto_clear_scratch();
Antonio de Angelis4743e672019-04-11 11:38:48 +0100170 return status;
171 }
172 /* Populate the fields of the output to the secure function */
173 out_vec[i].base = alloc_buf_ptr;
174 out_vec[i].len = msg->out_size[i];
175 }
176
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100177 /* Set the owner of the data in the scratch */
178 (void)tfm_crypto_set_scratch_owner(msg->client_id);
179
Antonio de Angelis4743e672019-04-11 11:38:48 +0100180 /* Call the uniform signature API */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800181 status = sfid_func_table[iov.srv_id](in_vec, in_len, out_vec, out_len);
Antonio de Angelis4743e672019-04-11 11:38:48 +0100182
183 /* Write into the IPC framework outputs from the scratch */
184 for (i = 0; i < out_len; i++) {
185 psa_write(msg->handle, i, out_vec[i].base, out_vec[i].len);
186 }
187
188 /* Clear the allocated internal scratch before returning */
Summer Qin0a9e5372020-11-27 16:04:05 +0800189 tfm_crypto_clear_scratch();
Antonio de Angelis4743e672019-04-11 11:38:48 +0100190
191 return status;
192}
193
Antonio de Angelis4743e672019-04-11 11:38:48 +0100194#endif /* TFM_PSA_API */
195
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100196/**
197 * \brief Default value for the size of the static buffer used by Mbed
198 * Crypto for its dynamic allocations
199 */
200#ifndef TFM_CRYPTO_ENGINE_BUF_SIZE
Soby Mathew7740b602020-10-07 12:08:28 +0100201#error TFM_CRYPTO_ENGINE_BUF_SIZE is not defined
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100202#endif
203
204/**
205 * \brief Static buffer to be used by Mbed Crypto for memory allocations
206 *
207 */
208static uint8_t mbedtls_mem_buf[TFM_CRYPTO_ENGINE_BUF_SIZE] = {0};
209
210static psa_status_t tfm_crypto_engine_init(void)
211{
Raef Coles618fc152021-06-18 09:26:46 +0100212
213#ifdef CRYPTO_NV_SEED
214#ifdef TFM_PSA_API
215 if (tfm_plat_crypto_provision_entropy_seed() != TFM_CRYPTO_NV_SEED_SUCCESS) {
Summer Qina5448d62020-12-07 14:03:37 +0800216 return PSA_ERROR_GENERIC_ERROR;
217 }
Raef Coles618fc152021-06-18 09:26:46 +0100218#else
219 LOG_INFFMT("\033[1;31m[Crypto] ");
220 LOG_INFFMT("TF-M in library mode uses a dummy NV seed. ");
221 LOG_INFFMT("This is not suitable for production! ");
222 LOG_INFFMT("This device is \033[1;1mNOT SECURE");
223 LOG_INFFMT("\033[0m\r\n");
224#endif /* TFM_PSA_API */
225#endif /* CRYPTO_NV_SEED */
Summer Qina5448d62020-12-07 14:03:37 +0800226
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100227 /* Initialise the Mbed Crypto memory allocator to use static
228 * memory allocation from the provided buffer instead of using
229 * the heap
230 */
231 mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf,
232 TFM_CRYPTO_ENGINE_BUF_SIZE);
233
Raef Colesd2485af2019-10-30 10:15:33 +0000234 /* Initialise the crypto accelerator if one is enabled */
235#ifdef CRYPTO_HW_ACCELERATOR
236 if (crypto_hw_accelerator_init() != 0) {
237 return PSA_ERROR_HARDWARE_FAILURE;
238 }
239#endif /* CRYPTO_HW_ACCELERATOR */
240
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100241 /* Previous function does not return any value, so just call the
242 * initialisation function of the Mbed Crypto layer
243 */
244 return psa_crypto_init();
245}
246
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000247static psa_status_t tfm_crypto_module_init(void)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100248{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100249 /* Init the Alloc module */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000250 return tfm_crypto_init_alloc();
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100251}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100252
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100253psa_status_t tfm_crypto_get_caller_id(int32_t *id)
254{
255#ifdef TFM_PSA_API
256 return tfm_crypto_get_scratch_owner(id);
257#else
258 int32_t res;
259
260 res = tfm_core_get_caller_client_id(id);
261 if (res != TFM_SUCCESS) {
262 return PSA_ERROR_NOT_PERMITTED;
263 } else {
264 return PSA_SUCCESS;
265 }
266#endif
267}
268
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000269psa_status_t tfm_crypto_init(void)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100270{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100271 psa_status_t status;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100272
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100273 /* Initialise other modules of the service */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000274 status = tfm_crypto_module_init();
275 if (status != PSA_SUCCESS) {
276 return status;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100277 }
278
Jamie Fox0e54ebc2019-04-09 14:21:04 +0100279 /* Initialise the engine layer */
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800280 return tfm_crypto_engine_init();
281}
Antonio de Angelis8908f472018-08-31 15:44:25 +0100282
Antonio de Angelis4743e672019-04-11 11:38:48 +0100283#ifdef TFM_PSA_API
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800284psa_status_t tfm_crypto_sfn(const psa_msg_t *msg)
285{
286 /* Process the message type */
287 switch (msg->type) {
288 case PSA_IPC_CALL:
289 return tfm_crypto_call_srv(msg);
290 default:
291 return PSA_ERROR_NOT_SUPPORTED;
292 }
Antonio de Angelis4743e672019-04-11 11:38:48 +0100293
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800294 return PSA_ERROR_GENERIC_ERROR;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100295}
Kevin Peng2d4bc2e2022-01-28 16:19:30 +0800296#endif