1 /*
2 * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11
12 #include "config_tfm.h"
13 #include "tfm_mbedcrypto_include.h"
14
15 #include "tfm_crypto_api.h"
16 #include "tfm_crypto_defs.h"
17
18 /**
19 * \brief Define miscellaneous literal constants that are used in the service
20 */
21 enum {
22 TFM_CRYPTO_NOT_IN_USE = 0,
23 TFM_CRYPTO_IN_USE = 1
24 };
25
26 /**
27 * \brief This value is used to mark an handle for multipart operations as invalid.
28 */
29 #define TFM_CRYPTO_INVALID_HANDLE (0x0u)
30
31 /**
32 * \brief A type describing the context stored in Secure memory by the TF-M Crypto
33 * service to support multipart calls on secure side
34 */
35 struct tfm_crypto_operation_s {
36 uint32_t in_use; /*!< Indicates if the operation is in use */
37 int32_t owner; /*!< Indicates an ID of the owner of
38 * the context
39 */
40 enum tfm_crypto_operation_type type; /*!< Type of the operation */
41 union {
42 psa_cipher_operation_t cipher; /*!< Cipher operation context */
43 psa_mac_operation_t mac; /*!< MAC operation context */
44 psa_hash_operation_t hash; /*!< Hash operation context */
45 psa_key_derivation_operation_t key_deriv; /*!< Key derivation operation context */
46 psa_aead_operation_t aead; /*!< AEAD operation context */
47 } operation;
48 };
49
50 static struct tfm_crypto_operation_s operations[CRYPTO_CONC_OPER_NUM] = {{0}};
51
52 /*
53 * \brief Function used to clear the memory associated to a backend context
54 *
55 * \param[in] index Numerical index in the database of the backend contexts
56 *
57 * \return None
58 *
59 */
memset_operation_context(uint32_t index)60 static void memset_operation_context(uint32_t index)
61 {
62 /* Clear the contents of the backend context */
63 (void)memset((uint8_t *)&(operations[index].operation), 0,
64 sizeof(operations[index].operation));
65 }
66
67 /*!
68 * \defgroup alloc Function that implement allocation and deallocation of
69 * contexts to be stored in the secure world for multipart
70 * operations
71 */
72
73 /*!@{*/
tfm_crypto_init_alloc(void)74 psa_status_t tfm_crypto_init_alloc(void)
75 {
76 /* Clear the contents of the local contexts */
77 (void)memset(operations, 0, sizeof(operations));
78 return PSA_SUCCESS;
79 }
80
tfm_crypto_operation_alloc(enum tfm_crypto_operation_type type,uint32_t * handle,void ** ctx)81 psa_status_t tfm_crypto_operation_alloc(enum tfm_crypto_operation_type type,
82 uint32_t *handle,
83 void **ctx)
84 {
85 uint32_t i = 0;
86 int32_t partition_id = 0;
87 psa_status_t status;
88
89 /* Handle must be initialised before calling a setup function */
90 if (*handle != TFM_CRYPTO_INVALID_HANDLE) {
91 return PSA_ERROR_BAD_STATE;
92 }
93
94 /* Init to invalid values */
95 if (ctx == NULL) {
96 return PSA_ERROR_INVALID_ARGUMENT;
97 }
98 *ctx = NULL;
99
100 status = tfm_crypto_get_caller_id(&partition_id);
101 if (status != PSA_SUCCESS) {
102 return status;
103 }
104
105 for (i = 0; i < CRYPTO_CONC_OPER_NUM; i++) {
106 if (operations[i].in_use == TFM_CRYPTO_NOT_IN_USE) {
107 operations[i].in_use = TFM_CRYPTO_IN_USE;
108 operations[i].owner = partition_id;
109 operations[i].type = type;
110 *handle = i + 1;
111 *ctx = (void *) &(operations[i].operation);
112 return PSA_SUCCESS;
113 }
114 }
115
116 return PSA_ERROR_NOT_PERMITTED;
117 }
118
tfm_crypto_operation_release(uint32_t * handle)119 psa_status_t tfm_crypto_operation_release(uint32_t *handle)
120 {
121 uint32_t h_val = *handle;
122 int32_t partition_id = 0;
123 psa_status_t status;
124
125 /* Handle shall be cleaned up always at first */
126 *handle = TFM_CRYPTO_INVALID_HANDLE;
127
128 if ((h_val == TFM_CRYPTO_INVALID_HANDLE) ||
129 (h_val > CRYPTO_CONC_OPER_NUM)) {
130 return PSA_ERROR_INVALID_ARGUMENT;
131 }
132
133 status = tfm_crypto_get_caller_id(&partition_id);
134 if (status != PSA_SUCCESS) {
135 return status;
136 }
137
138 if ((operations[h_val - 1].in_use == TFM_CRYPTO_IN_USE) &&
139 (operations[h_val - 1].owner == partition_id)) {
140
141 memset_operation_context(h_val - 1);
142 operations[h_val - 1].in_use = TFM_CRYPTO_NOT_IN_USE;
143 operations[h_val - 1].type = TFM_CRYPTO_OPERATION_NONE;
144 operations[h_val - 1].owner = 0;
145
146 return PSA_SUCCESS;
147 }
148
149 return PSA_ERROR_INVALID_ARGUMENT;
150 }
151
tfm_crypto_operation_lookup(enum tfm_crypto_operation_type type,uint32_t handle,void ** ctx)152 psa_status_t tfm_crypto_operation_lookup(enum tfm_crypto_operation_type type,
153 uint32_t handle,
154 void **ctx)
155 {
156 int32_t partition_id = 0;
157 psa_status_t status;
158
159 if ((handle == TFM_CRYPTO_INVALID_HANDLE) ||
160 (handle > CRYPTO_CONC_OPER_NUM)) {
161 return PSA_ERROR_BAD_STATE;
162 }
163
164 if (ctx == NULL) {
165 return PSA_ERROR_INVALID_ARGUMENT;
166 }
167
168 status = tfm_crypto_get_caller_id(&partition_id);
169 if (status != PSA_SUCCESS) {
170 return status;
171 }
172
173 if ((operations[handle - 1].in_use == TFM_CRYPTO_IN_USE) &&
174 (operations[handle - 1].type == type) &&
175 (operations[handle - 1].owner == partition_id)) {
176 *ctx = (void *) &(operations[handle - 1].operation);
177 return PSA_SUCCESS;
178 }
179
180 return PSA_ERROR_BAD_STATE;
181 }
182 /*!@}*/
183