1 /*
2  * Copyright (c) 2019-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_key.h"
16 #include "tfm_crypto_defs.h"
17 
18 #include "crypto_library.h"
19 
20 /*!
21  * \defgroup tfm_crypto_api_shim_layer Set of functions implementing a thin shim
22  *                                  layer between the TF-M Crypto service
23  *                                  frontend and the underlying library which
24  *                                  implements the PSA Crypto APIs
25  *                                  (i.e. mbed TLS)
26  */
27 
28 /*!@{*/
29 #if CRYPTO_AEAD_MODULE_ENABLED
tfm_crypto_aead_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)30 psa_status_t tfm_crypto_aead_interface(psa_invec in_vec[],
31                                        psa_outvec out_vec[],
32                                        struct tfm_crypto_key_id_s *encoded_key)
33 {
34     const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
35     psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
36     psa_aead_operation_t *operation = NULL;
37     uint32_t *p_handle = NULL;
38     enum tfm_crypto_func_sid_t sid = (enum tfm_crypto_func_sid_t)iov->function_id;
39 
40     tfm_crypto_library_key_id_t library_key = tfm_crypto_library_key_id_init(
41                                                   encoded_key->owner, encoded_key->key_id);
42     if (sid == TFM_CRYPTO_AEAD_ENCRYPT_SID) {
43 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
44         return PSA_ERROR_NOT_SUPPORTED;
45 #else
46         const struct tfm_crypto_aead_pack_input *aead_pack_input =
47                                                                  &iov->aead_in;
48         const uint8_t *nonce = aead_pack_input->nonce;
49         size_t nonce_length = aead_pack_input->nonce_length;
50         const uint8_t *plaintext = in_vec[1].base;
51         size_t plaintext_length = in_vec[1].len;
52         uint8_t *ciphertext = out_vec[0].base;
53         size_t ciphertext_size = out_vec[0].len;
54         const uint8_t *additional_data = in_vec[2].base;
55         size_t additional_data_length = in_vec[2].len;
56 
57         status = psa_aead_encrypt(library_key, iov->alg, nonce, nonce_length,
58                                   additional_data, additional_data_length,
59                                   plaintext, plaintext_length,
60                                   ciphertext, ciphertext_size, &out_vec[0].len);
61         if (status != PSA_SUCCESS) {
62             out_vec[0].len = 0;
63         }
64         return status;
65 #endif
66     }
67 
68     if (sid == TFM_CRYPTO_AEAD_DECRYPT_SID) {
69 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
70         return PSA_ERROR_NOT_SUPPORTED;
71 #else
72         const struct tfm_crypto_aead_pack_input *aead_pack_input =
73                                                                  &iov->aead_in;
74         const uint8_t *nonce = aead_pack_input->nonce;
75         size_t nonce_length = aead_pack_input->nonce_length;
76         const uint8_t *ciphertext = in_vec[1].base;
77         size_t ciphertext_length = in_vec[1].len;
78         uint8_t *plaintext = out_vec[0].base;
79         size_t plaintext_size = out_vec[0].len;
80         const uint8_t *additional_data = in_vec[2].base;
81         size_t additional_data_length = in_vec[2].len;
82 
83         status = psa_aead_decrypt(library_key, iov->alg, nonce, nonce_length,
84                                   additional_data, additional_data_length,
85                                   ciphertext, ciphertext_length,
86                                   plaintext, plaintext_size, &out_vec[0].len);
87         if (status != PSA_SUCCESS) {
88             out_vec[0].len = 0;
89         }
90         return status;
91 #endif
92     }
93 
94     if ((sid == TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID) ||
95         (sid == TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID)) {
96         p_handle = out_vec[0].base;
97         if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
98             return PSA_ERROR_PROGRAMMER_ERROR;
99         }
100         *p_handle = iov->op_handle;
101         status = tfm_crypto_operation_alloc(TFM_CRYPTO_AEAD_OPERATION,
102                                             out_vec[0].base,
103                                             (void **)&operation);
104     } else {
105         status = tfm_crypto_operation_lookup(TFM_CRYPTO_AEAD_OPERATION,
106                                              iov->op_handle,
107                                              (void **)&operation);
108         if ((sid == TFM_CRYPTO_AEAD_FINISH_SID) ||
109             (sid == TFM_CRYPTO_AEAD_VERIFY_SID) ||
110             (sid == TFM_CRYPTO_AEAD_ABORT_SID)) {
111             /*
112              * finish()/abort() interface put handle pointer in out_vec[0].
113              * Therefore, out_vec[0] shall be specially set to original handle
114              * value. Otherwise, later psa_write() may override the original
115              * handle value in client with garbage data in message out_vec[0],
116              * if lookup fails.
117              */
118             p_handle = out_vec[0].base;
119             if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
120                 return PSA_ERROR_PROGRAMMER_ERROR;
121             }
122             *p_handle = iov->op_handle;
123         }
124     }
125     if (status != PSA_SUCCESS) {
126         if (sid == TFM_CRYPTO_AEAD_ABORT_SID) {
127             /*
128              * Mbed TLS psa_aead_abort() will return a misleading error code
129              * if it is called with invalid operation content, since it
130              * doesn't validate the operation handle.
131              * It is neither necessary to call tfm_crypto_operation_release()
132              * with an invalid handle.
133              * Therefore return PSA_SUCCESS directly as psa_aead_abort() can be
134              * called multiple times.
135              */
136             return PSA_SUCCESS;
137         }
138         return status;
139     }
140 
141     switch (sid) {
142     case TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID:
143     {
144         status = psa_aead_encrypt_setup(operation, library_key, iov->alg);
145         if (status != PSA_SUCCESS) {
146             goto release_operation_and_return;
147         }
148     }
149     break;
150     case TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID:
151     {
152         status = psa_aead_decrypt_setup(operation, library_key, iov->alg);
153         if (status != PSA_SUCCESS) {
154             goto release_operation_and_return;
155         }
156     }
157     break;
158     case TFM_CRYPTO_AEAD_FINISH_SID:
159     {
160         uint8_t *ciphertext = out_vec[2].base;
161         size_t ciphertext_size = out_vec[2].len;
162         uint8_t *tag = out_vec[1].base;
163         size_t tag_size = out_vec[1].len;
164 
165         status = psa_aead_finish(operation,
166                                  ciphertext, ciphertext_size, &out_vec[2].len,
167                                  tag, tag_size, &out_vec[1].len);
168         if (status == PSA_SUCCESS) {
169             goto release_operation_and_return;
170         } else {
171             out_vec[1].len = 0;
172             out_vec[2].len = 0;
173         }
174     }
175     break;
176     case TFM_CRYPTO_AEAD_ABORT_SID:
177     {
178         status = psa_aead_abort(operation);
179         goto release_operation_and_return;
180     }
181     case TFM_CRYPTO_AEAD_GENERATE_NONCE_SID:
182     {
183         uint8_t *nonce = out_vec[0].base;
184         size_t nonce_size = out_vec[0].len;
185 
186         status = psa_aead_generate_nonce(operation,
187                                          nonce,
188                                          nonce_size,
189                                          &out_vec[0].len);
190         if (status != PSA_SUCCESS) {
191             out_vec[0].len = 0;
192         }
193         return status;
194     }
195     case TFM_CRYPTO_AEAD_SET_NONCE_SID:
196     {
197         const uint8_t *nonce = in_vec[1].base;
198         size_t nonce_size = in_vec[1].len;
199 
200         return psa_aead_set_nonce(operation, nonce, nonce_size);
201     }
202     case TFM_CRYPTO_AEAD_SET_LENGTHS_SID:
203     {
204         return psa_aead_set_lengths(operation, iov->ad_length,
205                                     iov->plaintext_length);
206     }
207     case TFM_CRYPTO_AEAD_UPDATE_SID:
208     {
209         const uint8_t *input = in_vec[1].base;
210         size_t input_length = in_vec[1].len;
211         uint8_t *output = out_vec[0].base;
212         size_t output_size = out_vec[0].len;
213 
214         status = psa_aead_update(operation, input, input_length,
215                                  output, output_size, &out_vec[0].len);
216         if (status != PSA_SUCCESS) {
217             out_vec[0].len = 0;
218         }
219         return status;
220     }
221     case TFM_CRYPTO_AEAD_UPDATE_AD_SID:
222     {
223         const uint8_t *input = in_vec[1].base;
224         size_t input_length = in_vec[1].len;
225 
226         return psa_aead_update_ad(operation, input, input_length);
227     }
228     case TFM_CRYPTO_AEAD_VERIFY_SID:
229     {
230         const uint8_t *tag = in_vec[1].base;
231         size_t tag_length = in_vec[1].len;
232         uint8_t *plaintext = out_vec[1].base;
233         size_t plaintext_size = out_vec[1].len;
234 
235         status = psa_aead_verify(operation,
236                                  plaintext, plaintext_size, &out_vec[1].len,
237                                  tag, tag_length);
238         if (status == PSA_SUCCESS) {
239             goto release_operation_and_return;
240         } else {
241             out_vec[1].len = 0;
242         }
243     }
244     break;
245     default:
246         return PSA_ERROR_NOT_SUPPORTED;
247     }
248 
249     return status;
250 
251 release_operation_and_return:
252     /* Release the operation context, ignore if the operation fails. */
253     (void)tfm_crypto_operation_release(p_handle);
254     return status;
255 }
256 #else /* CRYPTO_AEAD_MODULE_ENABLED */
tfm_crypto_aead_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)257 psa_status_t tfm_crypto_aead_interface(psa_invec in_vec[],
258                                        psa_outvec out_vec[],
259                                        struct tfm_crypto_key_id_s *encoded_key)
260 {
261     (void)in_vec;
262     (void)out_vec;
263     (void)encoded_key;
264 
265     return PSA_ERROR_NOT_SUPPORTED;
266 }
267 #endif /* CRYPTO_AEAD_MODULE_ENABLED */
268 /*!@}*/
269