blob: bb79de957d7b92ae046abbcf01669b3b3d26b05a [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
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100112 status = tfm_crypto_check_handle_owner(key_handle, NULL);
113 if (status != PSA_SUCCESS) {
114 return status;
115 }
116
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100117 /* Look up the corresponding operation context */
118 status = tfm_crypto_operation_lookup(TFM_CRYPTO_GENERATOR_OPERATION,
119 handle,
120 (void **)&generator);
121 if (status != PSA_SUCCESS) {
122 return status;
123 }
124
125 return psa_generator_import_key(key_handle, type, bits, generator);
126}
127
128psa_status_t tfm_crypto_generator_abort(psa_invec in_vec[],
129 size_t in_len,
130 psa_outvec out_vec[],
131 size_t out_len)
132{
133 psa_status_t status;
134 if ((in_len != 1) || (out_len != 1)) {
135 return PSA_CONNECTION_REFUSED;
136 }
137
138 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
139 (out_vec[0].len != sizeof(uint32_t))) {
140 return PSA_CONNECTION_REFUSED;
141 }
142 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
143
144 uint32_t handle = iov->op_handle;
145 uint32_t *handle_out = out_vec[0].base;
146 psa_crypto_generator_t *generator = NULL;
147
148 /* Init the handle in the operation with the one passed from the iov */
149 *handle_out = iov->op_handle;
150
151 /* Look up the corresponding operation context */
152 status = tfm_crypto_operation_lookup(TFM_CRYPTO_GENERATOR_OPERATION,
153 handle,
154 (void **)&generator);
155 if (status != PSA_SUCCESS) {
156 /* Operation does not exist, so abort has no effect */
157 return PSA_SUCCESS;
158 }
159
160 *handle_out = handle;
161
162 status = psa_generator_abort(generator);
163 if (status != PSA_SUCCESS) {
Jamie Fox707caf72019-05-29 15:14:18 +0100164 /* Release the operation context, ignore if the operation fails. */
165 (void)tfm_crypto_operation_release(handle_out);
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100166 return status;
167 }
168
169 status = tfm_crypto_operation_release(handle_out);
170
171 return status;
172}
173
174psa_status_t tfm_crypto_key_derivation(psa_invec in_vec[],
175 size_t in_len,
176 psa_outvec out_vec[],
177 size_t out_len)
178{
179 psa_status_t status;
180 if (!((in_len == 1) || (in_len == 2) || (in_len == 3)) || (out_len != 1)) {
181 return PSA_CONNECTION_REFUSED;
182 }
183
184 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
185 (out_vec[0].len != sizeof(uint32_t))) {
186 return PSA_CONNECTION_REFUSED;
187 }
188 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
189
190 uint32_t handle = iov->op_handle;
191 uint32_t *handle_out = out_vec[0].base;
192 psa_key_handle_t key_handle = iov->key_handle;
193 psa_algorithm_t alg = iov->alg;
194 const uint8_t *salt = NULL;
195 size_t salt_length = 0;
196 const uint8_t *label = NULL;
197 size_t label_length = 0;
198 size_t capacity = iov->capacity;
199 psa_crypto_generator_t *generator = NULL;
200
201 if (in_len > 1) {
202 salt = in_vec[2].base;
203 salt_length = in_vec[2].len;
204 }
205
206 if (in_len > 2) {
207 label = in_vec[3].base;
208 label_length = in_vec[3].len;
209 }
210
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100211 status = tfm_crypto_check_handle_owner(key_handle, NULL);
212 if (status != PSA_SUCCESS) {
213 return status;
214 }
215
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100216 /* Allocate the generator context in the secure world */
217 status = tfm_crypto_operation_alloc(TFM_CRYPTO_GENERATOR_OPERATION,
218 &handle,
219 (void **)&generator);
220 if (status != PSA_SUCCESS) {
221 return status;
222 }
223
224 *handle_out = handle;
225
Jamie Fox707caf72019-05-29 15:14:18 +0100226 status = psa_key_derivation(generator, key_handle, alg, salt, salt_length,
227 label, label_length, capacity);
228 if (status != PSA_SUCCESS) {
229 /* Release the operation context, ignore if the operation fails. */
230 (void)tfm_crypto_operation_release(handle_out);
231 }
232
233 return status;
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100234}
235
236psa_status_t tfm_crypto_key_agreement(psa_invec in_vec[],
237 size_t in_len,
238 psa_outvec out_vec[],
239 size_t out_len)
240{
241 psa_status_t status;
242 if ((in_len != 2) || (out_len != 1)) {
243 return PSA_CONNECTION_REFUSED;
244 }
245
246 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
247 (out_vec[0].len != sizeof(uint32_t))) {
248 return PSA_CONNECTION_REFUSED;
249 }
250 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
251
252 uint32_t handle = iov->op_handle;
253 uint32_t *handle_out = out_vec[0].base;
254 psa_key_handle_t private_key = iov->key_handle;
255 psa_algorithm_t alg = iov->alg;
256 const uint8_t *peer_key = in_vec[1].base;
257 size_t peer_key_length = in_vec[1].len;
258 psa_crypto_generator_t *generator = NULL;
259
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100260 status = tfm_crypto_check_handle_owner(private_key, NULL);
261 if (status != PSA_SUCCESS) {
262 return status;
263 }
264
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100265 /* Allocate the generator context in the secure world */
266 status = tfm_crypto_operation_alloc(TFM_CRYPTO_GENERATOR_OPERATION,
267 &handle,
268 (void **)&generator);
269 if (status != PSA_SUCCESS) {
270 return status;
271 }
272
273 *handle_out = handle;
274
Jamie Fox707caf72019-05-29 15:14:18 +0100275 status = psa_key_agreement(generator, private_key,
276 peer_key, peer_key_length, alg);
277 if (status != PSA_SUCCESS) {
278 /* Release the operation context, ignore if the operation fails. */
279 (void)tfm_crypto_operation_release(handle_out);
280 }
281
282 return status;
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100283}
284
285psa_status_t tfm_crypto_generate_random(psa_invec in_vec[],
286 size_t in_len,
287 psa_outvec out_vec[],
288 size_t out_len)
289{
290 if ((in_len != 1) || (out_len != 1)) {
291 return PSA_CONNECTION_REFUSED;
292 }
293
294 if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
295 return PSA_CONNECTION_REFUSED;
296 }
297 uint8_t *output = out_vec[0].base;
298 size_t output_size = out_vec[0].len;
299
300 return psa_generate_random(output, output_size);
301}
302
303psa_status_t tfm_crypto_generate_key(psa_invec in_vec[],
304 size_t in_len,
305 psa_outvec out_vec[],
306 size_t out_len)
307{
308 if (!((in_len == 2) || (in_len == 3)) || (out_len != 0)) {
309 return PSA_CONNECTION_REFUSED;
310 }
311
312 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
313 (in_vec[1].len != sizeof(size_t))) {
314 return PSA_CONNECTION_REFUSED;
315 }
316 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
317 psa_key_handle_t key_handle = iov->key_handle;
318 psa_key_type_t type = iov->type;
319 size_t bits = *((size_t *)(in_vec[1].base));
320 const void *extra = NULL;
321 size_t extra_size = 0;
Antonio de Angelis60a6fe62019-06-18 15:27:34 +0100322 psa_status_t status;
323
324 status = tfm_crypto_check_handle_owner(key_handle, NULL);
325 if (status != PSA_SUCCESS) {
326 return status;
327 }
Antonio de Angelis25e2b2d2019-04-25 14:49:50 +0100328
329 if (in_len == 3) {
330 extra = in_vec[2].base;
331 extra_size = in_vec[2].len;
332 }
333
334 return psa_generate_key(key_handle, type, bits, extra, extra_size);
335}
336/*!@}*/