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
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
tfm_crypto_hash_interface(psa_invec in_vec[],psa_outvec out_vec[])24 psa_status_t tfm_crypto_hash_interface(psa_invec in_vec[],
25 psa_outvec out_vec[])
26 {
27 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
28 psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
29 psa_hash_operation_t *operation = NULL;
30 uint32_t *p_handle = NULL;
31 enum tfm_crypto_func_sid_t sid = iov->function_id;
32
33 if (sid == TFM_CRYPTO_HASH_COMPUTE_SID) {
34 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
35 return PSA_ERROR_NOT_SUPPORTED;
36 #else
37 const uint8_t *input = in_vec[1].base;
38 size_t input_length = in_vec[1].len;
39 uint8_t *hash = out_vec[0].base;
40 size_t hash_size = out_vec[0].len;
41
42 status = psa_hash_compute(iov->alg, input, input_length,
43 hash, hash_size, &out_vec[0].len);
44 if (status != PSA_SUCCESS) {
45 out_vec[0].len = 0;
46 }
47 return status;
48 #endif
49 }
50
51 if (sid == TFM_CRYPTO_HASH_COMPARE_SID) {
52 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
53 return PSA_ERROR_NOT_SUPPORTED;
54 #else
55 const uint8_t *input = in_vec[1].base;
56 size_t input_length = in_vec[1].len;
57 const uint8_t *hash = in_vec[2].base;
58 size_t hash_length = in_vec[2].len;
59
60 return psa_hash_compare(iov->alg, input, input_length,
61 hash, hash_length);
62 #endif
63 }
64
65 if (sid == TFM_CRYPTO_HASH_SETUP_SID) {
66 p_handle = out_vec[0].base;
67 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
68 return PSA_ERROR_PROGRAMMER_ERROR;
69 }
70 *p_handle = iov->op_handle;
71 status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
72 out_vec[0].base,
73 (void **)&operation);
74 } else {
75 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
76 iov->op_handle,
77 (void **)&operation);
78 if ((sid == TFM_CRYPTO_HASH_FINISH_SID) ||
79 (sid == TFM_CRYPTO_HASH_VERIFY_SID) ||
80 (sid == TFM_CRYPTO_HASH_ABORT_SID)) {
81 /*
82 * finish()/abort() interface put handle in out_vec[0].
83 * Therefore, out_vec[0] shall be specially set to original handle
84 * value. Otherwise, the garbage data in message out_vec[0] may
85 * override the original handle value in client, after lookup fails.
86 */
87 p_handle = out_vec[0].base;
88 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
89 return PSA_ERROR_PROGRAMMER_ERROR;
90 }
91 *p_handle = iov->op_handle;
92 }
93 }
94 if (status != PSA_SUCCESS) {
95 if (sid == TFM_CRYPTO_HASH_ABORT_SID) {
96 /*
97 * Mbed TLS psa_hash_abort() will return a misleading error code
98 * if it is called with invalid operation content, since it
99 * doesn't validate the operation handle.
100 * It is neither necessary to call tfm_crypto_operation_release()
101 * with an invalid handle.
102 * Therefore return PSA_SUCCESS directly as psa_hash_abort() can
103 * be called multiple times.
104 */
105 return PSA_SUCCESS;
106 }
107 return status;
108 }
109
110 switch (sid) {
111 case TFM_CRYPTO_HASH_SETUP_SID:
112 {
113 status = psa_hash_setup(operation, iov->alg);
114 if (status != PSA_SUCCESS) {
115 goto release_operation_and_return;
116 }
117 }
118 break;
119 case TFM_CRYPTO_HASH_UPDATE_SID:
120 {
121 const uint8_t *input = in_vec[1].base;
122 size_t input_length = in_vec[1].len;
123
124 return psa_hash_update(operation, input, input_length);
125 }
126 case TFM_CRYPTO_HASH_FINISH_SID:
127 {
128 uint8_t *hash = out_vec[1].base;
129 size_t hash_size = out_vec[1].len;
130
131 status = psa_hash_finish(operation, hash, hash_size, &out_vec[1].len);
132 if (status == PSA_SUCCESS) {
133 goto release_operation_and_return;
134 } else {
135 out_vec[1].len = 0;
136 }
137 }
138 break;
139 case TFM_CRYPTO_HASH_VERIFY_SID:
140 {
141 const uint8_t *hash = in_vec[1].base;
142 size_t hash_length = in_vec[1].len;
143
144 status = psa_hash_verify(operation, hash, hash_length);
145 if (status == PSA_SUCCESS) {
146 goto release_operation_and_return;
147 }
148 }
149 break;
150 case TFM_CRYPTO_HASH_ABORT_SID:
151 {
152 status = psa_hash_abort(operation);
153 goto release_operation_and_return;
154 }
155 case TFM_CRYPTO_HASH_CLONE_SID:
156 {
157 psa_hash_operation_t *target_operation = NULL;
158 p_handle = out_vec[0].base;
159 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t)) ||
160 (in_vec[1].base == NULL) || (in_vec[1].len < sizeof(uint32_t))) {
161 return PSA_ERROR_PROGRAMMER_ERROR;
162 }
163 *p_handle = *((uint32_t *)in_vec[1].base);
164
165 /* Allocate the target operation context in the secure world */
166 status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
167 p_handle,
168 (void **)&target_operation);
169 if (status != PSA_SUCCESS) {
170 return status;
171 }
172 status = psa_hash_clone(operation, target_operation);
173 if (status != PSA_SUCCESS) {
174 (void)tfm_crypto_operation_release(p_handle);
175 }
176 }
177 break;
178 default:
179 return PSA_ERROR_NOT_SUPPORTED;
180 }
181
182 return status;
183
184 release_operation_and_return:
185 /* Release the operation context, ignore if the release fails. */
186 (void)tfm_crypto_operation_release(p_handle);
187 return status;
188 }
189 #else /* CRYPTO_HASH_MODULE_ENABLED */
tfm_crypto_hash_interface(psa_invec in_vec[],psa_outvec out_vec[])190 psa_status_t tfm_crypto_hash_interface(psa_invec in_vec[],
191 psa_outvec out_vec[])
192 {
193 (void)in_vec;
194 (void)out_vec;
195
196 return PSA_ERROR_NOT_SUPPORTED;
197 }
198 #endif /* CRYPTO_HASH_MODULE_ENABLED */
199 /*!@}*/
200