blob: 87050299a33fa08d48296471c4f57d3f9de821d4 [file] [log] [blame]
Antonio de Angelis8908f472018-08-31 15:44:25 +01001/*
Antonio de Angelis377a1552018-11-22 17:02:40 +00002 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
Antonio de Angelis8908f472018-08-31 15:44:25 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <limits.h>
9
10#include "tfm_crypto_defs.h"
11
Antonio de Angelis8908f472018-08-31 15:44:25 +010012#include "psa_crypto.h"
13#include "tfm_crypto_api.h"
14
Antonio de Angelis377a1552018-11-22 17:02:40 +000015#include "tfm_crypto_struct.h"
Tamas Ban8bd24b72019-02-19 12:13:13 +000016#include "secure_fw/core/tfm_memory_utils.h"
Antonio de Angelis8908f472018-08-31 15:44:25 +010017
18/**
Antonio de Angelis819c2f32019-02-06 14:32:02 +000019 * \def LIST_OPERATION_LOOKUP
20 *
21 * \brief This is an X macro which enforces the correspondence
22 * between backend operation type (through the enum
23 * tfm_crypto_operation_type) and the corresponding frontend type
24 */
25#define LIST_OPERATION_LOOKUP \
26 X(TFM_CRYPTO_CIPHER_OPERATION, psa_cipher_operation_t) \
27 X(TFM_CRYPTO_MAC_OPERATION, psa_mac_operation_t) \
28 X(TFM_CRYPTO_HASH_OPERATION, psa_hash_operation_t)
29
30/**
31 * \def CHECK_ALIGNMENT
32 *
33 * \brief This macro checks the alignment of the operation object pointer which
34 * receives as input based on the requirement of the front end operation
35 * type. This macro expands in a case statement so it must be used in a
36 * switch-case construct. It sets the handle value it receives in input
37 * with the proper value or TFM_CRYPTO_INVALID_HANDLE in case the oper
38 * pointer does not satisfy alignment requirements of the front end type
39 */
40#define CHECK_ALIGNMENT(e,t,oper,handle) \
41 case e: \
42 if ((uintptr_t)oper % offsetof(struct {char c; t x;},x)) { \
43 handle = TFM_CRYPTO_INVALID_HANDLE; \
44 } else { \
45 handle = ((t *)oper)->handle; \
46 } \
47 break;
48/**
49 * \def GET_HANDLE_POINTER
50 *
51 * \brief This macro extracts the pointer to handle value from the object
52 * operation pointer it receives as input. This macro expands in a case
53 * statement so it must be used in a switch case-case construct.
54 */
55#define GET_HANDLE_POINTER(e,t,oper,handle) \
56 case e: \
57 handle = &(((t *)oper)->handle); \
58 break;
59/**
60 * \def TFM_CRYPTO_CONC_OPER_NUM
61 *
Antonio de Angelis8908f472018-08-31 15:44:25 +010062 * \brief This value defines the maximum number of simultaneous operations
63 * supported by this implementation.
64 */
65#define TFM_CRYPTO_CONC_OPER_NUM (8)
66
Antonio de Angelis8908f472018-08-31 15:44:25 +010067struct tfm_crypto_operation_s {
68 uint32_t in_use; /*!< Indicates if the operation is in use */
69 enum tfm_crypto_operation_type type; /*!< Type of the operation */
70 union {
Antonio de Angelis377a1552018-11-22 17:02:40 +000071 struct tfm_cipher_operation_s cipher; /*!< Cipher operation context */
72 struct tfm_mac_operation_s mac; /*!< MAC operation context */
73 struct tfm_hash_operation_s hash; /*!< Hash operation context */
Antonio de Angelis8908f472018-08-31 15:44:25 +010074 } operation;
75};
76
77static struct tfm_crypto_operation_s operation[TFM_CRYPTO_CONC_OPER_NUM] ={{0}};
78
Antonio de Angelis819c2f32019-02-06 14:32:02 +000079/*
80 * \brief Function used to clear the memory associated to a backend context
81 *
82 * \param[in] index Numerical index in the database of the backend contexts
83 *
84 * \return None
85 *
86 */
Antonio de Angelis8908f472018-08-31 15:44:25 +010087static void memset_operation_context(uint32_t index)
88{
Antonio de Angelis819c2f32019-02-06 14:32:02 +000089 uint32_t mem_size;
Antonio de Angelis8908f472018-08-31 15:44:25 +010090
Antonio de Angelis819c2f32019-02-06 14:32:02 +000091 uint8_t *mem_ptr = (uint8_t *) &(operation[index].operation);
Antonio de Angelis8908f472018-08-31 15:44:25 +010092
93 switch(operation[index].type) {
94 case TFM_CRYPTO_CIPHER_OPERATION:
Antonio de Angelis377a1552018-11-22 17:02:40 +000095 mem_size = sizeof(struct tfm_cipher_operation_s);
Antonio de Angelis8908f472018-08-31 15:44:25 +010096 break;
97 case TFM_CRYPTO_MAC_OPERATION:
Antonio de Angelis377a1552018-11-22 17:02:40 +000098 mem_size = sizeof(struct tfm_mac_operation_s);
Antonio de Angelis8908f472018-08-31 15:44:25 +010099 break;
100 case TFM_CRYPTO_HASH_OPERATION:
Antonio de Angelis377a1552018-11-22 17:02:40 +0000101 mem_size = sizeof(struct tfm_hash_operation_s);
Antonio de Angelis8908f472018-08-31 15:44:25 +0100102 break;
103 case TFM_CRYPTO_OPERATION_NONE:
104 default:
105 mem_size = 0;
106 break;
107 }
108
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000109 /* Clear the contents of the backend context */
110 (void)tfm_memset(mem_ptr, 0, mem_size);
111}
112
113/*
114 * \brief Function used to extract the handle value from a pointer to a
115 * frontend operation
116 *
117 * \param[in] type Type of the operation context to extract from
118 * \param[in] oper Pointer to the frontend operation
119 *
120 * \return handle 4-byte identifier associated to the context,
121 * TFM_CRYPTO_INVALID_HANDLE in case of problems
122 *
123 */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000124static uint32_t get_handle(enum tfm_crypto_operation_type type,
125 const void *oper)
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000126{
127 uint32_t handle = TFM_CRYPTO_INVALID_HANDLE;
128
129 /* Dereference the pointer */
130 switch(type) {
131 /* Generate the list of cases needed to check alignment for all the
132 * possible operation types listed in LIST_OPERATION_LOOKUP. The default
133 * case and TFM_CRYPTO_OPERATION_NONE must be created explicitly
134 */
135#define X(e,t) CHECK_ALIGNMENT(e,t,oper,handle)
136LIST_OPERATION_LOOKUP
137#undef X
138 case TFM_CRYPTO_OPERATION_NONE:
139 default:
140 break;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100141 }
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000142
143 return handle;
144}
145
146/*
147 * \brief Function used to set the handle value in a pointer to a
148 * frontend operation
149 *
150 * \param[in] type Type of the operation context to extract from
151 * \param[out] oper Pointer to the frontend operation
152 *
153 * \return handle 4-byte identifier associated to the context,
154 * TFM_CRYPTO_INVALID_HANDLE in case of problems
155 *
156 */
157static uint32_t set_handle(enum tfm_crypto_operation_type type,
158 void *oper,
159 uint32_t set_value)
160{
161 uint32_t *handle = NULL;
162
163 /* Extract the pointer value */
164 switch(type) {
165 /* Generate the list of cases needed to get the handle pointer for all the
166 * possible operation types listed in LIST_OPERATION_LOOKUP. The default
167 * case and TFM_CRYPTO_OPERATION_NONE must be created explicitly
168 */
169#define X(e,t) GET_HANDLE_POINTER(e,t,oper,handle)
170LIST_OPERATION_LOOKUP
171#undef X
172 case TFM_CRYPTO_OPERATION_NONE:
173 default:
174 break;
175 }
176
177 if (handle == NULL || ((uintptr_t)handle % sizeof(uint32_t))) {
178 return TFM_CRYPTO_INVALID_HANDLE;
179 }
180
181 /* Set the value by derefencing the pointer, alignment is correct */
182 *handle = set_value;
183
184 return set_value;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100185}
186
187/*!
188 * \defgroup public Public functions
189 *
190 */
191
192/*!@{*/
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000193psa_status_t tfm_crypto_init_alloc(void)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100194{
195 /* Clear the contents of the local contexts */
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000196 (void)tfm_memset(operation, 0, sizeof(operation));
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000197 return PSA_SUCCESS;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100198}
199
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000200psa_status_t tfm_crypto_operation_alloc(enum tfm_crypto_operation_type type,
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000201 void *oper,
202 void **ctx)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100203{
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000204 uint32_t i = 0, handle;
205
206 /* Init to invalid values */
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000207 if (ctx == NULL) {
208 return PSA_ERROR_INVALID_ARGUMENT;
209 }
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000210 *ctx = NULL;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100211
212 for (i=0; i<TFM_CRYPTO_CONC_OPER_NUM; i++) {
213 if (operation[i].in_use == TFM_CRYPTO_NOT_IN_USE) {
214 operation[i].in_use = TFM_CRYPTO_IN_USE;
215 operation[i].type = type;
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000216 handle = set_handle(type, oper, i);
217 if (handle == TFM_CRYPTO_INVALID_HANDLE) {
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000218 return PSA_ERROR_NOT_PERMITTED;
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000219 }
220 *ctx = (void *) &(operation[i].operation);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000221 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100222 }
223 }
Antonio de Angelis8908f472018-08-31 15:44:25 +0100224
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000225 return PSA_ERROR_NOT_PERMITTED;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100226}
227
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000228psa_status_t tfm_crypto_operation_release(enum tfm_crypto_operation_type type,
229 void *oper)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100230{
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000231 uint32_t handle = get_handle(type, oper);
Antonio de Angelis8908f472018-08-31 15:44:25 +0100232
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000233 if ( (handle != TFM_CRYPTO_INVALID_HANDLE) &&
234 (handle < TFM_CRYPTO_CONC_OPER_NUM) &&
235 (operation[handle].in_use == TFM_CRYPTO_IN_USE) ) {
236 memset_operation_context(handle);
237 operation[handle].in_use = TFM_CRYPTO_NOT_IN_USE;
238 operation[handle].type = TFM_CRYPTO_OPERATION_NONE;
239 (void)set_handle(type, oper, TFM_CRYPTO_INVALID_HANDLE);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000240 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100241 }
242
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000243 return PSA_ERROR_INVALID_ARGUMENT;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100244}
245
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000246psa_status_t tfm_crypto_operation_lookup(enum tfm_crypto_operation_type type,
247 const void *oper,
248 void **ctx)
Antonio de Angelis8908f472018-08-31 15:44:25 +0100249{
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000250 uint32_t handle = get_handle(type, oper);
251
252 if ( (handle != TFM_CRYPTO_INVALID_HANDLE) &&
253 (handle < TFM_CRYPTO_CONC_OPER_NUM) &&
Antonio de Angelis377a1552018-11-22 17:02:40 +0000254 (operation[handle].in_use == TFM_CRYPTO_IN_USE) &&
255 (operation[handle].type == type) ) {
Antonio de Angelis819c2f32019-02-06 14:32:02 +0000256 *ctx = (void *) &(operation[handle].operation);
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000257 return PSA_SUCCESS;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100258 }
259
Antonio de Angelisab85ccd2019-03-25 15:14:29 +0000260 return PSA_ERROR_BAD_STATE;
Antonio de Angelis8908f472018-08-31 15:44:25 +0100261}
262/*!@}*/