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_key.h"
16 #include "tfm_crypto_defs.h"
17
18 #include "crypto_library.h"
19
20 /*!
21 * \addtogroup tfm_crypto_api_shim_layer
22 *
23 */
24
25 /*!@{*/
26 #if CRYPTO_CIPHER_MODULE_ENABLED
27 /**
28 * \brief Check whether PSA is capable of handling the specified cipher algorithm and the given key
29 * type.
30 *
31 * \note As service initialization is performed during TF-M boot up, so there is no need
32 * to check whether psa_crypto_init has already been called.
33 *
34 * \param[in] key_type The key type.
35 * \param[in] alg The cipher algorithm.
36 *
37 * \return 1 if the PSA can handle \p alg and the given \p key_type, 0 otherwise.
38 */
tfm_crypto_can_do_cipher(psa_key_type_t key_type,psa_algorithm_t alg)39 int tfm_crypto_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t alg)
40 {
41 /* Check whether desired key type is available. */
42 switch (key_type) {
43 #if defined(PSA_WANT_KEY_TYPE_AES)
44 case PSA_KEY_TYPE_AES:
45 break;
46 #endif
47 #if defined(PSA_WANT_KEY_TYPE_ARIA)
48 case PSA_KEY_TYPE_ARIA:
49 break;
50 #endif
51 #if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
52 case PSA_KEY_TYPE_CAMELLIA:
53 break;
54 #endif
55 #if defined(PSA_WANT_KEY_TYPE_DES)
56 case PSA_KEY_TYPE_DES:
57 break;
58 #endif
59 #if defined(PSA_WANT_KEY_TYPE_CHACHA20)
60 case PSA_KEY_TYPE_CHACHA20:
61 break;
62 #endif
63 default:
64 return 0;
65 }
66
67 /* Check whether desired algorithm is available. */
68 if (PSA_ALG_IS_AEAD(alg)) {
69 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
70 }
71
72 switch (alg) {
73 #if defined(PSA_WANT_ALG_CTR)
74 case PSA_ALG_CTR:
75 break;
76 #endif
77 #if defined(PSA_WANT_ALG_CFB)
78 case PSA_ALG_CFB:
79 break;
80 #endif
81 #if defined(PSA_WANT_ALG_OFB)
82 case PSA_ALG_OFB:
83 break;
84 #endif
85 #if defined(PSA_WANT_ALG_XTS)
86 case PSA_ALG_XTS:
87 break;
88 #endif
89 #if defined(PSA_WANT_ALG_ECB_NO_PADDING)
90 case PSA_ALG_ECB_NO_PADDING:
91 break;
92 #endif
93 #if defined(PSA_WANT_ALG_CBC_NO_PADDING)
94 case PSA_ALG_CBC_NO_PADDING:
95 break;
96 #endif
97 #if defined(PSA_WANT_ALG_CBC_PKCS7)
98 case PSA_ALG_CBC_PKCS7:
99 break;
100 #endif
101 #if defined(PSA_WANT_ALG_CMAC)
102 case PSA_ALG_CMAC:
103 break;
104 #endif
105 #if defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)
106 case PSA_ALG_CCM_STAR_NO_TAG:
107 break;
108 #endif
109 #if defined(PSA_WANT_ALG_CCM)
110 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
111 break;
112 #endif
113 #if defined(PSA_WANT_ALG_GCM)
114 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
115 break;
116 #endif
117 #if defined(PSA_WANT_ALG_STREAM_CIPHER)
118 case PSA_ALG_STREAM_CIPHER:
119 break;
120 #endif
121 #if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
122 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
123 break;
124 #endif
125 default:
126 return 0;
127 }
128
129 return 1;
130 }
131
tfm_crypto_cipher_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)132 psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
133 psa_outvec out_vec[],
134 struct tfm_crypto_key_id_s *encoded_key)
135 {
136 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
137 psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
138 psa_cipher_operation_t *operation = NULL;
139 uint32_t *p_handle = NULL;
140 enum tfm_crypto_func_sid_t sid = (enum tfm_crypto_func_sid_t)iov->function_id;
141
142 if (sid == TFM_CRYPTO_CAN_DO_CIPHER_SID) {
143 int *p_result = out_vec[0].base;
144 psa_key_type_t *p_key_type = in_vec[1].base;
145
146 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(int)) ||
147 (in_vec[1].base == NULL) || (in_vec[1].len < sizeof(psa_key_type_t))) {
148 return PSA_ERROR_PROGRAMMER_ERROR;
149 }
150
151 *p_result = tfm_crypto_can_do_cipher(*p_key_type, iov->alg);
152 return PSA_SUCCESS;
153 }
154
155 tfm_crypto_library_key_id_t library_key = tfm_crypto_library_key_id_init(
156 encoded_key->owner, encoded_key->key_id);
157 if (sid == TFM_CRYPTO_CIPHER_ENCRYPT_SID) {
158 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
159 return PSA_ERROR_NOT_SUPPORTED;
160 #else
161 const uint8_t *input = in_vec[1].base;
162 size_t input_length = in_vec[1].len;
163 uint8_t *output = out_vec[0].base;
164 size_t output_size = out_vec[0].len;
165
166 status = psa_cipher_encrypt(library_key, iov->alg, input, input_length,
167 output, output_size, &out_vec[0].len);
168 if (status != PSA_SUCCESS) {
169 out_vec[0].len = 0;
170 }
171 return status;
172 #endif
173 }
174
175 if (sid == TFM_CRYPTO_CIPHER_DECRYPT_SID) {
176 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
177 return PSA_ERROR_NOT_SUPPORTED;
178 #else
179 const uint8_t *input = in_vec[1].base;
180 size_t input_length = in_vec[1].len;
181 uint8_t *output = out_vec[0].base;
182 size_t output_size = out_vec[0].len;
183
184 status = psa_cipher_decrypt(library_key, iov->alg, input, input_length,
185 output, output_size, &out_vec[0].len);
186 if (status != PSA_SUCCESS) {
187 out_vec[0].len = 0;
188 }
189 return status;
190 #endif
191 }
192
193 if ((sid == TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID) ||
194 (sid == TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID)) {
195 p_handle = out_vec[0].base;
196 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
197 return PSA_ERROR_PROGRAMMER_ERROR;
198 }
199 *p_handle = iov->op_handle;
200 status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
201 out_vec[0].base,
202 (void **)&operation);
203 } else {
204 status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
205 iov->op_handle,
206 (void **)&operation);
207 if ((sid == TFM_CRYPTO_CIPHER_FINISH_SID) ||
208 (sid == TFM_CRYPTO_CIPHER_ABORT_SID)) {
209 /*
210 * finish()/abort() interface put handle in out_vec[0].
211 * Therefore, out_vec[0] shall be specially set to original handle
212 * value. Otherwise, the garbage data in message out_vec[0] may
213 * override the original handle value in client, after lookup fails.
214 */
215 p_handle = out_vec[0].base;
216 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
217 return PSA_ERROR_PROGRAMMER_ERROR;
218 }
219 *p_handle = iov->op_handle;
220 }
221 }
222 if (status != PSA_SUCCESS) {
223 if (sid == TFM_CRYPTO_CIPHER_ABORT_SID) {
224 /*
225 * Mbed TLS psa_cipher_abort() will return a misleading error code
226 * if it is called with invalid operation content, since it
227 * doesn't validate the operation handle.
228 * It is neither necessary to call tfm_crypto_operation_release()
229 * with an invalid handle.
230 * Therefore return PSA_SUCCESS directly as psa_cipher_abort() can
231 * be called multiple times.
232 */
233 return PSA_SUCCESS;
234 }
235 return status;
236 }
237
238 switch (sid) {
239 case TFM_CRYPTO_CIPHER_GENERATE_IV_SID:
240 {
241 unsigned char *iv = out_vec[0].base;
242 size_t iv_size = out_vec[0].len;
243
244 status = psa_cipher_generate_iv(operation, iv, iv_size, &out_vec[0].len);
245 if (status != PSA_SUCCESS) {
246 out_vec[0].len = 0;
247 }
248 return status;
249 }
250 case TFM_CRYPTO_CIPHER_SET_IV_SID:
251 {
252 const unsigned char *iv = in_vec[1].base;
253 size_t iv_length = in_vec[1].len;
254
255 return psa_cipher_set_iv(operation, iv, iv_length);
256 }
257 case TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID:
258 {
259 status = psa_cipher_encrypt_setup(operation, library_key, iov->alg);
260 if (status != PSA_SUCCESS) {
261 goto release_operation_and_return;
262 }
263 }
264 break;
265 case TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID:
266 {
267 status = psa_cipher_decrypt_setup(operation, library_key, iov->alg);
268 if (status != PSA_SUCCESS) {
269 goto release_operation_and_return;
270 }
271 }
272 break;
273 case TFM_CRYPTO_CIPHER_UPDATE_SID:
274 {
275 const uint8_t *input = in_vec[1].base;
276 size_t input_length = in_vec[1].len;
277 unsigned char *output = out_vec[0].base;
278 size_t output_size = out_vec[0].len;
279
280 status = psa_cipher_update(operation, input, input_length,
281 output, output_size, &out_vec[0].len);
282 if (status != PSA_SUCCESS) {
283 out_vec[0].len = 0;
284 }
285 return status;
286 }
287 case TFM_CRYPTO_CIPHER_FINISH_SID:
288 {
289 uint8_t *output = out_vec[1].base;
290 size_t output_size = out_vec[1].len;
291
292 status = psa_cipher_finish(operation,
293 output, output_size, &out_vec[1].len);
294 if (status == PSA_SUCCESS) {
295 /* In case of success automatically release the operation */
296 goto release_operation_and_return;
297 } else {
298 out_vec[1].len = 0;
299 }
300 }
301 break;
302 case TFM_CRYPTO_CIPHER_ABORT_SID:
303 {
304 status = psa_cipher_abort(operation);
305 goto release_operation_and_return;
306 }
307 default:
308 return PSA_ERROR_NOT_SUPPORTED;
309 }
310
311 return status;
312
313 release_operation_and_return:
314 /* Release the operation context, ignore if the operation fails. */
315 (void)tfm_crypto_operation_release(p_handle);
316 return status;
317 }
318 #else /* CRYPTO_CIPHER_MODULE_ENABLED */
tfm_crypto_cipher_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)319 psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
320 psa_outvec out_vec[],
321 struct tfm_crypto_key_id_s *encoded_key)
322 {
323 (void)in_vec;
324 (void)out_vec;
325 (void)encoded_key;
326
327 return PSA_ERROR_NOT_SUPPORTED;
328 }
329 #endif /* CRYPTO_CIPHER_MODULE_ENABLED */
330 /*!@}*/
331