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 uint16_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 *p_handle = iov->op_handle;
68 status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
69 out_vec[0].base,
70 (void **)&operation);
71 } else {
72 status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
73 iov->op_handle,
74 (void **)&operation);
75 if ((sid == TFM_CRYPTO_HASH_FINISH_SID) ||
76 (sid == TFM_CRYPTO_HASH_VERIFY_SID) ||
77 (sid == TFM_CRYPTO_HASH_ABORT_SID)) {
78 /*
79 * finish()/abort() interface put handle in out_vec[0].
80 * Therefore, out_vec[0] shall be specially set to original handle
81 * value. Otherwise, the garbage data in message out_vec[0] may
82 * override the original handle value in client, after lookup fails.
83 */
84 p_handle = out_vec[0].base;
85 *p_handle = iov->op_handle;
86 }
87 }
88 if (status != PSA_SUCCESS) {
89 if (sid == TFM_CRYPTO_HASH_ABORT_SID) {
90 /*
91 * Mbed TLS psa_hash_abort() will return a misleading error code
92 * if it is called with invalid operation content, since it
93 * doesn't validate the operation handle.
94 * It is neither necessary to call tfm_crypto_operation_release()
95 * with an invalid handle.
96 * Therefore return PSA_SUCCESS directly as psa_hash_abort() can
97 * be called multiple times.
98 */
99 return PSA_SUCCESS;
100 }
101 return status;
102 }
103
104 switch (sid) {
105 case TFM_CRYPTO_HASH_SETUP_SID:
106 {
107 status = psa_hash_setup(operation, iov->alg);
108 if (status != PSA_SUCCESS) {
109 goto release_operation_and_return;
110 }
111 }
112 break;
113 case TFM_CRYPTO_HASH_UPDATE_SID:
114 {
115 const uint8_t *input = in_vec[1].base;
116 size_t input_length = in_vec[1].len;
117
118 return psa_hash_update(operation, input, input_length);
119 }
120 case TFM_CRYPTO_HASH_FINISH_SID:
121 {
122 uint8_t *hash = out_vec[1].base;
123 size_t hash_size = out_vec[1].len;
124
125 status = psa_hash_finish(operation, hash, hash_size, &out_vec[1].len);
126 if (status == PSA_SUCCESS) {
127 goto release_operation_and_return;
128 } else {
129 out_vec[1].len = 0;
130 }
131 }
132 break;
133 case TFM_CRYPTO_HASH_VERIFY_SID:
134 {
135 const uint8_t *hash = in_vec[1].base;
136 size_t hash_length = in_vec[1].len;
137
138 status = psa_hash_verify(operation, hash, hash_length);
139 if (status == PSA_SUCCESS) {
140 goto release_operation_and_return;
141 }
142 }
143 break;
144 case TFM_CRYPTO_HASH_ABORT_SID:
145 {
146 status = psa_hash_abort(operation);
147 goto release_operation_and_return;
148 }
149 case TFM_CRYPTO_HASH_CLONE_SID:
150 {
151 psa_hash_operation_t *target_operation = NULL;
152 p_handle = out_vec[0].base;
153 *p_handle = *((uint32_t *)in_vec[1].base);
154
155 /* Allocate the target operation context in the secure world */
156 status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
157 p_handle,
158 (void **)&target_operation);
159 if (status != PSA_SUCCESS) {
160 return status;
161 }
162 status = psa_hash_clone(operation, target_operation);
163 if (status != PSA_SUCCESS) {
164 (void)tfm_crypto_operation_release(p_handle);
165 }
166 }
167 break;
168 default:
169 return PSA_ERROR_NOT_SUPPORTED;
170 }
171
172 return status;
173
174 release_operation_and_return:
175 /* Release the operation context, ignore if the release fails. */
176 (void)tfm_crypto_operation_release(p_handle);
177 return status;
178 }
179 #else /* CRYPTO_HASH_MODULE_ENABLED */
tfm_crypto_hash_interface(psa_invec in_vec[],psa_outvec out_vec[])180 psa_status_t tfm_crypto_hash_interface(psa_invec in_vec[],
181 psa_outvec out_vec[])
182 {
183 (void)in_vec;
184 (void)out_vec;
185
186 return PSA_ERROR_NOT_SUPPORTED;
187 }
188 #endif /* CRYPTO_HASH_MODULE_ENABLED */
189 /*!@}*/
190