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