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 enum tfm_crypto_func_sid_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
55 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(*p_handle))) {
56 return PSA_ERROR_PROGRAMMER_ERROR;
57 }
58
59 *p_handle = iov->op_handle;
60 status = tfm_crypto_operation_alloc(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
61 out_vec[0].base,
62 (void **)&operation);
63 } else {
64 status = tfm_crypto_operation_lookup(
65 TFM_CRYPTO_KEY_DERIVATION_OPERATION,
66 iov->op_handle,
67 (void **)&operation);
68 }
69 if ((status != PSA_SUCCESS) &&
70 (sid != TFM_CRYPTO_KEY_DERIVATION_ABORT_SID)) {
71 return status;
72 }
73
74 switch (sid) {
75 case TFM_CRYPTO_KEY_DERIVATION_SETUP_SID:
76 {
77 status = psa_key_derivation_setup(operation, iov->alg);
78
79 if (status != PSA_SUCCESS) {
80 goto release_operation_and_return;
81 }
82 }
83 break;
84 case TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID:
85 {
86 size_t *capacity = out_vec[0].base;
87
88 if ((out_vec[0].base == NULL) || (out_vec[0].len != sizeof(*capacity))) {
89 return PSA_ERROR_PROGRAMMER_ERROR;
90 }
91
92 return psa_key_derivation_get_capacity(operation, capacity);
93 }
94 case TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID:
95 {
96 return psa_key_derivation_set_capacity(operation, iov->capacity);
97 }
98 case TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID:
99 {
100 const uint8_t *data = in_vec[1].base;
101 size_t data_length = in_vec[1].len;
102
103 return psa_key_derivation_input_bytes(operation, iov->step, data,
104 data_length);
105 }
106 case TFM_CRYPTO_KEY_DERIVATION_INPUT_INTEGER_SID:
107 {
108 return psa_key_derivation_input_integer(operation, iov->step, iov->value);
109 }
110 case TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID:
111 {
112 uint8_t *output = out_vec[0].base;
113 size_t output_length = out_vec[0].len;
114
115 return psa_key_derivation_output_bytes(operation,
116 output, output_length);
117 }
118 case TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID:
119 {
120 return psa_key_derivation_input_key(operation,
121 iov->step, library_key);
122 }
123 case TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID:
124 {
125 psa_key_id_t *key_handle = out_vec[0].base;
126 psa_key_attributes_t srv_key_attr;
127 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(psa_key_id_t))) {
128 return PSA_ERROR_PROGRAMMER_ERROR;
129 }
130
131 if ((in_vec[1].base == NULL) ||
132 (in_vec[1].len != (sizeof(srv_key_attr) - TFM_CRYPTO_KEY_ATTR_OFFSET_CLIENT_SERVER))) {
133 return PSA_ERROR_PROGRAMMER_ERROR;
134 }
135 memcpy(&srv_key_attr, in_vec[1].base, in_vec[1].len);
136 tfm_crypto_library_get_library_key_id_set_owner(encoded_key->owner, &srv_key_attr);
137
138 status = psa_key_derivation_output_key(&srv_key_attr, operation,
139 &library_key);
140
141 *key_handle = CRYPTO_LIBRARY_GET_KEY_ID(library_key);
142 }
143 break;
144 case TFM_CRYPTO_KEY_DERIVATION_ABORT_SID:
145 {
146 p_handle = out_vec[0].base;
147 if ((out_vec[0].base == NULL) || (out_vec[0].len < sizeof(iov->op_handle))) {
148 return PSA_ERROR_PROGRAMMER_ERROR;
149 }
150 *p_handle = iov->op_handle;
151
152 if (status != PSA_SUCCESS) {
153 /*
154 * If lookup() failed to find out a valid operation, it is not
155 * an error for _abort(), as it is allowed to be called multiple
156 * times, and it is likely the operation has just already been
157 * aborted.
158 */
159 return PSA_SUCCESS;
160 }
161
162 status = psa_key_derivation_abort(operation);
163
164 goto release_operation_and_return;
165 }
166 case TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID:
167 {
168 const uint8_t *peer_key = in_vec[1].base;
169 size_t peer_key_length = in_vec[1].len;
170
171 return psa_key_derivation_key_agreement(operation, iov->step,
172 library_key,
173 peer_key,
174 peer_key_length);
175 }
176 break;
177 default:
178 return PSA_ERROR_NOT_SUPPORTED;
179 }
180
181 return status;
182
183 release_operation_and_return:
184 /* Release the operation context, ignore if the operation fails. */
185 (void)tfm_crypto_operation_release(p_handle);
186 return status;
187 }
188 #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)189 psa_status_t tfm_crypto_key_derivation_interface(psa_invec in_vec[],
190 psa_outvec out_vec[],
191 struct tfm_crypto_key_id_s *encoded_key)
192 {
193 (void)in_vec;
194 (void)out_vec;
195 (void)encoded_key;
196
197 return PSA_ERROR_NOT_SUPPORTED;
198 }
199 #endif /* CRYPTO_KEY_DERIVATION_MODULE_ENABLED */
200 /*!@}*/
201