1 /*
2  * Copyright (c) 2018-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  * \addtogroup tfm_crypto_api_shim_layer
22  *
23  */
24 
25 /*!@{*/
26 #if CRYPTO_CIPHER_MODULE_ENABLED
tfm_crypto_cipher_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)27 psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
28                                          psa_outvec out_vec[],
29                                          struct tfm_crypto_key_id_s *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_cipher_operation_t *operation = NULL;
34     uint32_t *p_handle = NULL;
35     enum tfm_crypto_func_sid_t sid = iov->function_id;
36 
37     tfm_crypto_library_key_id_t library_key = tfm_crypto_library_key_id_init(
38                                                   encoded_key->owner, encoded_key->key_id);
39     if (sid == TFM_CRYPTO_CIPHER_ENCRYPT_SID) {
40 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
41         return PSA_ERROR_NOT_SUPPORTED;
42 #else
43         const uint8_t *input = in_vec[1].base;
44         size_t input_length = in_vec[1].len;
45         uint8_t *output = out_vec[0].base;
46         size_t output_size = out_vec[0].len;
47 
48         status = psa_cipher_encrypt(library_key, iov->alg, input, input_length,
49                                     output, output_size, &out_vec[0].len);
50         if (status != PSA_SUCCESS) {
51             out_vec[0].len = 0;
52         }
53         return status;
54 #endif
55     }
56 
57     if (sid == TFM_CRYPTO_CIPHER_DECRYPT_SID) {
58 #if CRYPTO_SINGLE_PART_FUNCS_DISABLED
59         return PSA_ERROR_NOT_SUPPORTED;
60 #else
61         const uint8_t *input = in_vec[1].base;
62         size_t input_length = in_vec[1].len;
63         uint8_t *output = out_vec[0].base;
64         size_t output_size = out_vec[0].len;
65 
66         status = psa_cipher_decrypt(library_key, iov->alg, input, input_length,
67                                     output, output_size, &out_vec[0].len);
68         if (status != PSA_SUCCESS) {
69             out_vec[0].len = 0;
70         }
71         return status;
72 #endif
73     }
74 
75     if ((sid == TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID) ||
76         (sid == TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID)) {
77         p_handle = out_vec[0].base;
78         if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
79             return PSA_ERROR_PROGRAMMER_ERROR;
80         }
81         *p_handle = iov->op_handle;
82         status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
83                                             out_vec[0].base,
84                                             (void **)&operation);
85     } else {
86         status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
87                                              iov->op_handle,
88                                              (void **)&operation);
89         if ((sid == TFM_CRYPTO_CIPHER_FINISH_SID) ||
90             (sid == TFM_CRYPTO_CIPHER_ABORT_SID)) {
91             /*
92              * finish()/abort() interface put handle in out_vec[0].
93              * Therefore, out_vec[0] shall be specially set to original handle
94              * value. Otherwise, the garbage data in message out_vec[0] may
95              * override the original handle value in client, after lookup fails.
96              */
97             p_handle = out_vec[0].base;
98             if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
99                 return PSA_ERROR_PROGRAMMER_ERROR;
100             }
101             *p_handle = iov->op_handle;
102         }
103     }
104     if (status != PSA_SUCCESS) {
105         if (sid == TFM_CRYPTO_CIPHER_ABORT_SID) {
106             /*
107              * Mbed TLS psa_cipher_abort() will return a misleading error code
108              * if it is called with invalid operation content, since it
109              * doesn't validate the operation handle.
110              * It is neither necessary to call tfm_crypto_operation_release()
111              * with an invalid handle.
112              * Therefore return PSA_SUCCESS directly as psa_cipher_abort() can
113              * be called multiple times.
114              */
115             return PSA_SUCCESS;
116         }
117         return status;
118     }
119 
120     switch (sid) {
121     case TFM_CRYPTO_CIPHER_GENERATE_IV_SID:
122     {
123         unsigned char *iv = out_vec[0].base;
124         size_t iv_size = out_vec[0].len;
125 
126         status = psa_cipher_generate_iv(operation, iv, iv_size, &out_vec[0].len);
127         if (status != PSA_SUCCESS) {
128             out_vec[0].len = 0;
129         }
130         return status;
131     }
132     case TFM_CRYPTO_CIPHER_SET_IV_SID:
133     {
134         const unsigned char *iv = in_vec[1].base;
135         size_t iv_length = in_vec[1].len;
136 
137         return psa_cipher_set_iv(operation, iv, iv_length);
138     }
139     case TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID:
140     {
141         status = psa_cipher_encrypt_setup(operation, library_key, iov->alg);
142         if (status != PSA_SUCCESS) {
143             goto release_operation_and_return;
144         }
145     }
146     break;
147     case TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID:
148     {
149         status = psa_cipher_decrypt_setup(operation, library_key, iov->alg);
150         if (status != PSA_SUCCESS) {
151             goto release_operation_and_return;
152         }
153     }
154     break;
155     case TFM_CRYPTO_CIPHER_UPDATE_SID:
156     {
157         const uint8_t *input = in_vec[1].base;
158         size_t input_length = in_vec[1].len;
159         unsigned char *output = out_vec[0].base;
160         size_t output_size = out_vec[0].len;
161 
162         status = psa_cipher_update(operation, input, input_length,
163                                    output, output_size, &out_vec[0].len);
164         if (status != PSA_SUCCESS) {
165             out_vec[0].len = 0;
166         }
167         return status;
168     }
169     case TFM_CRYPTO_CIPHER_FINISH_SID:
170     {
171         uint8_t *output = out_vec[1].base;
172         size_t output_size = out_vec[1].len;
173 
174         status = psa_cipher_finish(operation,
175                                    output, output_size, &out_vec[1].len);
176         if (status == PSA_SUCCESS) {
177             /* In case of success automatically release the operation */
178             goto release_operation_and_return;
179         } else {
180             out_vec[1].len = 0;
181         }
182     }
183     break;
184     case TFM_CRYPTO_CIPHER_ABORT_SID:
185     {
186         status = psa_cipher_abort(operation);
187         goto release_operation_and_return;
188     }
189     default:
190         return PSA_ERROR_NOT_SUPPORTED;
191     }
192 
193     return status;
194 
195 release_operation_and_return:
196     /* Release the operation context, ignore if the operation fails. */
197     (void)tfm_crypto_operation_release(p_handle);
198     return status;
199 }
200 #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)201 psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
202                                          psa_outvec out_vec[],
203                                          struct tfm_crypto_key_id_s *encoded_key)
204 {
205     (void)in_vec;
206     (void)out_vec;
207     (void)encoded_key;
208 
209     return PSA_ERROR_NOT_SUPPORTED;
210 }
211 #endif /* CRYPTO_CIPHER_MODULE_ENABLED */
212 /*!@}*/
213