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