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  * \addtogroup tfm_crypto_api_shim_layer
22  *
23  */
24 
25 /*!@{*/
26 #if CRYPTO_MAC_MODULE_ENABLED
tfm_crypto_mac_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)27 psa_status_t tfm_crypto_mac_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_mac_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_MAC_COMPUTE_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 *mac = out_vec[0].base;
46         size_t mac_size = out_vec[0].len;
47 
48         status = psa_mac_compute(library_key, iov->alg, input, input_length,
49                                  mac, mac_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_MAC_VERIFY_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         const uint8_t *mac = in_vec[2].base;
64         size_t mac_length = in_vec[2].len;
65 
66         return psa_mac_verify(library_key, iov->alg, input, input_length,
67                               mac, mac_length);
68 #endif
69     }
70 
71     if ((sid == TFM_CRYPTO_MAC_SIGN_SETUP_SID) ||
72         (sid == TFM_CRYPTO_MAC_VERIFY_SETUP_SID)) {
73         p_handle = out_vec[0].base;
74         if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
75             return PSA_ERROR_PROGRAMMER_ERROR;
76         }
77         *p_handle = iov->op_handle;
78         status = tfm_crypto_operation_alloc(TFM_CRYPTO_MAC_OPERATION,
79                                             out_vec[0].base,
80                                             (void **)&operation);
81     } else {
82         status = tfm_crypto_operation_lookup(TFM_CRYPTO_MAC_OPERATION,
83                                              iov->op_handle,
84                                              (void **)&operation);
85         if ((sid == TFM_CRYPTO_MAC_SIGN_FINISH_SID) ||
86             (sid == TFM_CRYPTO_MAC_VERIFY_FINISH_SID) ||
87             (sid == TFM_CRYPTO_MAC_ABORT_SID)) {
88             /*
89              * finish()/abort() interface put handle in out_vec[0].
90              * Therefore, out_vec[0] shall be specially set to original handle
91              * value. Otherwise, the garbage data in message out_vec[0] may
92              * override the original handle value in client, after lookup fails.
93              */
94             p_handle = out_vec[0].base;
95             if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(uint32_t))) {
96                 return PSA_ERROR_PROGRAMMER_ERROR;
97             }
98             *p_handle = iov->op_handle;
99         }
100     }
101     if (status != PSA_SUCCESS) {
102         if (sid == TFM_CRYPTO_MAC_ABORT_SID) {
103             /*
104              * Mbed TLS psa_mac_abort() will return a misleading error code
105              * if it is called with invalid operation content, since it
106              * doesn't validate the operation handle.
107              * It is neither necessary to call tfm_crypto_operation_release()
108              * with an invalid handle.
109              * Therefore return PSA_SUCCESS directly as psa_mac_abort() can be
110              * called multiple times.
111              */
112             return PSA_SUCCESS;
113         }
114         return status;
115     }
116 
117     switch (sid) {
118     case TFM_CRYPTO_MAC_SIGN_SETUP_SID:
119     {
120         status = psa_mac_sign_setup(operation, library_key, iov->alg);
121         if (status != PSA_SUCCESS) {
122             goto release_operation_and_return;
123         }
124     }
125     break;
126     case TFM_CRYPTO_MAC_VERIFY_SETUP_SID:
127     {
128         status = psa_mac_verify_setup(operation, library_key, iov->alg);
129         if (status != PSA_SUCCESS) {
130             goto release_operation_and_return;
131         }
132     }
133     break;
134     case TFM_CRYPTO_MAC_UPDATE_SID:
135     {
136         const uint8_t *input = in_vec[1].base;
137         size_t input_length = in_vec[1].len;
138 
139         return psa_mac_update(operation, input, input_length);
140     }
141     case TFM_CRYPTO_MAC_SIGN_FINISH_SID:
142     {
143         uint8_t *mac = out_vec[1].base;
144         size_t mac_size = out_vec[1].len;
145 
146         status = psa_mac_sign_finish(operation, mac, mac_size, &out_vec[1].len);
147         if (status == PSA_SUCCESS) {
148             /* In case of success automatically release the operation */
149             goto release_operation_and_return;
150         } else {
151             out_vec[1].len = 0;
152         }
153     }
154     break;
155     case TFM_CRYPTO_MAC_VERIFY_FINISH_SID:
156     {
157         const uint8_t *mac = in_vec[1].base;
158         size_t mac_length = in_vec[1].len;
159 
160         status = psa_mac_verify_finish(operation, mac, mac_length);
161         if (status == PSA_SUCCESS) {
162             goto release_operation_and_return;
163         }
164     }
165     break;
166     case TFM_CRYPTO_MAC_ABORT_SID:
167     {
168         status = psa_mac_abort(operation);
169         goto release_operation_and_return;
170     }
171     default:
172         return PSA_ERROR_NOT_SUPPORTED;
173     }
174 
175     return status;
176 
177 release_operation_and_return:
178     /* Release the operation context, ignore if the operation fails. */
179     (void)tfm_crypto_operation_release(p_handle);
180     return status;
181 }
182 #else /* CRYPTO_MAC_MODULE_ENABLED */
tfm_crypto_mac_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)183 psa_status_t tfm_crypto_mac_interface(psa_invec in_vec[],
184                                       psa_outvec out_vec[],
185                                       struct tfm_crypto_key_id_s *encoded_key)
186 {
187     (void)in_vec;
188     (void)out_vec;
189     (void)encoded_key;
190 
191     return PSA_ERROR_NOT_SUPPORTED;
192 }
193 #endif /* CRYPTO_MAC_MODULE_ENABLED */
194 /*!@}*/
195