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 #include <string.h>
11 #include "config_tfm.h"
12 #include "tfm_sp_log.h"
13 
14 #include "tfm_mbedcrypto_include.h"
15 
16 #include "tfm_crypto_api.h"
17 #include "tfm_crypto_key.h"
18 #include "tfm_crypto_defs.h"
19 
20 #include "crypto_library.h"
21 
22 /*!
23  * \addtogroup tfm_crypto_api_shim_layer
24  *
25  */
26 
27 /*!@{*/
28 #if CRYPTO_KEY_DERIVATION_MODULE_ENABLED
tfm_crypto_key_derivation_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)29 psa_status_t tfm_crypto_key_derivation_interface(psa_invec in_vec[],
30                                                  psa_outvec out_vec[],
31                                                  struct tfm_crypto_key_id_s *encoded_key)
32 {
33     const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
34     psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
35     psa_key_derivation_operation_t *operation = NULL;
36     uint32_t *p_handle = NULL;
37     uint16_t sid = iov->function_id;
38 
39     tfm_crypto_library_key_id_t library_key = tfm_crypto_library_key_id_init(
40                                                   encoded_key->owner, encoded_key->key_id);
41     if (sid == TFM_CRYPTO_RAW_KEY_AGREEMENT_SID) {
42         uint8_t *output = out_vec[0].base;
43         size_t output_size = out_vec[0].len;
44         const uint8_t *peer_key = in_vec[1].base;
45         size_t peer_key_length = in_vec[1].len;
46 
47         return psa_raw_key_agreement(iov->alg, library_key,
48                                      peer_key, peer_key_length,
49                                      output, output_size, &out_vec[0].len);
50     }
51 
52     if (sid == TFM_CRYPTO_KEY_DERIVATION_SETUP_SID) {
53         p_handle = out_vec[0].base;
54         *p_handle = iov->op_handle;
55         status = tfm_crypto_operation_alloc(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
56                                             out_vec[0].base,
57                                             (void **)&operation);
58     } else {
59         status = tfm_crypto_operation_lookup(
60                                             TFM_CRYPTO_KEY_DERIVATION_OPERATION,
61                                             iov->op_handle,
62                                             (void **)&operation);
63     }
64     if ((status != PSA_SUCCESS) &&
65         (sid != TFM_CRYPTO_KEY_DERIVATION_ABORT_SID)) {
66         return status;
67     }
68 
69     switch (sid) {
70     case TFM_CRYPTO_KEY_DERIVATION_SETUP_SID:
71     {
72         status = psa_key_derivation_setup(operation, iov->alg);
73 
74         if (status != PSA_SUCCESS) {
75             goto release_operation_and_return;
76         }
77     }
78     break;
79     case TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID:
80     {
81         size_t *capacity = out_vec[0].base;
82 
83         return psa_key_derivation_get_capacity(operation, capacity);
84     }
85     case TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID:
86     {
87         return psa_key_derivation_set_capacity(operation, iov->capacity);
88     }
89     case TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID:
90     {
91         const uint8_t *data = in_vec[1].base;
92         size_t data_length = in_vec[1].len;
93 
94         return psa_key_derivation_input_bytes(operation, iov->step, data,
95                                               data_length);
96     }
97     case TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID:
98     {
99         uint8_t *output = out_vec[0].base;
100         size_t output_length = out_vec[0].len;
101 
102         return psa_key_derivation_output_bytes(operation,
103                                                output, output_length);
104     }
105     case TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID:
106     {
107          return psa_key_derivation_input_key(operation,
108                                              iov->step, library_key);
109     }
110     case TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID:
111     {
112         const struct psa_client_key_attributes_s *client_key_attr =
113                                                             in_vec[1].base;
114         psa_key_id_t *key_handle = out_vec[0].base;
115         psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
116         int32_t partition_id = encoded_key->owner;
117 
118         status = tfm_crypto_core_library_key_attributes_from_client(
119                                                        client_key_attr,
120                                                        partition_id,
121                                                        &key_attributes);
122         if (status != PSA_SUCCESS) {
123             return status;
124         }
125 
126         status = psa_key_derivation_output_key(&key_attributes, operation,
127                                                &library_key);
128 
129         *key_handle = CRYPTO_LIBRARY_GET_KEY_ID(library_key);
130     }
131     break;
132     case TFM_CRYPTO_KEY_DERIVATION_ABORT_SID:
133     {
134         p_handle = out_vec[0].base;
135         *p_handle = iov->op_handle;
136         if (status != PSA_SUCCESS) {
137             /*
138              * If lookup() failed to find out a valid operation, it is not
139              * an error for _abort(), as it is allowed to be called multiple
140              * times, and it is likely the operation has just already been
141              * aborted.
142              */
143             return PSA_SUCCESS;
144         }
145 
146         status = psa_key_derivation_abort(operation);
147 
148         goto release_operation_and_return;
149     }
150     case TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID:
151     {
152         const uint8_t *peer_key = in_vec[1].base;
153         size_t peer_key_length = in_vec[1].len;
154 
155         return psa_key_derivation_key_agreement(operation, iov->step,
156                                                 library_key,
157                                                 peer_key,
158                                                 peer_key_length);
159     }
160     break;
161     default:
162         return PSA_ERROR_NOT_SUPPORTED;
163     }
164 
165     return status;
166 
167 release_operation_and_return:
168     /* Release the operation context, ignore if the operation fails. */
169     (void)tfm_crypto_operation_release(p_handle);
170     return status;
171 }
172 #else /* CRYPTO_KEY_DERIVATION_MODULE_ENABLED */
tfm_crypto_key_derivation_interface(psa_invec in_vec[],psa_outvec out_vec[],struct tfm_crypto_key_id_s * encoded_key)173 psa_status_t tfm_crypto_key_derivation_interface(psa_invec in_vec[],
174                                                  psa_outvec out_vec[],
175                                                  struct tfm_crypto_key_id_s *encoded_key)
176 {
177     (void)in_vec;
178     (void)out_vec;
179     (void)encoded_key;
180 
181     return PSA_ERROR_NOT_SUPPORTED;
182 }
183 #endif /* CRYPTO_KEY_DERIVATION_MODULE_ENABLED */
184 /*!@}*/
185