1 /*
2 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <protocols/service/crypto/packed-c/opcodes.h>
9 #include <service/crypto/provider/extension/mac/mac_provider.h>
10 #include <protocols/rpc/common/packed-c/status.h>
11 #include <service/crypto/backend/crypto_backend.h>
12 #include <service/crypto/provider/crypto_partition.h>
13
14 /* Service request handlers */
15 static rpc_status_t mac_setup_handler(void *context, struct rpc_request *req);
16 static rpc_status_t mac_update_handler(void *context, struct rpc_request *req);
17 static rpc_status_t mac_sign_finish_handler(void *context, struct rpc_request *req);
18 static rpc_status_t mac_verify_finish_handler(void *context, struct rpc_request *req);
19 static rpc_status_t mac_abort_handler(void *context, struct rpc_request *req);
20
21 /* Handler mapping table for service */
22 static const struct service_handler handler_table[] = {
23 {TS_CRYPTO_OPCODE_MAC_SIGN_SETUP, mac_setup_handler},
24 {TS_CRYPTO_OPCODE_MAC_VERIFY_SETUP, mac_setup_handler},
25 {TS_CRYPTO_OPCODE_MAC_UPDATE, mac_update_handler},
26 {TS_CRYPTO_OPCODE_MAC_SIGN_FINISH, mac_sign_finish_handler},
27 {TS_CRYPTO_OPCODE_MAC_VERIFY_FINISH, mac_verify_finish_handler},
28 {TS_CRYPTO_OPCODE_MAC_ABORT, mac_abort_handler}
29 };
30
mac_provider_init(struct mac_provider * context)31 void mac_provider_init(struct mac_provider *context)
32 {
33 const struct rpc_uuid nil_uuid = { 0 };
34
35 crypto_context_pool_init(&context->context_pool);
36
37 for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
38 context->serializers[encoding] = NULL;
39
40 service_provider_init(&context->base_provider, context, &nil_uuid,
41 handler_table, sizeof(handler_table)/sizeof(struct service_handler));
42 }
43
mac_provider_deinit(struct mac_provider * context)44 void mac_provider_deinit(struct mac_provider *context)
45 {
46 crypto_context_pool_deinit(&context->context_pool);
47 }
48
mac_provider_register_serializer(struct mac_provider * context,unsigned int encoding,const struct mac_provider_serializer * serializer)49 void mac_provider_register_serializer(struct mac_provider *context,
50 unsigned int encoding, const struct mac_provider_serializer *serializer)
51 {
52 if (encoding < TS_RPC_ENCODING_LIMIT)
53 context->serializers[encoding] = serializer;
54 }
55
get_serializer(void * context,const struct rpc_request * req)56 static const struct mac_provider_serializer* get_serializer(void *context,
57 const struct rpc_request *req)
58 {
59 struct mac_provider *this_instance = (struct mac_provider*)context;
60 unsigned int encoding = 0; /* No other encodings supported */
61
62 return this_instance->serializers[encoding];
63 }
64
mac_setup_handler(void * context,struct rpc_request * req)65 static rpc_status_t mac_setup_handler(void *context, struct rpc_request *req)
66 {
67 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
68 struct rpc_buffer *req_buf = &req->request;
69 const struct mac_provider_serializer *serializer = get_serializer(context, req);
70 struct mac_provider *this_instance = (struct mac_provider*)context;
71
72 psa_key_id_t key_id;
73 psa_algorithm_t alg;
74
75 if (serializer)
76 rpc_status = serializer->deserialize_mac_setup_req(req_buf, &key_id, &alg);
77
78 if (rpc_status == RPC_SUCCESS) {
79
80 uint32_t op_handle;
81
82 struct crypto_context *crypto_context =
83 crypto_context_pool_alloc(&this_instance->context_pool,
84 CRYPTO_CONTEXT_OP_ID_MAC, req->source_id,
85 &op_handle);
86
87 if (crypto_context) {
88 namespaced_key_id_t ns_key_id =
89 crypto_partition_get_namespaced_key_id(req->source_id, key_id);
90
91 crypto_context->op.mac = psa_mac_operation_init();
92
93 psa_status_t psa_status =
94 (req->opcode == TS_CRYPTO_OPCODE_MAC_SIGN_SETUP) ?
95 psa_mac_sign_setup(&crypto_context->op.mac, ns_key_id, alg) :
96 psa_mac_verify_setup(&crypto_context->op.mac, ns_key_id, alg);
97
98 if (psa_status == PSA_SUCCESS) {
99
100 struct rpc_buffer *resp_buf = &req->response;
101 rpc_status = serializer->serialize_mac_setup_resp(resp_buf, op_handle);
102 }
103
104 if ((psa_status != PSA_SUCCESS) || (rpc_status != RPC_SUCCESS))
105 crypto_context_pool_free(&this_instance->context_pool, crypto_context);
106
107 req->service_status = psa_status;
108 }
109 else {
110 /* Failed to allocate crypto context for transaction */
111 rpc_status = RPC_ERROR_RESOURCE_FAILURE;
112 }
113 }
114
115 return rpc_status;
116 }
117
mac_update_handler(void * context,struct rpc_request * req)118 static rpc_status_t mac_update_handler(void *context, struct rpc_request *req)
119 {
120 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
121 struct rpc_buffer *req_buf = &req->request;
122 const struct mac_provider_serializer *serializer = get_serializer(context, req);
123 struct mac_provider *this_instance = (struct mac_provider*)context;
124
125 uint32_t op_handle;
126 const uint8_t *data;
127 size_t data_len;
128
129 if (serializer)
130 rpc_status = serializer->deserialize_mac_update_req(req_buf, &op_handle, &data, &data_len);
131
132 if (rpc_status == RPC_SUCCESS) {
133
134 psa_status_t psa_status = PSA_ERROR_BAD_STATE;
135
136 struct crypto_context *crypto_context =
137 crypto_context_pool_find(&this_instance->context_pool,
138 CRYPTO_CONTEXT_OP_ID_MAC, req->source_id,
139 op_handle);
140
141 if (crypto_context) {
142
143 psa_status = psa_mac_update(&crypto_context->op.mac, data, data_len);
144 }
145
146 req->service_status = psa_status;
147 }
148
149 return rpc_status;
150 }
151
mac_sign_finish_handler(void * context,struct rpc_request * req)152 static rpc_status_t mac_sign_finish_handler(void *context, struct rpc_request *req)
153 {
154 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
155 struct rpc_buffer *req_buf = &req->request;
156 const struct mac_provider_serializer *serializer = get_serializer(context, req);
157 struct mac_provider *this_instance = (struct mac_provider*)context;
158
159 uint32_t op_handle;
160
161 if (serializer)
162 rpc_status = serializer->deserialize_mac_sign_finish_req(req_buf, &op_handle);
163
164 if (rpc_status == RPC_SUCCESS) {
165
166 psa_status_t psa_status = PSA_ERROR_BAD_STATE;
167
168 struct crypto_context *crypto_context =
169 crypto_context_pool_find(&this_instance->context_pool,
170 CRYPTO_CONTEXT_OP_ID_MAC, req->source_id,
171 op_handle);
172
173 if (crypto_context) {
174
175 size_t mac_len;
176 uint8_t mac[PSA_MAC_MAX_SIZE];
177
178 psa_status = psa_mac_sign_finish(&crypto_context->op.mac, mac, sizeof(mac), &mac_len);
179
180 if (psa_status == PSA_SUCCESS) {
181
182 struct rpc_buffer *resp_buf = &req->response;
183 rpc_status = serializer->serialize_mac_sign_finish_resp(resp_buf, mac, mac_len);
184
185 crypto_context_pool_free(&this_instance->context_pool, crypto_context);
186 }
187 }
188
189 req->service_status = psa_status;
190 }
191
192 return rpc_status;
193 }
194
mac_verify_finish_handler(void * context,struct rpc_request * req)195 static rpc_status_t mac_verify_finish_handler(void *context, struct rpc_request *req)
196 {
197 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
198 struct rpc_buffer *req_buf = &req->request;
199 const struct mac_provider_serializer *serializer = get_serializer(context, req);
200 struct mac_provider *this_instance = (struct mac_provider*)context;
201
202 uint32_t op_handle;
203 const uint8_t *mac;
204 size_t mac_len;
205
206 if (serializer)
207 rpc_status = serializer->deserialize_mac_verify_finish_req(req_buf,
208 &op_handle, &mac, &mac_len);
209
210 if (rpc_status == RPC_SUCCESS) {
211
212 psa_status_t psa_status = PSA_ERROR_BAD_STATE;
213
214 struct crypto_context *crypto_context =
215 crypto_context_pool_find(&this_instance->context_pool,
216 CRYPTO_CONTEXT_OP_ID_MAC, req->source_id,
217 op_handle);
218
219 if (crypto_context) {
220
221 psa_status = psa_mac_verify_finish(&crypto_context->op.mac, mac, mac_len);
222
223 if (psa_status == PSA_SUCCESS) {
224
225 crypto_context_pool_free(&this_instance->context_pool, crypto_context);
226 }
227 }
228
229 req->service_status = psa_status;
230 }
231
232 return rpc_status;
233 }
234
mac_abort_handler(void * context,struct rpc_request * req)235 static rpc_status_t mac_abort_handler(void *context, struct rpc_request *req)
236 {
237 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
238 struct rpc_buffer *req_buf = &req->request;
239 const struct mac_provider_serializer *serializer = get_serializer(context, req);
240 struct mac_provider *this_instance = (struct mac_provider*)context;
241
242 uint32_t op_handle;
243
244 if (serializer)
245 rpc_status = serializer->deserialize_mac_abort_req(req_buf, &op_handle);
246
247 if (rpc_status == RPC_SUCCESS) {
248
249 /* Return success if operation is no longer active and
250 * doesn't need aborting.
251 */
252 psa_status_t psa_status = PSA_SUCCESS;
253
254 struct crypto_context *crypto_context =
255 crypto_context_pool_find(&this_instance->context_pool,
256 CRYPTO_CONTEXT_OP_ID_MAC, req->source_id,
257 op_handle);
258
259 if (crypto_context) {
260
261 psa_status = psa_mac_abort(&crypto_context->op.mac);
262 crypto_context_pool_free(&this_instance->context_pool, crypto_context);
263 }
264
265 req->service_status = psa_status;
266 }
267
268 return rpc_status;
269 }
270