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