blob: e8c77e90a5835795adae63ea8227887eed947f41 [file] [log] [blame]
Julian Hallc02fffb2020-11-23 18:22:06 +01001/*
2 * Copyright (c) 2020, 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/mbedcrypto/crypto_provider.h>
10#include <service/crypto/provider/serializer/crypto_provider_serializer.h>
11#include <service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h>
12#include <service/secure_storage/client/psa/its/its_client.h>
13#include <protocols/rpc/common/packed-c/status.h>
14#include <psa/crypto.h>
15
16/* Service request handlers */
17static rpc_status_t nop_handler(void *context, struct call_req* req);
18static rpc_status_t generate_key_handler(void *context, struct call_req* req);
19static rpc_status_t destroy_key_handler(void *context, struct call_req* req);
20static rpc_status_t open_key_handler(void *context, struct call_req* req);
21static rpc_status_t close_key_handler(void *context, struct call_req* req);
22static rpc_status_t export_key_handler(void *context, struct call_req* req);
23static rpc_status_t export_public_key_handler(void *context, struct call_req* req);
24static rpc_status_t import_key_handler(void *context, struct call_req* req);
25static rpc_status_t sign_hash_handler(void *context, struct call_req* req);
26static rpc_status_t verify_hash_handler(void *context, struct call_req* req);
27static rpc_status_t asymmetric_decrypt_handler(void *context, struct call_req* req);
28static rpc_status_t asymmetric_encrypt_handler(void *context, struct call_req* req);
29static rpc_status_t generate_random_handler(void *context, struct call_req* req);
30
31/* Handler mapping table for service */
32static const struct service_handler handler_table[] = {
33 {TS_CRYPTO_OPCODE_NOP, nop_handler},
34 {TS_CRYPTO_OPCODE_GENERATE_KEY, generate_key_handler},
35 {TS_CRYPTO_OPCODE_DESTROY_KEY, destroy_key_handler},
36 {TS_CRYPTO_OPCODE_OPEN_KEY, open_key_handler},
37 {TS_CRYPTO_OPCODE_CLOSE_KEY, close_key_handler},
38 {TS_CRYPTO_OPCODE_EXPORT_KEY, export_key_handler},
39 {TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY, export_public_key_handler},
40 {TS_CRYPTO_OPCODE_IMPORT_KEY, import_key_handler},
41 {TS_CRYPTO_OPCODE_SIGN_HASH, sign_hash_handler},
42 {TS_CRYPTO_OPCODE_VERIFY_HASH, verify_hash_handler},
43 {TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT, asymmetric_decrypt_handler},
44 {TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, asymmetric_encrypt_handler},
45 {TS_CRYPTO_OPCODE_GENERATE_RANDOM, generate_random_handler}
46};
47
48struct call_ep *mbed_crypto_provider_init(struct mbed_crypto_provider *context,
49 struct rpc_caller *storage_provider)
50{
51 struct call_ep *call_ep = NULL;
52
53 /*
54 * A storage provider is required for persistent key storage. As this
55 * is a mandatory feature of the crypto service, insist on a storage
56 * provider being available.
57 */
58 if (context && storage_provider) {
59
60 service_provider_init(&context->base_provider, context,
61 handler_table, sizeof(handler_table)/sizeof(struct service_handler));
62
63 service_set_default_serializer(&context->base_provider,
64 pb_crypto_provider_serializer_instance());
65
66 if ((psa_its_client_init(storage_provider) == PSA_SUCCESS) &&
67 (psa_crypto_init() == PSA_SUCCESS))
68 call_ep = service_provider_get_call_ep(&context->base_provider);
69 }
70
71 return call_ep;
72}
73
74void mbed_crypto_provider_deinit(struct mbed_crypto_provider *context)
75{
76 (void)context;
77}
78
79static inline const struct crypto_provider_serializer* get_crypto_serializer(const struct call_req *req)
80{
81 return (const struct crypto_provider_serializer*)call_req_get_serializer(req);
82}
83
84static rpc_status_t nop_handler(void *context, struct call_req* req)
85{
86 /* Responds to a request by returning success */
87 rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
88 psa_status_t psa_status = PSA_SUCCESS;
89
90 (void)context;
91 call_req_set_opstatus(req, psa_status);
92
93 return rpc_status;
94}
95
96static rpc_status_t generate_key_handler(void *context, struct call_req* req)
97{
98 rpc_status_t rpc_status;
99 struct call_param_buf *req_buf = call_req_get_req_buf(req);
100 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
101 (void)context;
102
103 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
104
105 rpc_status = serializer->deserialize_generate_key_req(req_buf, &attributes);
106
107 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
108
109 psa_status_t psa_status;
110 psa_key_handle_t handle;
111
112 psa_status = psa_generate_key(&attributes, &handle);
113
114 if (psa_status == PSA_SUCCESS) {
115
116 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
117 rpc_status = serializer->serialize_generate_key_resp(resp_buf, handle);
118 }
119
120 call_req_set_opstatus(req, psa_status);
121 }
122
123 psa_reset_key_attributes(&attributes);
124
125 return rpc_status;
126}
127
128static rpc_status_t destroy_key_handler(void *context, struct call_req* req)
129{
130 rpc_status_t rpc_status;
131 struct call_param_buf *req_buf = call_req_get_req_buf(req);
132 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
133 (void)context;
134
135 psa_key_handle_t handle;
136
137 rpc_status = serializer->deserialize_destroy_key_req(req_buf, &handle);
138
139 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
140
141 psa_status_t psa_status;
142
143 psa_status = psa_destroy_key(handle);
144 call_req_set_opstatus(req, psa_status);
145 }
146
147 return rpc_status;
148}
149
150static rpc_status_t open_key_handler(void *context, struct call_req* req)
151{
152 rpc_status_t rpc_status;
153 struct call_param_buf *req_buf = call_req_get_req_buf(req);
154 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
155 (void)context;
156
157 psa_key_id_t id;
158
159 rpc_status = serializer->deserialize_open_key_req(req_buf, &id);
160
161 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
162
163 psa_status_t psa_status;
164 psa_key_handle_t handle;
165
166 psa_status = psa_open_key(id, &handle);
167
168 if (psa_status == PSA_SUCCESS) {
169
170 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
171 rpc_status = serializer->serialize_open_key_resp(resp_buf, handle);
172 }
173
174 call_req_set_opstatus(req, psa_status);
175 }
176
177 return rpc_status;
178}
179
180static rpc_status_t close_key_handler(void *context, struct call_req* req)
181{
182 rpc_status_t rpc_status;
183 struct call_param_buf *req_buf = call_req_get_req_buf(req);
184 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
185 (void)context;
186
187 psa_key_handle_t handle;
188
189 rpc_status = serializer->deserialize_close_key_req(req_buf, &handle);
190
191 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
192
193 psa_status_t psa_status;
194
195 psa_status = psa_close_key(handle);
196 call_req_set_opstatus(req, psa_status);
197 }
198
199 return rpc_status;
200}
201
202static rpc_status_t export_key_handler(void *context, struct call_req* req)
203{
204 rpc_status_t rpc_status;
205 struct call_param_buf *req_buf = call_req_get_req_buf(req);
206 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
207 (void)context;
208
209 psa_key_handle_t handle;
210
211 rpc_status = serializer->deserialize_export_key_req(req_buf, &handle);
212
213 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
214
215 psa_status_t psa_status;
216 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
217
218 psa_status = psa_get_key_attributes(handle, &attributes);
219
220 if (psa_status == PSA_SUCCESS) {
221
222 size_t max_export_size = PSA_KEY_EXPORT_MAX_SIZE(
223 psa_get_key_type(&attributes),
224 psa_get_key_bits(&attributes));
225
226 uint8_t *key_buffer = malloc(max_export_size);
227
228 if (key_buffer) {
229
230 size_t export_size;
231 psa_status = psa_export_key(handle, key_buffer, max_export_size, &export_size);
232
233 if (psa_status == PSA_SUCCESS) {
234
235 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
236 rpc_status = serializer->serialize_export_key_resp(resp_buf, key_buffer, export_size);
237 }
238
239 free(key_buffer);
240 }
241 else {
242 /* Failed to allocate key buffer */
243 rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
244 }
245 }
246
247 call_req_set_opstatus(req, psa_status);
248 psa_reset_key_attributes(&attributes);
249 }
250
251 return rpc_status;
252}
253
254static rpc_status_t export_public_key_handler(void *context, struct call_req* req)
255{
256 rpc_status_t rpc_status;
257 struct call_param_buf *req_buf = call_req_get_req_buf(req);
258 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
259 (void)context;
260
261 psa_key_handle_t handle;
262
263 rpc_status = serializer->deserialize_export_public_key_req(req_buf, &handle);
264
265 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
266
267 psa_status_t psa_status;
268 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
269
270 psa_status = psa_get_key_attributes(handle, &attributes);
271
272 if (psa_status == PSA_SUCCESS) {
273
274 size_t max_export_size = PSA_KEY_EXPORT_MAX_SIZE(
275 PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_get_key_type(&attributes)),
276 psa_get_key_bits(&attributes));
277
278 uint8_t *key_buffer = malloc(max_export_size);
279
280 if (key_buffer) {
281
282 size_t export_size;
283 psa_status = psa_export_public_key(handle, key_buffer, max_export_size, &export_size);
284
285 if (psa_status == PSA_SUCCESS) {
286
287 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
288 rpc_status = serializer->serialize_export_public_key_resp(resp_buf, key_buffer, export_size);
289 }
290
291 free(key_buffer);
292 }
293 else {
294 /* Failed to allocate key buffer */
295 rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
296 }
297 }
298
299 call_req_set_opstatus(req, psa_status);
300 psa_reset_key_attributes(&attributes);
301 }
302
303 return rpc_status;
304}
305
306static rpc_status_t import_key_handler(void *context, struct call_req* req)
307{
308 rpc_status_t rpc_status;
309 struct call_param_buf *req_buf = call_req_get_req_buf(req);
310 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
311 (void)context;
312
313 size_t key_data_len = serializer->max_deserialised_parameter_size(req_buf);
314 uint8_t *key_buffer = malloc(key_data_len);
315
316 if (key_buffer) {
317
318 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
319 rpc_status = serializer->deserialize_import_key_req(req_buf, &attributes, key_buffer, &key_data_len);
320
321 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
322
323 psa_status_t psa_status;
324 psa_key_handle_t handle;
325
326 psa_status = psa_import_key(&attributes, key_buffer, key_data_len, &handle);
327
328 if (psa_status == PSA_SUCCESS) {
329
330 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
331 rpc_status = serializer->serialize_import_key_resp(resp_buf, handle);
332 }
333
334 call_req_set_opstatus(req, psa_status);
335 }
336
337 psa_reset_key_attributes(&attributes);
338 free(key_buffer);
339 }
340 else {
341
342 rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
343 }
344
345 return rpc_status;
346}
347
348static rpc_status_t sign_hash_handler(void *context, struct call_req* req)
349{
350 rpc_status_t rpc_status;
351 struct call_param_buf *req_buf = call_req_get_req_buf(req);
352 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
353 (void)context;
354
355 psa_key_handle_t handle;
356 psa_algorithm_t alg;
357 size_t hash_len = PSA_HASH_MAX_SIZE;
358 uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
359
360 rpc_status = serializer->deserialize_sign_hash_req(req_buf, &handle, &alg, hash_buffer, &hash_len);
361
362 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
363
364 psa_status_t psa_status;
365 size_t sig_len;
366 uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
367
368 psa_status = psa_sign_hash(handle, alg,
369 hash_buffer, hash_len,
370 sig_buffer, sizeof(sig_buffer), &sig_len);
371
372 if (psa_status == PSA_SUCCESS) {
373
374 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
375 rpc_status = serializer->serialize_sign_hash_resp(resp_buf, sig_buffer, sig_len);
376 }
377
378 call_req_set_opstatus(req, psa_status);
379 }
380
381 return rpc_status;
382}
383
384static rpc_status_t verify_hash_handler(void *context, struct call_req* req)
385{
386 rpc_status_t rpc_status;
387 struct call_param_buf *req_buf = call_req_get_req_buf(req);
388 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
389 (void)context;
390
391 psa_key_handle_t handle;
392 psa_algorithm_t alg;
393 size_t hash_len = PSA_HASH_MAX_SIZE;
394 uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
395 size_t sig_len = PSA_SIGNATURE_MAX_SIZE;
396 uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
397
398 rpc_status = serializer->deserialize_verify_hash_req(req_buf, &handle, &alg,
399 hash_buffer, &hash_len,
400 sig_buffer, &sig_len);
401
402 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
403
404 psa_status_t psa_status;
405
406 psa_status = psa_verify_hash(handle, alg,
407 hash_buffer, hash_len,
408 sig_buffer, sig_len);
409
410 call_req_set_opstatus(req, psa_status);
411 }
412
413 return rpc_status;
414}
415
416static rpc_status_t asymmetric_decrypt_handler(void *context, struct call_req* req)
417{
418 rpc_status_t rpc_status;
419 struct call_param_buf *req_buf = call_req_get_req_buf(req);
420 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
421 size_t max_param_size = serializer->max_deserialised_parameter_size(req_buf);
422 (void)context;
423
424 psa_key_handle_t handle;
425 psa_algorithm_t alg;
426 size_t ciphertext_len = max_param_size;
427 uint8_t *ciphertext_buffer = malloc(ciphertext_len);
428 size_t salt_len = max_param_size;
429 uint8_t *salt_buffer = malloc(salt_len);
430
431 if (ciphertext_buffer && salt_buffer) {
432
433 rpc_status = serializer->deserialize_asymmetric_decrypt_req(req_buf,
434 &handle, &alg,
435 ciphertext_buffer, &ciphertext_len,
436 salt_buffer, &salt_len);
437
438 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
439
440 psa_status_t psa_status;
441 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
442
443 psa_status = psa_get_key_attributes(handle, &attributes);
444
445 if (psa_status == PSA_SUCCESS) {
446
447 size_t max_decrypt_size = PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(
448 psa_get_key_type(&attributes),
449 psa_get_key_bits(&attributes),
450 alg);
451
452 size_t plaintext_len;
453 uint8_t *plaintext_buffer = malloc(max_decrypt_size);
454
455 if (plaintext_buffer) {
456
457 psa_status = psa_asymmetric_decrypt(handle, alg,
458 ciphertext_buffer, ciphertext_len,
459 salt_buffer, salt_len,
460 plaintext_buffer, max_decrypt_size, &plaintext_len);
461
462 if (psa_status == PSA_SUCCESS) {
463
464 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
465 rpc_status = serializer->serialize_asymmetric_decrypt_resp(resp_buf,
466 plaintext_buffer, plaintext_len);
467 }
468
469 free(plaintext_buffer);
470 }
471 else {
472 /* Failed to allocate ouptput buffer */
473 rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
474 }
475 }
476
477 call_req_set_opstatus(req, psa_status);
478 psa_reset_key_attributes(&attributes);
479 }
480 }
481 else {
482 /* Failed to allocate buffers */
483 rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
484 }
485
486 free(ciphertext_buffer);
487 free(salt_buffer);
488
489 return rpc_status;
490}
491
492static rpc_status_t asymmetric_encrypt_handler(void *context, struct call_req* req)
493{
494 rpc_status_t rpc_status;
495 struct call_param_buf *req_buf = call_req_get_req_buf(req);
496 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
497 size_t max_param_size = serializer->max_deserialised_parameter_size(req_buf);
498 (void)context;
499
500 psa_key_handle_t handle;
501 psa_algorithm_t alg;
502 size_t plaintext_len = max_param_size;
503 uint8_t *plaintext_buffer = malloc(plaintext_len);
504 size_t salt_len = max_param_size;
505 uint8_t *salt_buffer = malloc(salt_len);
506
507 if (plaintext_buffer && salt_buffer) {
508
509 rpc_status = serializer->deserialize_asymmetric_encrypt_req(req_buf,
510 &handle, &alg,
511 plaintext_buffer, &plaintext_len,
512 salt_buffer, &salt_len);
513
514 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
515
516 psa_status_t psa_status;
517 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
518
519 psa_status = psa_get_key_attributes(handle, &attributes);
520
521 if (psa_status == PSA_SUCCESS) {
522
523 size_t max_encrypt_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(
524 psa_get_key_type(&attributes),
525 psa_get_key_bits(&attributes),
526 alg);
527
528 size_t ciphertext_len;
529 uint8_t *ciphertext_buffer = malloc(max_encrypt_size);
530
531 if (ciphertext_buffer) {
532
533 psa_status = psa_asymmetric_encrypt(handle, alg,
534 plaintext_buffer, plaintext_len,
535 salt_buffer, salt_len,
536 ciphertext_buffer, max_encrypt_size, &ciphertext_len);
537
538 if (psa_status == PSA_SUCCESS) {
539
540 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
541 rpc_status = serializer->serialize_asymmetric_encrypt_resp(resp_buf,
542 ciphertext_buffer, ciphertext_len);
543 }
544
545 free(ciphertext_buffer);
546 }
547 else {
548 /* Failed to allocate ouptput buffer */
549 rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
550 }
551 }
552
553 call_req_set_opstatus(req, psa_status);
554 psa_reset_key_attributes(&attributes);
555 }
556 }
557 else {
558 /* Failed to allocate buffers */
559 rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
560 }
561
562 free(plaintext_buffer);
563 free(salt_buffer);
564
565 return rpc_status;
566}
567
568static rpc_status_t generate_random_handler(void *context, struct call_req* req)
569{
570 rpc_status_t rpc_status;
571 struct call_param_buf *req_buf = call_req_get_req_buf(req);
572 const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
573 (void)context;
574
575 size_t output_size;
576
577 rpc_status = serializer->deserialize_generate_random_req(req_buf, &output_size);
578
579 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
580
581 psa_status_t psa_status;
582 uint8_t *output_buffer = malloc(output_size);
583
584 if (output_buffer) {
585
586 psa_status = psa_generate_random(output_buffer, output_size);
587
588 if (psa_status == PSA_SUCCESS) {
589
590 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
591 rpc_status = serializer->serialize_generate_random_resp(resp_buf,
592 output_buffer, output_size);
593 }
594
595 call_req_set_opstatus(req, psa_status);
596 free(output_buffer);
597 }
598 else {
599 /* Failed to allocate output buffer */
600 rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
601 }
602 }
603
604 return rpc_status;
605}