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