1 /*
2  * Copyright (c) 2018-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 
12 #include "config_crypto.h"
13 #include "tfm_mbedcrypto_include.h"
14 
15 #include "tfm_crypto_api.h"
16 #include "tfm_crypto_defs.h"
17 
18 
19 struct tfm_crypto_operation_s {
20     uint32_t in_use;                /*!< Indicates if the operation is in use */
21     int32_t owner;                  /*!< Indicates an ID of the owner of
22                                      *   the context
23                                      */
24     enum tfm_crypto_operation_type type; /*!< Type of the operation */
25     union {
26         psa_cipher_operation_t cipher;    /*!< Cipher operation context */
27         psa_mac_operation_t mac;          /*!< MAC operation context */
28         psa_hash_operation_t hash;        /*!< Hash operation context */
29         psa_key_derivation_operation_t key_deriv; /*!< Key derivation operation context */
30         psa_aead_operation_t aead;        /*!< AEAD operation context */
31     } operation;
32 };
33 
34 static struct tfm_crypto_operation_s operations[CRYPTO_CONC_OPER_NUM] = {{0}};
35 
36 /*
37  * \brief Function used to clear the memory associated to a backend context
38  *
39  * \param[in] index Numerical index in the database of the backend contexts
40  *
41  * \return None
42  *
43  */
memset_operation_context(uint32_t index)44 static void memset_operation_context(uint32_t index)
45 {
46     /* Clear the contents of the backend context */
47     (void)memset((uint8_t *)&(operations[index].operation), 0,
48                  sizeof(operations[index].operation));
49 }
50 
51 /*!
52  * \defgroup alloc Function that implement allocation and deallocation of
53  *                 contexts to be stored in the secure world for multipart
54  *                 operations
55  */
56 
57 /*!@{*/
tfm_crypto_init_alloc(void)58 psa_status_t tfm_crypto_init_alloc(void)
59 {
60     /* Clear the contents of the local contexts */
61     (void)memset(operations, 0, sizeof(operations));
62     return PSA_SUCCESS;
63 }
64 
tfm_crypto_operation_alloc(enum tfm_crypto_operation_type type,uint32_t * handle,void ** ctx)65 psa_status_t tfm_crypto_operation_alloc(enum tfm_crypto_operation_type type,
66                                         uint32_t *handle,
67                                         void **ctx)
68 {
69     uint32_t i = 0;
70     int32_t partition_id = 0;
71     psa_status_t status;
72 
73     /* Handle must be initialised before calling a setup function */
74     if (*handle != TFM_CRYPTO_INVALID_HANDLE) {
75         return PSA_ERROR_BAD_STATE;
76     }
77 
78     /* Init to invalid values */
79     if (ctx == NULL) {
80         return PSA_ERROR_INVALID_ARGUMENT;
81     }
82     *ctx = NULL;
83 
84     status = tfm_crypto_get_caller_id(&partition_id);
85     if (status != PSA_SUCCESS) {
86         return status;
87     }
88 
89     for (i = 0; i < CRYPTO_CONC_OPER_NUM; i++) {
90         if (operations[i].in_use == TFM_CRYPTO_NOT_IN_USE) {
91             operations[i].in_use = TFM_CRYPTO_IN_USE;
92             operations[i].owner = partition_id;
93             operations[i].type = type;
94             *handle = i + 1;
95             *ctx = (void *) &(operations[i].operation);
96             return PSA_SUCCESS;
97         }
98     }
99 
100     return PSA_ERROR_NOT_PERMITTED;
101 }
102 
tfm_crypto_operation_release(uint32_t * handle)103 psa_status_t tfm_crypto_operation_release(uint32_t *handle)
104 {
105     uint32_t h_val = *handle;
106     int32_t partition_id = 0;
107     psa_status_t status;
108 
109     /* Handle shall be cleaned up always at first */
110     *handle = TFM_CRYPTO_INVALID_HANDLE;
111 
112     if ((h_val == TFM_CRYPTO_INVALID_HANDLE) ||
113         (h_val > CRYPTO_CONC_OPER_NUM)) {
114         return PSA_ERROR_INVALID_ARGUMENT;
115     }
116 
117     status = tfm_crypto_get_caller_id(&partition_id);
118     if (status != PSA_SUCCESS) {
119         return status;
120     }
121 
122     if ((operations[h_val - 1].in_use == TFM_CRYPTO_IN_USE) &&
123         (operations[h_val - 1].owner == partition_id)) {
124 
125         memset_operation_context(h_val - 1);
126         operations[h_val - 1].in_use = TFM_CRYPTO_NOT_IN_USE;
127         operations[h_val - 1].type = TFM_CRYPTO_OPERATION_NONE;
128         operations[h_val - 1].owner = 0;
129 
130         return PSA_SUCCESS;
131     }
132 
133     return PSA_ERROR_INVALID_ARGUMENT;
134 }
135 
tfm_crypto_operation_lookup(enum tfm_crypto_operation_type type,uint32_t handle,void ** ctx)136 psa_status_t tfm_crypto_operation_lookup(enum tfm_crypto_operation_type type,
137                                          uint32_t handle,
138                                          void **ctx)
139 {
140     int32_t partition_id = 0;
141     psa_status_t status;
142 
143     if ((handle == TFM_CRYPTO_INVALID_HANDLE) ||
144         (handle > CRYPTO_CONC_OPER_NUM)) {
145         return PSA_ERROR_BAD_STATE;
146     }
147 
148     if (ctx == NULL) {
149         return PSA_ERROR_INVALID_ARGUMENT;
150     }
151 
152     status = tfm_crypto_get_caller_id(&partition_id);
153     if (status != PSA_SUCCESS) {
154         return status;
155     }
156 
157     if ((operations[handle - 1].in_use == TFM_CRYPTO_IN_USE) &&
158         (operations[handle - 1].type == type) &&
159         (operations[handle - 1].owner == partition_id)) {
160         *ctx = (void *) &(operations[handle - 1].operation);
161         return PSA_SUCCESS;
162     }
163 
164     return PSA_ERROR_BAD_STATE;
165 }
166 /*!@}*/
167