blob: 4f42ee02119a51aa0eac2ecd55ecf7567b999493 [file] [log] [blame]
Antonio de Angelis04debbd2019-10-14 12:12:52 +01001/*
Jamie Fox044bd8e2020-02-20 13:34:57 +00002 * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
Antonio de Angelis04debbd2019-10-14 12:12:52 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <stddef.h>
9#include <stdint.h>
10
11/* FixMe: Use PSA_ERROR_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
Jamie Fox044bd8e2020-02-20 13:34:57 +000018/* Required for mbedtls_calloc in tfm_crypto_huk_derivation_input_bytes */
19#include "mbedtls/platform.h"
20
Antonio de Angelis04debbd2019-10-14 12:12:52 +010021#include "tfm_crypto_api.h"
22#include "tfm_crypto_defs.h"
Jamie Fox044bd8e2020-02-20 13:34:57 +000023#include "tfm_memory_utils.h"
24
25#include "platform/include/tfm_plat_crypto_keys.h"
26
27#ifdef TFM_PARTITION_TEST_SST
28#include "psa_manifest/pid.h"
29#endif /* TFM_PARTITION_TEST_SST */
30
31#ifndef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
32static psa_status_t tfm_crypto_huk_derivation_setup(
33 psa_key_derivation_operation_t *operation,
34 psa_algorithm_t alg)
35{
36 operation->alg = TFM_CRYPTO_ALG_HUK_DERIVATION;
37 return PSA_SUCCESS;
38}
39
40static psa_status_t tfm_crypto_huk_derivation_input_bytes(
41 psa_key_derivation_operation_t *operation,
42 psa_key_derivation_step_t step,
43 const uint8_t *data,
44 size_t data_length)
45{
46 psa_status_t status;
47 int32_t partition_id;
48
49 if (step != PSA_KEY_DERIVATION_INPUT_LABEL) {
50 return PSA_ERROR_INVALID_ARGUMENT;
51 }
52
53 /* Concatenate the caller's partition ID with the supplied label to prevent
54 * two different partitions from deriving the same key.
55 */
56 status = tfm_crypto_get_caller_id(&partition_id);
57 if (status != PSA_SUCCESS) {
58 return status;
59 }
60
61#ifdef TFM_PARTITION_TEST_SST
62 /* The SST tests run some operations under the wrong partition ID - this
63 * causes the key derivation to change.
64 */
65 if (partition_id == TFM_SP_SST_TEST) {
66 partition_id = TFM_SP_STORAGE;
67 }
68#endif /* TFM_PARTITION_TEST_SST */
69
70 /* Put the label in the tls12_prf ctx to make it available in the output key
71 * step.
72 */
73 operation->ctx.tls12_prf.label = mbedtls_calloc(1, sizeof(partition_id)
74 + data_length);
75 if (operation->ctx.tls12_prf.label == NULL) {
76 return PSA_ERROR_INSUFFICIENT_MEMORY;
77 }
78 (void)tfm_memcpy(operation->ctx.tls12_prf.label, &partition_id,
79 sizeof(partition_id));
80 (void)tfm_memcpy(operation->ctx.tls12_prf.label + sizeof(partition_id),
81 data, data_length);
82 operation->ctx.tls12_prf.label_length = sizeof(partition_id) + data_length;
83
84 return PSA_SUCCESS;
85}
86
87static psa_status_t tfm_crypto_huk_derivation_output_key(
88 const psa_key_attributes_t *attributes,
89 psa_key_derivation_operation_t *operation,
90 psa_key_handle_t *handle)
91{
92 enum tfm_plat_err_t err;
93 size_t bytes = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes));
94
95 if (sizeof(operation->ctx.tls12_prf.output_block) < bytes) {
96 return PSA_ERROR_INSUFFICIENT_MEMORY;
97 }
98
99 /* Derive key material from the HUK and output it to the operation buffer */
100 err = tfm_plat_get_huk_derived_key(operation->ctx.tls12_prf.label,
101 operation->ctx.tls12_prf.label_length,
102 NULL, 0,
103 operation->ctx.tls12_prf.output_block,
104 bytes);
105 if (err != TFM_PLAT_ERR_SUCCESS) {
106 return PSA_ERROR_HARDWARE_FAILURE;
107 }
108
109 return psa_import_key(attributes, operation->ctx.tls12_prf.output_block,
110 bytes, handle);
111}
112
113static psa_status_t tfm_crypto_huk_derivation_abort(
114 psa_key_derivation_operation_t *operation)
115{
116 if (operation->ctx.tls12_prf.label != NULL) {
117 (void)tfm_memset(operation->ctx.tls12_prf.label, 0,
118 operation->ctx.tls12_prf.label_length);
119 mbedtls_free(operation->ctx.tls12_prf.label);
120 }
121
122 (void)tfm_memset(operation, 0, sizeof(*operation));
123
124 return PSA_SUCCESS;
125}
126#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100127
128/*!
129 * \defgroup public_psa Public functions, PSA
130 *
131 */
132
133/*!@{*/
134psa_status_t tfm_crypto_key_derivation_setup(psa_invec in_vec[],
135 size_t in_len,
136 psa_outvec out_vec[],
137 size_t out_len)
138{
139#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
140 return PSA_ERROR_NOT_SUPPORTED;
141#else
142 psa_status_t status = PSA_SUCCESS;
143 psa_key_derivation_operation_t *operation = NULL;
144
145 if ((in_len != 1) || (out_len != 1)) {
146 return PSA_ERROR_CONNECTION_REFUSED;
147 }
148
149 if ((out_vec[0].len != sizeof(uint32_t)) ||
150 (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
151 return PSA_ERROR_CONNECTION_REFUSED;
152 }
153 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
154 uint32_t handle = iov->op_handle;
155 uint32_t *handle_out = out_vec[0].base;
156 psa_algorithm_t alg = iov->alg;
157
158 /* Allocate the operation context in the secure world */
159 status = tfm_crypto_operation_alloc(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
160 &handle,
161 (void **)&operation);
162 if (status != PSA_SUCCESS) {
163 return status;
164 }
165
166 *handle_out = handle;
167
Jamie Fox044bd8e2020-02-20 13:34:57 +0000168 if (alg == TFM_CRYPTO_ALG_HUK_DERIVATION) {
169 status = tfm_crypto_huk_derivation_setup(operation, alg);
170 } else {
171 status = psa_key_derivation_setup(operation, alg);
172 }
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100173 if (status != PSA_SUCCESS) {
174 /* Release the operation context, ignore if the operation fails. */
175 (void)tfm_crypto_operation_release(handle_out);
176 return status;
177 }
178
179 return status;
180#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
181}
182
183psa_status_t tfm_crypto_key_derivation_get_capacity(psa_invec in_vec[],
184 size_t in_len,
185 psa_outvec out_vec[],
186 size_t out_len)
187{
188#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
189 return PSA_ERROR_NOT_SUPPORTED;
190#else
191 psa_status_t status;
192 if ((in_len != 1) || (out_len != 1)) {
193 return PSA_ERROR_CONNECTION_REFUSED;
194 }
195
196 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
197 (out_vec[0].len != sizeof(size_t))) {
198 return PSA_ERROR_CONNECTION_REFUSED;
199 }
200 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
201
202 uint32_t handle = iov->op_handle;
203 size_t *capacity = out_vec[0].base;
204 psa_key_derivation_operation_t *operation = NULL;
205
206 /* Look up the corresponding operation context */
207 status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
208 handle,
209 (void **)&operation);
210 if (status != PSA_SUCCESS) {
211 *capacity = 0;
212 return status;
213 }
214
215 return psa_key_derivation_get_capacity(operation, capacity);
216#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
217}
218
219psa_status_t tfm_crypto_key_derivation_set_capacity(psa_invec in_vec[],
220 size_t in_len,
221 psa_outvec out_vec[],
222 size_t out_len)
223{
224#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
225 return PSA_ERROR_NOT_SUPPORTED;
226#else
227 psa_status_t status;
228 if ((in_len != 1) || (out_len != 0)) {
229 return PSA_ERROR_CONNECTION_REFUSED;
230 }
231
232 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
233 return PSA_ERROR_CONNECTION_REFUSED;
234 }
235 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
236
237 uint32_t handle = iov->op_handle;
238 size_t capacity = iov->capacity;
239 psa_key_derivation_operation_t *operation = NULL;
240
241 /* Look up the corresponding operation context */
242 status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
243 handle,
244 (void **)&operation);
245 if (status != PSA_SUCCESS) {
246 return status;
247 }
248
249 return psa_key_derivation_set_capacity(operation, capacity);
250#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
251}
252
253psa_status_t tfm_crypto_key_derivation_input_bytes(psa_invec in_vec[],
254 size_t in_len,
255 psa_outvec out_vec[],
256 size_t out_len)
257{
258#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
259 return PSA_ERROR_NOT_SUPPORTED;
260#else
261 psa_status_t status;
262 if ((in_len != 2) || (out_len != 0)) {
263 return PSA_ERROR_CONNECTION_REFUSED;
264 }
265
266 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
267 return PSA_ERROR_CONNECTION_REFUSED;
268 }
269 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
270
271 uint32_t handle = iov->op_handle;
272 psa_key_derivation_step_t step = iov->step;
273 const uint8_t *data = in_vec[1].base;
274 size_t data_length = in_vec[1].len;
275 psa_key_derivation_operation_t *operation = NULL;
276
277 /* Look up the corresponding operation context */
278 status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
279 handle,
280 (void **)&operation);
281 if (status != PSA_SUCCESS) {
282 return status;
283 }
284
Jamie Fox044bd8e2020-02-20 13:34:57 +0000285 if (operation->alg == TFM_CRYPTO_ALG_HUK_DERIVATION) {
286 return tfm_crypto_huk_derivation_input_bytes(operation, step, data,
287 data_length);
288 } else {
289 return psa_key_derivation_input_bytes(operation, step, data,
290 data_length);
291 }
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100292#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
293}
294
295psa_status_t tfm_crypto_key_derivation_output_bytes(psa_invec in_vec[],
296 size_t in_len,
297 psa_outvec out_vec[],
298 size_t out_len)
299{
300#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
301 return PSA_ERROR_NOT_SUPPORTED;
302#else
303 psa_status_t status;
304 if ((in_len != 1) || (out_len != 1)) {
305 return PSA_ERROR_CONNECTION_REFUSED;
306 }
307
308 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
309 return PSA_ERROR_CONNECTION_REFUSED;
310 }
311 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
312
313 uint32_t handle = iov->op_handle;
314 uint8_t *output = out_vec[0].base;
315 size_t output_length = out_vec[0].len;
316 psa_key_derivation_operation_t *operation = NULL;
317
318 /* Look up the corresponding operation context */
319 status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
320 handle,
321 (void **)&operation);
322 if (status != PSA_SUCCESS) {
323 return status;
324 }
325
326 return psa_key_derivation_output_bytes(operation, output, output_length);
327#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
328}
329
330psa_status_t tfm_crypto_key_derivation_input_key(psa_invec in_vec[],
331 size_t in_len,
332 psa_outvec out_vec[],
333 size_t out_len)
334{
335#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
336 return PSA_ERROR_NOT_SUPPORTED;
337#else
338 psa_status_t status;
339 if ((in_len != 1) || (out_len != 0)) {
340 return PSA_ERROR_CONNECTION_REFUSED;
341 }
342
343 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
344 return PSA_ERROR_CONNECTION_REFUSED;
345 }
346 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
347
348 uint32_t handle = iov->op_handle;
349 psa_key_handle_t key_handle = iov->key_handle;
350 psa_key_derivation_step_t step = iov->step;
351 psa_key_derivation_operation_t *operation = NULL;
352
353 status = tfm_crypto_check_handle_owner(key_handle, NULL);
354 if (status != PSA_SUCCESS) {
355 return status;
356 }
357
358 /* Look up the corresponding operation context */
359 status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
360 handle,
361 (void **)&operation);
362 if (status != PSA_SUCCESS) {
363 return status;
364 }
365
366 return psa_key_derivation_input_key(operation, step, key_handle);
367#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
368}
369
370psa_status_t tfm_crypto_key_derivation_output_key(psa_invec in_vec[],
371 size_t in_len,
372 psa_outvec out_vec[],
373 size_t out_len)
374{
375#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
376 return PSA_ERROR_NOT_SUPPORTED;
377#else
378 psa_status_t status;
379 if ((in_len != 2) || (out_len != 1)) {
380 return PSA_ERROR_CONNECTION_REFUSED;
381 }
382
383 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
384 (in_vec[1].len != sizeof(psa_key_attributes_t)) ||
385 (out_vec[0].len != sizeof(psa_key_handle_t))) {
386 return PSA_ERROR_CONNECTION_REFUSED;
387 }
388 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
389
390 uint32_t handle = iov->op_handle;
391 const psa_key_attributes_t *key_attributes = in_vec[1].base;
392 psa_key_derivation_operation_t *operation = NULL;
393 psa_key_handle_t *key_handle = out_vec[0].base;
Jamie Fox99360e82020-02-20 16:00:09 +0000394 uint32_t index;
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100395
396 /* Look up the corresponding operation context */
397 status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
398 handle,
399 (void **)&operation);
400 if (status != PSA_SUCCESS) {
401 return status;
402 }
Jamie Fox99360e82020-02-20 16:00:09 +0000403
404 status = tfm_crypto_check_key_storage(&index);
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100405 if (status != PSA_SUCCESS) {
406 return status;
407 }
Jamie Fox99360e82020-02-20 16:00:09 +0000408
Jamie Fox044bd8e2020-02-20 13:34:57 +0000409 if (operation->alg == TFM_CRYPTO_ALG_HUK_DERIVATION) {
410 status = tfm_crypto_huk_derivation_output_key(key_attributes, operation,
411 key_handle);
412 } else {
413 status = psa_key_derivation_output_key(key_attributes, operation,
414 key_handle);
415 }
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100416 if (status == PSA_SUCCESS) {
Jamie Fox99360e82020-02-20 16:00:09 +0000417 status = tfm_crypto_set_key_storage(index, *key_handle);
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100418 }
Jamie Fox99360e82020-02-20 16:00:09 +0000419
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100420 return status;
421#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
422}
423
424psa_status_t tfm_crypto_key_derivation_abort(psa_invec in_vec[],
425 size_t in_len,
426 psa_outvec out_vec[],
427 size_t out_len)
428{
429#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
430 return PSA_ERROR_NOT_SUPPORTED;
431#else
432 psa_status_t status;
433 if ((in_len != 1) || (out_len != 1)) {
434 return PSA_ERROR_CONNECTION_REFUSED;
435 }
436
437 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
438 (out_vec[0].len != sizeof(uint32_t))) {
439 return PSA_ERROR_CONNECTION_REFUSED;
440 }
441 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
442
443 uint32_t handle = iov->op_handle;
444 uint32_t *handle_out = out_vec[0].base;
445 psa_key_derivation_operation_t *operation = NULL;
446
447 /* Init the handle in the operation with the one passed from the iov */
448 *handle_out = iov->op_handle;
449
450 /* Look up the corresponding operation context */
451 status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
452 handle,
453 (void **)&operation);
454 if (status != PSA_SUCCESS) {
455 /* Operation does not exist, so abort has no effect */
456 return PSA_SUCCESS;
457 }
458
459 *handle_out = handle;
460
Jamie Fox044bd8e2020-02-20 13:34:57 +0000461 if (operation->alg == TFM_CRYPTO_ALG_HUK_DERIVATION) {
462 status = tfm_crypto_huk_derivation_abort(operation);
463 } else {
464 status = psa_key_derivation_abort(operation);
465 }
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100466 if (status != PSA_SUCCESS) {
467 /* Release the operation context, ignore if the operation fails. */
468 (void)tfm_crypto_operation_release(handle_out);
469 return status;
470 }
471
472 status = tfm_crypto_operation_release(handle_out);
473
474 return status;
475#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
476}
477
478psa_status_t tfm_crypto_key_derivation_key_agreement(psa_invec in_vec[],
479 size_t in_len,
480 psa_outvec out_vec[],
481 size_t out_len)
482{
483#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
484 return PSA_ERROR_NOT_SUPPORTED;
485#else
486 psa_status_t status;
487 if ((in_len != 2) || (out_len != 0)) {
488 return PSA_ERROR_CONNECTION_REFUSED;
489 }
490
491 if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
492 return PSA_ERROR_CONNECTION_REFUSED;
493 }
494 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
495
496 uint32_t handle = iov->op_handle;
497 psa_key_handle_t private_key = iov->key_handle;
498 const uint8_t *peer_key = in_vec[1].base;
499 size_t peer_key_length = in_vec[1].len;
500 psa_key_derivation_operation_t *operation = NULL;
501 psa_key_derivation_step_t step = iov->step;
502
503 status = tfm_crypto_check_handle_owner(private_key, NULL);
504 if (status != PSA_SUCCESS) {
505 return status;
506 }
507
508 /* Look up the corresponding operation context */
509 status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
510 handle,
511 (void **)&operation);
512 if (status != PSA_SUCCESS) {
513 return status;
514 }
515
516 return psa_key_derivation_key_agreement(operation, step,
517 private_key,
518 peer_key,
519 peer_key_length);
520#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
521}
522
523psa_status_t tfm_crypto_generate_random(psa_invec in_vec[],
524 size_t in_len,
525 psa_outvec out_vec[],
526 size_t out_len)
527{
528#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
529 return PSA_ERROR_NOT_SUPPORTED;
530#else
531 if ((in_len != 1) || (out_len != 1)) {
532 return PSA_ERROR_CONNECTION_REFUSED;
533 }
534
535 if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
536 return PSA_ERROR_CONNECTION_REFUSED;
537 }
538 uint8_t *output = out_vec[0].base;
539 size_t output_size = out_vec[0].len;
540
541 return psa_generate_random(output, output_size);
542#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
543}
544
545psa_status_t tfm_crypto_raw_key_agreement(psa_invec in_vec[],
546 size_t in_len,
547 psa_outvec out_vec[],
548 size_t out_len)
549{
550#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
551 return PSA_ERROR_NOT_SUPPORTED;
552#else
553 if ((in_len != 2) || (out_len != 1)) {
554 return PSA_ERROR_CONNECTION_REFUSED;
555 }
556
557 if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
558 return PSA_ERROR_CONNECTION_REFUSED;
559 }
560 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
561 uint8_t *output = out_vec[0].base;
562 size_t output_size = out_vec[0].len;
563 psa_algorithm_t alg = iov->alg;
564 psa_key_handle_t private_key = iov->key_handle;
565 const uint8_t *peer_key = in_vec[1].base;
566 size_t peer_key_length = in_vec[1].len;
567
568 return psa_raw_key_agreement(alg, private_key, peer_key, peer_key_length,
569 output, output_size, &out_vec[0].len);
570#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
571}
572/*!@}*/