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