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/cipher/cipher_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 cipher_setup_handler(void *context, struct rpc_request *req);
16 static rpc_status_t cipher_generate_iv_handler(void *context, struct rpc_request *req);
17 static rpc_status_t cipher_set_iv_handler(void *context, struct rpc_request *req);
18 static rpc_status_t cipher_update_handler(void *context, struct rpc_request *req);
19 static rpc_status_t cipher_finish_handler(void *context, struct rpc_request *req);
20 static rpc_status_t cipher_abort_handler(void *context, struct rpc_request *req);
21 
22 /* Handler mapping table for service */
23 static const struct service_handler handler_table[] = {
24 	{TS_CRYPTO_OPCODE_CIPHER_ENCRYPT_SETUP,   	cipher_setup_handler},
25 	{TS_CRYPTO_OPCODE_CIPHER_DECRYPT_SETUP,   	cipher_setup_handler},
26 	{TS_CRYPTO_OPCODE_CIPHER_GENERATE_IV,   	cipher_generate_iv_handler},
27 	{TS_CRYPTO_OPCODE_CIPHER_SET_IV,   			cipher_set_iv_handler},
28 	{TS_CRYPTO_OPCODE_CIPHER_UPDATE,          	cipher_update_handler},
29 	{TS_CRYPTO_OPCODE_CIPHER_FINISH,          	cipher_finish_handler},
30 	{TS_CRYPTO_OPCODE_CIPHER_ABORT,          	cipher_abort_handler}
31 };
32 
cipher_provider_init(struct cipher_provider * context)33 void cipher_provider_init(struct cipher_provider *context)
34 {
35 	const struct rpc_uuid nil_uuid = { 0 };
36 
37 	crypto_context_pool_init(&context->context_pool);
38 
39 	for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
40 		context->serializers[encoding] = NULL;
41 
42 	service_provider_init(&context->base_provider, context, &nil_uuid,
43 		handler_table, sizeof(handler_table)/sizeof(struct service_handler));
44 }
45 
cipher_provider_deinit(struct cipher_provider * context)46 void cipher_provider_deinit(struct cipher_provider *context)
47 {
48 	crypto_context_pool_deinit(&context->context_pool);
49 }
50 
cipher_provider_register_serializer(struct cipher_provider * context,unsigned int encoding,const struct cipher_provider_serializer * serializer)51 void cipher_provider_register_serializer(struct cipher_provider *context,
52 	unsigned int encoding, const struct cipher_provider_serializer *serializer)
53 {
54 	if (encoding < TS_RPC_ENCODING_LIMIT)
55 		context->serializers[encoding] = serializer;
56 }
57 
get_serializer(void * context,const struct rpc_request * req)58 static const struct cipher_provider_serializer* get_serializer(void *context,
59 	const struct rpc_request *req)
60 {
61 	struct cipher_provider *this_instance = (struct cipher_provider*)context;
62 	unsigned int encoding = 0; /* No other encodings supported */
63 
64 	return this_instance->serializers[encoding];
65 }
66 
cipher_setup_handler(void * context,struct rpc_request * req)67 static rpc_status_t cipher_setup_handler(void *context, struct rpc_request *req)
68 {
69 	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
70 	struct rpc_buffer *req_buf = &req->request;
71 	const struct cipher_provider_serializer *serializer = get_serializer(context, req);
72 	struct cipher_provider *this_instance = (struct cipher_provider*)context;
73 
74 	psa_key_id_t key_id;
75 	psa_algorithm_t alg;
76 
77 	if (serializer)
78 		rpc_status = serializer->deserialize_cipher_setup_req(req_buf, &key_id, &alg);
79 
80 	if (rpc_status == RPC_SUCCESS) {
81 
82 		uint32_t op_handle;
83 
84 		struct crypto_context *crypto_context =
85 			crypto_context_pool_alloc(&this_instance->context_pool,
86 				CRYPTO_CONTEXT_OP_ID_CIPHER, req->source_id,
87 				&op_handle);
88 
89 		if (crypto_context) {
90 
91 			psa_status_t psa_status;
92 			namespaced_key_id_t ns_key_id =
93 				crypto_partition_get_namespaced_key_id(req->source_id, key_id);
94 
95 			crypto_context->op.cipher = psa_cipher_operation_init();
96 
97 			psa_status = (req->opcode == TS_CRYPTO_OPCODE_CIPHER_ENCRYPT_SETUP) ?
98 				psa_cipher_encrypt_setup(&crypto_context->op.cipher, ns_key_id, alg) :
99 				psa_cipher_decrypt_setup(&crypto_context->op.cipher, ns_key_id, alg);
100 
101 			if (psa_status == PSA_SUCCESS) {
102 
103 				struct rpc_buffer *resp_buf = &req->response;
104 				rpc_status = serializer->serialize_cipher_setup_resp(resp_buf, op_handle);
105 			}
106 
107 			if ((psa_status != PSA_SUCCESS) || (rpc_status != RPC_SUCCESS))
108 				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
109 
110 			req->service_status = psa_status;
111 		}
112 		else {
113 			/* Failed to allocate crypto context for transaction */
114 			rpc_status = RPC_ERROR_RESOURCE_FAILURE;
115 		}
116 	}
117 
118 	return rpc_status;
119 }
120 
cipher_generate_iv_handler(void * context,struct rpc_request * req)121 static rpc_status_t cipher_generate_iv_handler(void *context, struct rpc_request *req)
122 {
123 	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
124 	struct rpc_buffer *req_buf = &req->request;
125 	const struct cipher_provider_serializer *serializer = get_serializer(context, req);
126 	struct cipher_provider *this_instance = (struct cipher_provider*)context;
127 
128 	uint32_t op_handle;
129 
130 	if (serializer)
131 		rpc_status = serializer->deserialize_cipher_generate_iv_req(req_buf, &op_handle);
132 
133 	if (rpc_status == RPC_SUCCESS) {
134 
135 		psa_status_t psa_status = PSA_ERROR_BAD_STATE;
136 
137 		struct crypto_context *crypto_context =
138 			crypto_context_pool_find(&this_instance->context_pool,
139 				CRYPTO_CONTEXT_OP_ID_CIPHER, req->source_id,
140 				op_handle);
141 
142 		if (crypto_context) {
143 
144 			size_t iv_len;
145 			uint8_t iv[PSA_CIPHER_IV_MAX_SIZE];
146 
147 			psa_status = psa_cipher_generate_iv(&crypto_context->op.cipher, iv, sizeof(iv), &iv_len);
148 
149 			if (psa_status == PSA_SUCCESS) {
150 
151 				struct rpc_buffer *resp_buf = &req->response;
152 				rpc_status = serializer->serialize_cipher_generate_iv_resp(resp_buf, iv, iv_len);
153 			}
154 		}
155 
156 		req->service_status = psa_status;
157 	}
158 
159 	return rpc_status;
160 }
161 
cipher_set_iv_handler(void * context,struct rpc_request * req)162 static rpc_status_t cipher_set_iv_handler(void *context, struct rpc_request *req)
163 {
164 	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
165 	struct rpc_buffer *req_buf = &req->request;
166 	const struct cipher_provider_serializer *serializer = get_serializer(context, req);
167 	struct cipher_provider *this_instance = (struct cipher_provider*)context;
168 
169 	uint32_t op_handle;
170 	const uint8_t *iv;
171 	size_t iv_len;
172 
173 	if (serializer)
174 		rpc_status = serializer->deserialize_cipher_set_iv_req(req_buf, &op_handle,
175 			&iv, &iv_len);
176 
177 	if (rpc_status == RPC_SUCCESS) {
178 
179 		psa_status_t psa_status = PSA_ERROR_BAD_STATE;
180 
181 		struct crypto_context *crypto_context =
182 			crypto_context_pool_find(&this_instance->context_pool,
183 				CRYPTO_CONTEXT_OP_ID_CIPHER, req->source_id,
184 				op_handle);
185 
186 		if (crypto_context) {
187 
188 			psa_status = psa_cipher_set_iv(&crypto_context->op.cipher, iv, iv_len);
189 		}
190 
191 		req->service_status = psa_status;
192 	}
193 
194 	return rpc_status;
195 }
196 
cipher_update_handler(void * context,struct rpc_request * req)197 static rpc_status_t cipher_update_handler(void *context, struct rpc_request *req)
198 {
199 	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
200 	struct rpc_buffer *req_buf = &req->request;
201 	const struct cipher_provider_serializer *serializer = get_serializer(context, req);
202 	struct cipher_provider *this_instance = (struct cipher_provider*)context;
203 
204 	uint32_t op_handle;
205 	const uint8_t *input;
206 	size_t input_len;
207 
208 	if (serializer)
209 		rpc_status = serializer->deserialize_cipher_update_req(req_buf, &op_handle,
210 			&input, &input_len);
211 
212 	if (rpc_status == RPC_SUCCESS) {
213 
214 		psa_status_t psa_status = PSA_ERROR_BAD_STATE;
215 
216 		struct crypto_context *crypto_context =
217 			crypto_context_pool_find(&this_instance->context_pool,
218 				CRYPTO_CONTEXT_OP_ID_CIPHER, req->source_id,
219 				op_handle);
220 
221 		if (crypto_context) {
222 
223 			size_t output_len = 0;
224 			size_t output_size = PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input_len);
225 			uint8_t *output = malloc(output_size);
226 
227 			if (output) {
228 
229 				psa_status = psa_cipher_update(&crypto_context->op.cipher,
230 					input, input_len,
231 					output, output_size, &output_len);
232 
233 				if (psa_status == PSA_SUCCESS) {
234 
235 					struct rpc_buffer *resp_buf = &req->response;
236 					rpc_status = serializer->serialize_cipher_update_resp(resp_buf,
237 						output, output_len);
238 				}
239 
240 				free(output);
241 			}
242 			else {
243 
244 				psa_status = PSA_ERROR_INSUFFICIENT_MEMORY;
245 			}
246 		}
247 
248 		req->service_status = psa_status;
249 	}
250 
251 	return rpc_status;
252 }
253 
cipher_finish_handler(void * context,struct rpc_request * req)254 static rpc_status_t cipher_finish_handler(void *context, struct rpc_request *req)
255 {
256 	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
257 	struct rpc_buffer *req_buf = &req->request;
258 	const struct cipher_provider_serializer *serializer = get_serializer(context, req);
259 	struct cipher_provider *this_instance = (struct cipher_provider*)context;
260 
261 	uint32_t op_handle;
262 
263 	if (serializer)
264 		rpc_status = serializer->deserialize_cipher_finish_req(req_buf, &op_handle);
265 
266 	if (rpc_status == RPC_SUCCESS) {
267 
268 		psa_status_t psa_status = PSA_ERROR_BAD_STATE;
269 
270 		struct crypto_context *crypto_context =
271 			crypto_context_pool_find(&this_instance->context_pool,
272 				CRYPTO_CONTEXT_OP_ID_CIPHER, req->source_id,
273 				op_handle);
274 
275 		if (crypto_context) {
276 
277 			size_t output_len;
278 			uint8_t output[PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE];
279 
280 			psa_status = psa_cipher_finish(&crypto_context->op.cipher, output, sizeof(output), &output_len);
281 
282 			if (psa_status == PSA_SUCCESS) {
283 
284 				struct rpc_buffer *resp_buf = &req->response;
285 				rpc_status = serializer->serialize_cipher_finish_resp(resp_buf, output, output_len);
286 
287 				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
288 			}
289 		}
290 
291 		req->service_status = psa_status;
292 	}
293 
294 	return rpc_status;
295 }
296 
cipher_abort_handler(void * context,struct rpc_request * req)297 static rpc_status_t cipher_abort_handler(void *context, struct rpc_request *req)
298 {
299 	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
300 	struct rpc_buffer *req_buf = &req->request;
301 	const struct cipher_provider_serializer *serializer = get_serializer(context, req);
302 	struct cipher_provider *this_instance = (struct cipher_provider*)context;
303 
304 	uint32_t op_handle;
305 
306 	if (serializer)
307 		rpc_status = serializer->deserialize_cipher_abort_req(req_buf, &op_handle);
308 
309 	if (rpc_status == RPC_SUCCESS) {
310 
311 		/* Return success if operation is no longer active and
312 		 * doesn't need aborting.
313 		 */
314 		psa_status_t psa_status = PSA_SUCCESS;
315 
316 		struct crypto_context *crypto_context =
317 			crypto_context_pool_find(&this_instance->context_pool,
318 				CRYPTO_CONTEXT_OP_ID_CIPHER, req->source_id,
319 				op_handle);
320 
321 		if (crypto_context) {
322 
323 			psa_status = psa_cipher_abort(&crypto_context->op.cipher);
324 			crypto_context_pool_free(&this_instance->context_pool, crypto_context);
325 		}
326 
327 		req->service_status = psa_status;
328 	}
329 
330 	return rpc_status;
331 }
332