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