blob: 50e12b7f0d9f4c2e4c6abc776ff6c25e731e5718 [file] [log] [blame]
Antonio de Angelis04debbd2019-10-14 12:12:52 +01001/*
Antonio de Angelis202425a2022-04-06 11:13:15 +01002 * Copyright (c) 2019-2022, 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>
Ken Liub671d682022-05-12 20:39:29 +080010#include <string.h>
Antonio de Angelis202425a2022-04-06 11:13:15 +010011#include "tfm_sp_log.h"
Antonio de Angelis04debbd2019-10-14 12:12:52 +010012
Antonio de Angelis04debbd2019-10-14 12:12:52 +010013#include "tfm_mbedcrypto_include.h"
14
Jamie Fox044bd8e2020-02-20 13:34:57 +000015/* Required for mbedtls_calloc in tfm_crypto_huk_derivation_input_bytes */
16#include "mbedtls/platform.h"
17
Antonio de Angelis04debbd2019-10-14 12:12:52 +010018#include "tfm_crypto_api.h"
19#include "tfm_crypto_defs.h"
Jamie Fox044bd8e2020-02-20 13:34:57 +000020
Mingyang Sun8a19e7a2020-06-04 15:36:58 +080021#include "tfm_plat_crypto_keys.h"
Antonio de Angelis202425a2022-04-06 11:13:15 +010022
23#ifndef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
24#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER must be selected in Mbed TLS config file"
25#endif
Jamie Fox044bd8e2020-02-20 13:34:57 +000026
Kevin Pengc6d74502020-03-04 16:55:37 +080027#ifdef TFM_PARTITION_TEST_PS
Jamie Fox044bd8e2020-02-20 13:34:57 +000028#include "psa_manifest/pid.h"
Kevin Pengc6d74502020-03-04 16:55:37 +080029#endif /* TFM_PARTITION_TEST_PS */
Jamie Fox044bd8e2020-02-20 13:34:57 +000030
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{
Summer Qin359167d2021-07-05 18:11:50 +080036 operation->MBEDTLS_PRIVATE(alg) = TFM_CRYPTO_ALG_HUK_DERIVATION;
Jamie Fox044bd8e2020-02-20 13:34:57 +000037 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;
Summer Qin359167d2021-07-05 18:11:50 +080048 psa_tls12_prf_key_derivation_t *tls12_prf;
Jamie Fox044bd8e2020-02-20 13:34:57 +000049
50 if (step != PSA_KEY_DERIVATION_INPUT_LABEL) {
51 return PSA_ERROR_INVALID_ARGUMENT;
52 }
53
54 /* Concatenate the caller's partition ID with the supplied label to prevent
55 * two different partitions from deriving the same key.
56 */
57 status = tfm_crypto_get_caller_id(&partition_id);
58 if (status != PSA_SUCCESS) {
59 return status;
60 }
61
Kevin Pengc6d74502020-03-04 16:55:37 +080062#ifdef TFM_PARTITION_TEST_PS
63 /* The PS tests run some operations under the wrong partition ID - this
Jamie Fox044bd8e2020-02-20 13:34:57 +000064 * causes the key derivation to change.
65 */
Kevin Pengc6d74502020-03-04 16:55:37 +080066 if (partition_id == TFM_SP_PS_TEST) {
67 partition_id = TFM_SP_PS;
Jamie Fox044bd8e2020-02-20 13:34:57 +000068 }
Kevin Pengc6d74502020-03-04 16:55:37 +080069#endif /* TFM_PARTITION_TEST_PS */
Jamie Fox044bd8e2020-02-20 13:34:57 +000070
71 /* Put the label in the tls12_prf ctx to make it available in the output key
72 * step.
73 */
Summer Qin359167d2021-07-05 18:11:50 +080074 tls12_prf = &(operation->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(tls12_prf));
75 tls12_prf->MBEDTLS_PRIVATE(label) =
76 mbedtls_calloc(1, sizeof(partition_id) + data_length);
77 if (tls12_prf->MBEDTLS_PRIVATE(label) == NULL) {
Jamie Fox044bd8e2020-02-20 13:34:57 +000078 return PSA_ERROR_INSUFFICIENT_MEMORY;
79 }
Ken Liub671d682022-05-12 20:39:29 +080080 (void)memcpy(tls12_prf->MBEDTLS_PRIVATE(label), &partition_id,
81 sizeof(partition_id));
82 (void)memcpy(tls12_prf->MBEDTLS_PRIVATE(label) + sizeof(partition_id),
83 data, data_length);
Summer Qin359167d2021-07-05 18:11:50 +080084 tls12_prf->MBEDTLS_PRIVATE(label_length) = sizeof(partition_id) +
85 data_length;
Jamie Fox044bd8e2020-02-20 13:34:57 +000086
87 return PSA_SUCCESS;
88}
89
90static psa_status_t tfm_crypto_huk_derivation_output_key(
91 const psa_key_attributes_t *attributes,
92 psa_key_derivation_operation_t *operation,
Maulik Patel28659c42021-01-06 14:09:22 +000093 mbedtls_svc_key_id_t *key_id)
Jamie Fox044bd8e2020-02-20 13:34:57 +000094{
95 enum tfm_plat_err_t err;
96 size_t bytes = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes));
Summer Qin359167d2021-07-05 18:11:50 +080097 psa_tls12_prf_key_derivation_t *tls12_prf =
98 &(operation->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(tls12_prf));
Jamie Fox044bd8e2020-02-20 13:34:57 +000099
Summer Qin359167d2021-07-05 18:11:50 +0800100 if (sizeof(tls12_prf->MBEDTLS_PRIVATE(output_block)) < bytes) {
Jamie Fox044bd8e2020-02-20 13:34:57 +0000101 return PSA_ERROR_INSUFFICIENT_MEMORY;
102 }
103
104 /* Derive key material from the HUK and output it to the operation buffer */
Antonio de Angelis202425a2022-04-06 11:13:15 +0100105 /* The function below accesses an abstracted functionality at platform level
106 * to get a key derived from the HUK. The specific algorithm is abstracted
107 * away to the platform implementation (i.e. it can be HMAC-based KDF or
108 * CMAC based KDF, the latter for example when CC-312 is present)
109 */
Summer Qin359167d2021-07-05 18:11:50 +0800110 err = tfm_plat_get_huk_derived_key(tls12_prf->MBEDTLS_PRIVATE(label),
111 tls12_prf->MBEDTLS_PRIVATE(label_length),
Jamie Fox044bd8e2020-02-20 13:34:57 +0000112 NULL, 0,
Summer Qin359167d2021-07-05 18:11:50 +0800113 tls12_prf->MBEDTLS_PRIVATE(output_block),
Jamie Fox044bd8e2020-02-20 13:34:57 +0000114 bytes);
115 if (err != TFM_PLAT_ERR_SUCCESS) {
116 return PSA_ERROR_HARDWARE_FAILURE;
117 }
Antonio de Angelis202425a2022-04-06 11:13:15 +0100118 LOG_DBGFMT("\033[0;32mcomplete.\033[0m\r\n");
Jamie Fox044bd8e2020-02-20 13:34:57 +0000119
Summer Qin359167d2021-07-05 18:11:50 +0800120 return psa_import_key(attributes, tls12_prf->MBEDTLS_PRIVATE(output_block),
Maulik Patel28659c42021-01-06 14:09:22 +0000121 bytes, key_id);
Jamie Fox044bd8e2020-02-20 13:34:57 +0000122}
123
124static psa_status_t tfm_crypto_huk_derivation_abort(
125 psa_key_derivation_operation_t *operation)
126{
Summer Qin359167d2021-07-05 18:11:50 +0800127 psa_tls12_prf_key_derivation_t *tls12_prf =
128 &(operation->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(tls12_prf));
129
130 if (tls12_prf->MBEDTLS_PRIVATE(label) != NULL) {
Ken Liub671d682022-05-12 20:39:29 +0800131 (void)memset(tls12_prf->MBEDTLS_PRIVATE(label), 0,
132 tls12_prf->MBEDTLS_PRIVATE(label_length));
Summer Qin359167d2021-07-05 18:11:50 +0800133 mbedtls_free(tls12_prf->MBEDTLS_PRIVATE(label));
Jamie Fox044bd8e2020-02-20 13:34:57 +0000134 }
135
Ken Liub671d682022-05-12 20:39:29 +0800136 (void)memset(operation, 0, sizeof(*operation));
Jamie Fox044bd8e2020-02-20 13:34:57 +0000137
138 return PSA_SUCCESS;
139}
140#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100141
142/*!
Antonio de Angelis202425a2022-04-06 11:13:15 +0100143 * \addtogroup tfm_crypto_api_shim_layer
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100144 *
145 */
146
147/*!@{*/
Antonio de Angelis202425a2022-04-06 11:13:15 +0100148psa_status_t tfm_crypto_key_derivation_interface(psa_invec in_vec[],
149 psa_outvec out_vec[],
150 mbedtls_svc_key_id_t *encoded_key)
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100151{
152#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
153 return PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100154#endif
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100155 const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100156 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
157 psa_key_derivation_operation_t *operation = NULL;
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100158 uint32_t handle = iov->op_handle;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100159 uint32_t *handle_out = NULL;
160 enum tfm_crypto_function_type function_type =
161 TFM_CRYPTO_GET_FUNCTION_TYPE(iov->function_id);
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100162
Antonio de Angelis202425a2022-04-06 11:13:15 +0100163 if (function_type != TFM_CRYPTO_FUNCTION_TYPE_NON_MULTIPART) {
164 handle_out = (out_vec && out_vec[0].base != NULL) ?
165 out_vec[0].base : &handle;
166 *handle_out = handle;
167 status = tfm_crypto_operation_handling(
168 TFM_CRYPTO_KEY_DERIVATION_OPERATION,
169 function_type,
170 handle_out,
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100171 (void **)&operation);
Antonio de Angelis202425a2022-04-06 11:13:15 +0100172 if (status != PSA_SUCCESS) {
173 return (iov->function_id == TFM_CRYPTO_KEY_DERIVATION_ABORT_SID) ?
174 PSA_SUCCESS : status;
175 }
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100176 }
177
Antonio de Angelis202425a2022-04-06 11:13:15 +0100178 switch (iov->function_id) {
179 case TFM_CRYPTO_KEY_DERIVATION_SETUP_SID:
180 {
181 if (iov->alg == TFM_CRYPTO_ALG_HUK_DERIVATION) {
182 status = tfm_crypto_huk_derivation_setup(operation, iov->alg);
183 } else {
184 status = psa_key_derivation_setup(operation, iov->alg);
185 }
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100186
Antonio de Angelis202425a2022-04-06 11:13:15 +0100187 if (status != PSA_SUCCESS) {
188 goto release_operation_and_return;
189 }
Jamie Fox044bd8e2020-02-20 13:34:57 +0000190 }
Antonio de Angelis202425a2022-04-06 11:13:15 +0100191 break;
192 case TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID:
193 {
194 size_t *capacity = out_vec[0].base;
195
196 status = psa_key_derivation_get_capacity(operation, capacity);
197 }
198 break;
199 case TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID:
200 {
201 status = psa_key_derivation_set_capacity(operation, iov->capacity);
202 }
203 break;
204 case TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID:
205 {
206 const uint8_t *data = in_vec[1].base;
207 size_t data_length = in_vec[1].len;
208
209 if (operation->MBEDTLS_PRIVATE(alg) == TFM_CRYPTO_ALG_HUK_DERIVATION) {
210 status = tfm_crypto_huk_derivation_input_bytes(operation,
211 iov->step, data,
212 data_length);
213 } else {
214 status = psa_key_derivation_input_bytes(operation, iov->step, data,
215 data_length);
216 }
217 }
218 break;
219 case TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID:
220 {
221 uint8_t *output = out_vec[0].base;
222 size_t output_length = out_vec[0].len;
223
224 status = psa_key_derivation_output_bytes(operation,
225 output, output_length);
226 }
227 break;
228 case TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID:
229 {
230 status = psa_key_derivation_input_key(operation,
231 iov->step, *encoded_key);
232 }
233 break;
234 case TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID:
235 {
236 const struct psa_client_key_attributes_s *client_key_attr =
237 in_vec[1].base;
238 psa_key_id_t *key_handle = out_vec[0].base;
239 psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
240 int32_t partition_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(*encoded_key);
241
242 status = tfm_crypto_key_attributes_from_client(client_key_attr,
243 partition_id,
244 &key_attributes);
245 if (status != PSA_SUCCESS) {
246 return status;
247 }
248
249 if (operation->MBEDTLS_PRIVATE(alg) == TFM_CRYPTO_ALG_HUK_DERIVATION) {
250 status = tfm_crypto_huk_derivation_output_key(&key_attributes,
251 operation, encoded_key);
252 } else {
253 status = psa_key_derivation_output_key(&key_attributes, operation,
254 encoded_key);
255 }
256
257 *key_handle = encoded_key->MBEDTLS_PRIVATE(key_id);
258 }
259 break;
260 case TFM_CRYPTO_KEY_DERIVATION_ABORT_SID:
261 {
262 if (operation->MBEDTLS_PRIVATE(alg) == TFM_CRYPTO_ALG_HUK_DERIVATION) {
263 status = tfm_crypto_huk_derivation_abort(operation);
264 } else {
265 status = psa_key_derivation_abort(operation);
266 }
267
268 if (status != PSA_SUCCESS) {
269 goto release_operation_and_return;
270 } else {
271 status = tfm_crypto_operation_release(handle_out);
272 }
273 }
274 break;
275 case TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID:
276 {
277 const uint8_t *peer_key = in_vec[1].base;
278 size_t peer_key_length = in_vec[1].len;
279
280 status = psa_key_derivation_key_agreement(operation, iov->step,
281 *encoded_key,
282 peer_key,
283 peer_key_length);
284 }
285 break;
286 case TFM_CRYPTO_RAW_KEY_AGREEMENT_SID:
287 {
288 uint8_t *output = out_vec[0].base;
289 size_t output_size = out_vec[0].len;
290 const uint8_t *peer_key = in_vec[1].base;
291 size_t peer_key_length = in_vec[1].len;
292
293 status = psa_raw_key_agreement(iov->alg, *encoded_key,
294 peer_key, peer_key_length,
295 output, output_size, &out_vec[0].len);
296 }
297 break;
298 default:
299 status = PSA_ERROR_NOT_SUPPORTED;
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100300 }
301
302 return status;
Antonio de Angelis202425a2022-04-06 11:13:15 +0100303release_operation_and_return:
304 /* Release the operation context, ignore if the operation fails. */
305 (void)tfm_crypto_operation_release(handle_out);
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100306 return status;
Antonio de Angelis04debbd2019-10-14 12:12:52 +0100307}
308/*!@}*/