1 /*
2 * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include "config_tfm.h"
12 #include "tfm_mbedcrypto_include.h"
13
14 #include "tfm_crypto_api.h"
15 #include "tfm_crypto_defs.h"
16
17 /*!
18 * \addtogroup tfm_crypto_api_shim_layer
19 *
20 */
21
22 /*!@{*/
23 #if CRYPTO_HASH_MODULE_ENABLED
24 /**
25 * \brief Check whether PSA is capable of handling the specified hash algorithm.
26 *
27 * \note As service initialization is performed during TF-M boot up, so there is no need
28 * to check whether psa_crypto_init has already been called.
29 *
30 * \param[in] alg The hash algorithm.
31 *
32 * \return 1 if the PSA can handle \p alg, 0 otherwise.
33 */
tfm_crypto_can_do_hash(psa_algorithm_t alg)34 static int tfm_crypto_can_do_hash(psa_algorithm_t alg)
35 {
36 switch (alg) {
37 #if defined(PSA_WANT_ALG_MD5)
38 case PSA_ALG_MD5:
39 return 1;
40 #endif
41 #if defined(PSA_WANT_ALG_RIPEMD160)
42 case PSA_ALG_RIPEMD160:
43 return 1;
44 #endif
45 #if defined(PSA_WANT_ALG_SHA_1)
46 case PSA_ALG_SHA_1:
47 return 1;
48 #endif
49 #if defined(PSA_WANT_ALG_SHA_224)
50 case PSA_ALG_SHA_224:
51 return 1;
52 #endif
53 #if defined(PSA_WANT_ALG_SHA_256)
54 case PSA_ALG_SHA_256:
55 return 1;
56 #endif
57 #if defined(PSA_WANT_ALG_SHA_384)
58 case PSA_ALG_SHA_384:
59 return 1;
60 #endif
61 #if defined(PSA_WANT_ALG_SHA_512)
62 case PSA_ALG_SHA_512:
63 return 1;
64 #endif
65 #if defined(PSA_WANT_ALG_SHA3_224)
66 case PSA_ALG_SHA3_224:
67 return 1;
68 #endif
69 #if defined(PSA_WANT_ALG_SHA3_256)
70 case PSA_ALG_SHA3_256:
71 return 1;
72 #endif
73 #if defined(PSA_WANT_ALG_SHA3_384)
74 case PSA_ALG_SHA3_384:
75 return 1;
76 #endif
77 #if defined(PSA_WANT_ALG_SHA3_512)
78 case PSA_ALG_SHA3_512:
79 return 1;
80 #endif
81 default:
82 return 0;
83 }
84 }
85
tfm_crypto_hash_interface(psa_invec in_vec[],psa_outvec out_vec[])86 psa_status_t tfm_crypto_hash_interface(psa_invec in_vec[],
87 psa_outvec out_vec[])
88 {
89 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
90 psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
91 psa_hash_operation_t *operation = NULL;
92 uint32_t *p_handle = NULL;
93 enum tfm_crypto_func_sid_t sid = (enum tfm_crypto_func_sid_t)iov->function_id;
94
95 if (sid == TFM_CRYPTO_CAN_DO_HASH_SID)
96 {
97 int *p_result = out_vec[0].base;
98 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(int))) {
99 return PSA_ERROR_PROGRAMMER_ERROR;
100 }
101
102 *p_result = tfm_crypto_can_do_hash(iov->alg);
103 return PSA_SUCCESS;
104 }
105
106 if (sid == TFM_CRYPTO_HASH_COMPUTE_SID) {
107 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
108 return PSA_ERROR_NOT_SUPPORTED;
109 #else
110 const uint8_t *input = in_vec[1].base;
111 size_t input_length = in_vec[1].len;
112 uint8_t *hash = out_vec[0].base;
113 size_t hash_size = out_vec[0].len;
114
115 status = psa_hash_compute(iov->alg, input, input_length,
116 hash, hash_size, &out_vec[0].len);
117 if (status != PSA_SUCCESS) {
118 out_vec[0].len = 0;
119 }
120 return status;
121 #endif
122 }
123
124 if (sid == TFM_CRYPTO_HASH_COMPARE_SID) {
125 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
126 return PSA_ERROR_NOT_SUPPORTED;
127 #else
128 const uint8_t *input = in_vec[1].base;
129 size_t input_length = in_vec[1].len;
130 const uint8_t *hash = in_vec[2].base;
131 size_t hash_length = in_vec[2].len;
132
133 return psa_hash_compare(iov->alg, input, input_length,
134 hash, hash_length);
135 #endif
136 }
137
138 if (sid == TFM_CRYPTO_HASH_SETUP_SID) {
139 p_handle = out_vec[0].base;
140 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
141 return PSA_ERROR_PROGRAMMER_ERROR;
142 }
143 *p_handle = iov->op_handle;
144 status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
145 out_vec[0].base,
146 (void **)&operation);
147 } else {
148 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
149 iov->op_handle,
150 (void **)&operation);
151 if ((sid == TFM_CRYPTO_HASH_FINISH_SID) ||
152 (sid == TFM_CRYPTO_HASH_VERIFY_SID) ||
153 (sid == TFM_CRYPTO_HASH_ABORT_SID)) {
154 /*
155 * finish()/abort() interface put handle in out_vec[0].
156 * Therefore, out_vec[0] shall be specially set to original handle
157 * value. Otherwise, the garbage data in message out_vec[0] may
158 * override the original handle value in client, after lookup fails.
159 */
160 p_handle = out_vec[0].base;
161 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
162 return PSA_ERROR_PROGRAMMER_ERROR;
163 }
164 *p_handle = iov->op_handle;
165 }
166 }
167 if (status != PSA_SUCCESS) {
168 if (sid == TFM_CRYPTO_HASH_ABORT_SID) {
169 /*
170 * Mbed TLS psa_hash_abort() will return a misleading error code
171 * if it is called with invalid operation content, since it
172 * doesn't validate the operation handle.
173 * It is neither necessary to call tfm_crypto_operation_release()
174 * with an invalid handle.
175 * Therefore return PSA_SUCCESS directly as psa_hash_abort() can
176 * be called multiple times.
177 */
178 return PSA_SUCCESS;
179 }
180 return status;
181 }
182
183 switch (sid) {
184 case TFM_CRYPTO_HASH_SETUP_SID:
185 {
186 status = psa_hash_setup(operation, iov->alg);
187 if (status != PSA_SUCCESS) {
188 goto release_operation_and_return;
189 }
190 }
191 break;
192 case TFM_CRYPTO_HASH_UPDATE_SID:
193 {
194 const uint8_t *input = in_vec[1].base;
195 size_t input_length = in_vec[1].len;
196
197 return psa_hash_update(operation, input, input_length);
198 }
199 case TFM_CRYPTO_HASH_FINISH_SID:
200 {
201 uint8_t *hash = out_vec[1].base;
202 size_t hash_size = out_vec[1].len;
203
204 status = psa_hash_finish(operation, hash, hash_size, &out_vec[1].len);
205 if (status == PSA_SUCCESS) {
206 goto release_operation_and_return;
207 } else {
208 out_vec[1].len = 0;
209 }
210 }
211 break;
212 case TFM_CRYPTO_HASH_VERIFY_SID:
213 {
214 const uint8_t *hash = in_vec[1].base;
215 size_t hash_length = in_vec[1].len;
216
217 status = psa_hash_verify(operation, hash, hash_length);
218 if (status == PSA_SUCCESS) {
219 goto release_operation_and_return;
220 }
221 }
222 break;
223 case TFM_CRYPTO_HASH_ABORT_SID:
224 {
225 status = psa_hash_abort(operation);
226 goto release_operation_and_return;
227 }
228 case TFM_CRYPTO_HASH_CLONE_SID:
229 {
230 psa_hash_operation_t *target_operation = NULL;
231 p_handle = out_vec[0].base;
232 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t)) ||
233 (in_vec[1].base == NULL) || (in_vec[1].len < sizeof(uint32_t))) {
234 return PSA_ERROR_PROGRAMMER_ERROR;
235 }
236 *p_handle = *((uint32_t *)in_vec[1].base);
237
238 /* Allocate the target operation context in the secure world */
239 status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
240 p_handle,
241 (void **)&target_operation);
242 if (status != PSA_SUCCESS) {
243 return status;
244 }
245 status = psa_hash_clone(operation, target_operation);
246 if (status != PSA_SUCCESS) {
247 (void)tfm_crypto_operation_release(p_handle);
248 }
249 }
250 break;
251 default:
252 return PSA_ERROR_NOT_SUPPORTED;
253 }
254
255 return status;
256
257 release_operation_and_return:
258 /* Release the operation context, ignore if the release fails. */
259 (void)tfm_crypto_operation_release(p_handle);
260 return status;
261 }
262 #else /* CRYPTO_HASH_MODULE_ENABLED */
tfm_crypto_hash_interface(psa_invec in_vec[],psa_outvec out_vec[])263 psa_status_t tfm_crypto_hash_interface(psa_invec in_vec[],
264 psa_outvec out_vec[])
265 {
266 (void)in_vec;
267 (void)out_vec;
268
269 return PSA_ERROR_NOT_SUPPORTED;
270 }
271 #endif /* CRYPTO_HASH_MODULE_ENABLED */
272 /*!@}*/
273