blob: 4328ca8232f66b7b2ecf44b92ef7dc3142882508 [file] [log] [blame]
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +01001/*
2 * Copyright (c) 2019, 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/* FixMe: Use PSA_CONNECTION_REFUSED when performing parameter
12 * integrity checks but this will have to be revised
13 * when the full set of error codes mandated by PSA FF
14 * is available.
15 */
16#include "tfm_mbedcrypto_include.h"
17
18#include "tfm_crypto_api.h"
19#include "tfm_crypto_defs.h"
20
21/*!
22 * \defgroup public_psa Public functions, PSA
23 *
24 */
25
26/*!@{*/
27psa_status_t tfm_crypto_get_generator_capacity(psa_invec in_vec[],
28 size_t in_len,
29 psa_outvec out_vec[],
30 size_t out_len)
31{
32 psa_status_t status;
33 if ((in_len != 1) || (out_len != 1)) {
34 return PSA_CONNECTION_REFUSED;
35 }
36
37 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
38 (out_vec[0].len != sizeof(size_t))) {
39 return PSA_CONNECTION_REFUSED;
40 }
41 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
42
43 uint32_t handle = iov->op_handle;
44 size_t *capacity = out_vec[0].base;
45 psa_crypto_generator_t *generator = NULL;
46
47 /* Look up the corresponding operation context */
48 status = tfm_crypto_operation_lookup(TFM_CRYPTO_GENERATOR_OPERATION,
49 handle,
50 (void **)&generator);
51 if (status != PSA_SUCCESS) {
52 *capacity = 0;
53 return status;
54 }
55
56 return psa_get_generator_capacity(generator, capacity);
57}
58
59psa_status_t tfm_crypto_generator_read(psa_invec in_vec[],
60 size_t in_len,
61 psa_outvec out_vec[],
62 size_t out_len)
63{
64 psa_status_t status;
65 if ((in_len != 1) || (out_len != 1)) {
66 return PSA_CONNECTION_REFUSED;
67 }
68
69 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
70 return PSA_CONNECTION_REFUSED;
71 }
72 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
73
74 uint32_t handle = iov->op_handle;
75 uint8_t *output = out_vec[0].base;
76 size_t output_length = out_vec[0].len;
77 psa_crypto_generator_t *generator = NULL;
78
79 /* Look up the corresponding operation context */
80 status = tfm_crypto_operation_lookup(TFM_CRYPTO_GENERATOR_OPERATION,
81 handle,
82 (void **)&generator);
83 if (status != PSA_SUCCESS) {
84 return status;
85 }
86
87 return psa_generator_read(generator, output, output_length);
88}
89
90psa_status_t tfm_crypto_generator_import_key(psa_invec in_vec[],
91 size_t in_len,
92 psa_outvec out_vec[],
93 size_t out_len)
94{
95 psa_status_t status;
96 if ((in_len != 2) || (out_len != 0)) {
97 return PSA_CONNECTION_REFUSED;
98 }
99
100 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
101 (in_vec[1].len != sizeof(size_t))) {
102 return PSA_CONNECTION_REFUSED;
103 }
104 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
105
106 uint32_t handle = iov->op_handle;
107 psa_key_handle_t key_handle = iov->key_handle;
108 psa_key_type_t type = iov->type;
109 size_t bits = *(size_t *)(in_vec[1].base);
110 psa_crypto_generator_t *generator = NULL;
111
112 /* Look up the corresponding operation context */
113 status = tfm_crypto_operation_lookup(TFM_CRYPTO_GENERATOR_OPERATION,
114 handle,
115 (void **)&generator);
116 if (status != PSA_SUCCESS) {
117 return status;
118 }
119
120 return psa_generator_import_key(key_handle, type, bits, generator);
121}
122
123psa_status_t tfm_crypto_generator_abort(psa_invec in_vec[],
124 size_t in_len,
125 psa_outvec out_vec[],
126 size_t out_len)
127{
128 psa_status_t status;
129 if ((in_len != 1) || (out_len != 1)) {
130 return PSA_CONNECTION_REFUSED;
131 }
132
133 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
134 (out_vec[0].len != sizeof(uint32_t))) {
135 return PSA_CONNECTION_REFUSED;
136 }
137 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
138
139 uint32_t handle = iov->op_handle;
140 uint32_t *handle_out = out_vec[0].base;
141 psa_crypto_generator_t *generator = NULL;
142
143 /* Init the handle in the operation with the one passed from the iov */
144 *handle_out = iov->op_handle;
145
146 /* Look up the corresponding operation context */
147 status = tfm_crypto_operation_lookup(TFM_CRYPTO_GENERATOR_OPERATION,
148 handle,
149 (void **)&generator);
150 if (status != PSA_SUCCESS) {
151 /* Operation does not exist, so abort has no effect */
152 return PSA_SUCCESS;
153 }
154
155 *handle_out = handle;
156
157 status = psa_generator_abort(generator);
158 if (status != PSA_SUCCESS) {
Jamie Fox707caf72019-05-29 15:14:18 +0100159 /* Release the operation context, ignore if the operation fails. */
160 (void)tfm_crypto_operation_release(handle_out);
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100161 return status;
162 }
163
164 status = tfm_crypto_operation_release(handle_out);
165
166 return status;
167}
168
169psa_status_t tfm_crypto_key_derivation(psa_invec in_vec[],
170 size_t in_len,
171 psa_outvec out_vec[],
172 size_t out_len)
173{
174 psa_status_t status;
175 if (!((in_len == 1) || (in_len == 2) || (in_len == 3)) || (out_len != 1)) {
176 return PSA_CONNECTION_REFUSED;
177 }
178
179 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
180 (out_vec[0].len != sizeof(uint32_t))) {
181 return PSA_CONNECTION_REFUSED;
182 }
183 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
184
185 uint32_t handle = iov->op_handle;
186 uint32_t *handle_out = out_vec[0].base;
187 psa_key_handle_t key_handle = iov->key_handle;
188 psa_algorithm_t alg = iov->alg;
189 const uint8_t *salt = NULL;
190 size_t salt_length = 0;
191 const uint8_t *label = NULL;
192 size_t label_length = 0;
193 size_t capacity = iov->capacity;
194 psa_crypto_generator_t *generator = NULL;
195
196 if (in_len > 1) {
197 salt = in_vec[2].base;
198 salt_length = in_vec[2].len;
199 }
200
201 if (in_len > 2) {
202 label = in_vec[3].base;
203 label_length = in_vec[3].len;
204 }
205
206 /* Allocate the generator context in the secure world */
207 status = tfm_crypto_operation_alloc(TFM_CRYPTO_GENERATOR_OPERATION,
208 &handle,
209 (void **)&generator);
210 if (status != PSA_SUCCESS) {
211 return status;
212 }
213
214 *handle_out = handle;
215
Jamie Fox707caf72019-05-29 15:14:18 +0100216 status = psa_key_derivation(generator, key_handle, alg, salt, salt_length,
217 label, label_length, capacity);
218 if (status != PSA_SUCCESS) {
219 /* Release the operation context, ignore if the operation fails. */
220 (void)tfm_crypto_operation_release(handle_out);
221 }
222
223 return status;
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100224}
225
226psa_status_t tfm_crypto_key_agreement(psa_invec in_vec[],
227 size_t in_len,
228 psa_outvec out_vec[],
229 size_t out_len)
230{
231 psa_status_t status;
232 if ((in_len != 2) || (out_len != 1)) {
233 return PSA_CONNECTION_REFUSED;
234 }
235
236 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
237 (out_vec[0].len != sizeof(uint32_t))) {
238 return PSA_CONNECTION_REFUSED;
239 }
240 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
241
242 uint32_t handle = iov->op_handle;
243 uint32_t *handle_out = out_vec[0].base;
244 psa_key_handle_t private_key = iov->key_handle;
245 psa_algorithm_t alg = iov->alg;
246 const uint8_t *peer_key = in_vec[1].base;
247 size_t peer_key_length = in_vec[1].len;
248 psa_crypto_generator_t *generator = NULL;
249
250 /* Allocate the generator context in the secure world */
251 status = tfm_crypto_operation_alloc(TFM_CRYPTO_GENERATOR_OPERATION,
252 &handle,
253 (void **)&generator);
254 if (status != PSA_SUCCESS) {
255 return status;
256 }
257
258 *handle_out = handle;
259
Jamie Fox707caf72019-05-29 15:14:18 +0100260 status = psa_key_agreement(generator, private_key,
261 peer_key, peer_key_length, alg);
262 if (status != PSA_SUCCESS) {
263 /* Release the operation context, ignore if the operation fails. */
264 (void)tfm_crypto_operation_release(handle_out);
265 }
266
267 return status;
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100268}
269
270psa_status_t tfm_crypto_generate_random(psa_invec in_vec[],
271 size_t in_len,
272 psa_outvec out_vec[],
273 size_t out_len)
274{
275 if ((in_len != 1) || (out_len != 1)) {
276 return PSA_CONNECTION_REFUSED;
277 }
278
279 if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
280 return PSA_CONNECTION_REFUSED;
281 }
282 uint8_t *output = out_vec[0].base;
283 size_t output_size = out_vec[0].len;
284
285 return psa_generate_random(output, output_size);
286}
287
288psa_status_t tfm_crypto_generate_key(psa_invec in_vec[],
289 size_t in_len,
290 psa_outvec out_vec[],
291 size_t out_len)
292{
293 if (!((in_len == 2) || (in_len == 3)) || (out_len != 0)) {
294 return PSA_CONNECTION_REFUSED;
295 }
296
297 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
298 (in_vec[1].len != sizeof(size_t))) {
299 return PSA_CONNECTION_REFUSED;
300 }
301 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
302 psa_key_handle_t key_handle = iov->key_handle;
303 psa_key_type_t type = iov->type;
304 size_t bits = *((size_t *)(in_vec[1].base));
305 const void *extra = NULL;
306 size_t extra_size = 0;
307
308 if (in_len == 3) {
309 extra = in_vec[2].base;
310 extra_size = in_vec[2].len;
311 }
312
313 return psa_generate_key(key_handle, type, bits, extra, extra_size);
314}
315/*!@}*/