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 = 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         *p_handle = iov->op_handle;
98         status = tfm_crypto_operation_alloc(TFM_CRYPTO_AEAD_OPERATION,
99                                             out_vec[0].base,
100                                             (void **)&operation);
101     } else {
102         status = tfm_crypto_operation_lookup(TFM_CRYPTO_AEAD_OPERATION,
103                                              iov->op_handle,
104                                              (void **)&operation);
105         if ((sid == TFM_CRYPTO_AEAD_FINISH_SID) ||
106             (sid == TFM_CRYPTO_AEAD_VERIFY_SID) ||
107             (sid == TFM_CRYPTO_AEAD_ABORT_SID)) {
108             /*
109              * finish()/abort() interface put handle pointer in out_vec[0].
110              * Therefore, out_vec[0] shall be specially set to original handle
111              * value. Otherwise, later psa_write() may override the original
112              * handle value in client with garbage data in message out_vec[0],
113              * if lookup fails.
114              */
115             p_handle = out_vec[0].base;
116             *p_handle = iov->op_handle;
117         }
118     }
119     if (status != PSA_SUCCESS) {
120         if (sid == TFM_CRYPTO_AEAD_ABORT_SID) {
121             /*
122              * Mbed TLS psa_aead_abort() will return a misleading error code
123              * if it is called with invalid operation content, since it
124              * doesn't validate the operation handle.
125              * It is neither necessary to call tfm_crypto_operation_release()
126              * with an invalid handle.
127              * Therefore return PSA_SUCCESS directly as psa_aead_abort() can be
128              * called multiple times.
129              */
130             return PSA_SUCCESS;
131         }
132         return status;
133     }
134 
135     switch (sid) {
136     case TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID:
137     {
138         status = psa_aead_encrypt_setup(operation, library_key, iov->alg);
139         if (status != PSA_SUCCESS) {
140             goto release_operation_and_return;
141         }
142     }
143     break;
144     case TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID:
145     {
146         status = psa_aead_decrypt_setup(operation, library_key, iov->alg);
147         if (status != PSA_SUCCESS) {
148             goto release_operation_and_return;
149         }
150     }
151     break;
152     case TFM_CRYPTO_AEAD_FINISH_SID:
153     {
154         uint8_t *ciphertext = out_vec[2].base;
155         size_t ciphertext_size = out_vec[2].len;
156         uint8_t *tag = out_vec[1].base;
157         size_t tag_size = out_vec[1].len;
158 
159         status = psa_aead_finish(operation,
160                                  ciphertext, ciphertext_size, &out_vec[2].len,
161                                  tag, tag_size, &out_vec[1].len);
162         if (status == PSA_SUCCESS) {
163             goto release_operation_and_return;
164         } else {
165             out_vec[1].len = 0;
166             out_vec[2].len = 0;
167         }
168     }
169     break;
170     case TFM_CRYPTO_AEAD_ABORT_SID:
171     {
172         status = psa_aead_abort(operation);
173         goto release_operation_and_return;
174     }
175     case TFM_CRYPTO_AEAD_GENERATE_NONCE_SID:
176     {
177         uint8_t *nonce = out_vec[0].base;
178         size_t nonce_size = out_vec[0].len;
179 
180         status = psa_aead_generate_nonce(operation,
181                                          nonce,
182                                          nonce_size,
183                                          &out_vec[0].len);
184         if (status != PSA_SUCCESS) {
185             out_vec[0].len = 0;
186         }
187         return status;
188     }
189     case TFM_CRYPTO_AEAD_SET_NONCE_SID:
190     {
191         const uint8_t *nonce = in_vec[1].base;
192         size_t nonce_size = in_vec[1].len;
193 
194         return psa_aead_set_nonce(operation, nonce, nonce_size);
195     }
196     case TFM_CRYPTO_AEAD_SET_LENGTHS_SID:
197     {
198         return psa_aead_set_lengths(operation, iov->ad_length,
199                                     iov->plaintext_length);
200     }
201     case TFM_CRYPTO_AEAD_UPDATE_SID:
202     {
203         const uint8_t *input = in_vec[1].base;
204         size_t input_length = in_vec[1].len;
205         uint8_t *output = out_vec[0].base;
206         size_t output_size = out_vec[0].len;
207 
208         status = psa_aead_update(operation, input, input_length,
209                                  output, output_size, &out_vec[0].len);
210         if (status != PSA_SUCCESS) {
211             out_vec[0].len = 0;
212         }
213         return status;
214     }
215     case TFM_CRYPTO_AEAD_UPDATE_AD_SID:
216     {
217         const uint8_t *input = in_vec[1].base;
218         size_t input_length = in_vec[1].len;
219 
220         return psa_aead_update_ad(operation, input, input_length);
221     }
222     case TFM_CRYPTO_AEAD_VERIFY_SID:
223     {
224         const uint8_t *tag = in_vec[1].base;
225         size_t tag_length = in_vec[1].len;
226         uint8_t *plaintext = out_vec[1].base;
227         size_t plaintext_size = out_vec[1].len;
228 
229         status = psa_aead_verify(operation,
230                                  plaintext, plaintext_size, &out_vec[1].len,
231                                  tag, tag_length);
232         if (status == PSA_SUCCESS) {
233             goto release_operation_and_return;
234         } else {
235             out_vec[1].len = 0;
236         }
237     }
238     break;
239     default:
240         return PSA_ERROR_NOT_SUPPORTED;
241     }
242 
243     return status;
244 
245 release_operation_and_return:
246     /* Release the operation context, ignore if the operation fails. */
247     (void)tfm_crypto_operation_release(p_handle);
248     return status;
249 }
250 #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)251 psa_status_t tfm_crypto_aead_interface(psa_invec in_vec[],
252                                        psa_outvec out_vec[],
253                                        struct tfm_crypto_key_id_s *encoded_key)
254 {
255     (void)in_vec;
256     (void)out_vec;
257     (void)encoded_key;
258 
259     return PSA_ERROR_NOT_SUPPORTED;
260 }
261 #endif /* CRYPTO_AEAD_MODULE_ENABLED */
262 /*!@}*/
263