1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <psa/crypto.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 
11 #include "psa/service.h"
12 #include "psa_manifest/tfm_dummy_partition.h"
13 
14 #define NUM_SECRETS 5
15 
16 struct dp_secret {
17 	uint8_t secret[16];
18 };
19 
20 struct dp_secret secrets[NUM_SECRETS] = {
21 	{ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} },
22 	{ {1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} },
23 	{ {2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} },
24 	{ {3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} },
25 	{ {4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} },
26 };
27 
28 typedef void (*psa_write_callback_t)(void *handle, uint8_t *digest,
29 				     uint32_t digest_size);
30 
tfm_dp_secret_digest(uint32_t secret_index,size_t digest_size,size_t * p_digest_size,psa_write_callback_t callback,void * handle)31 static psa_status_t tfm_dp_secret_digest(uint32_t secret_index,
32 			size_t digest_size, size_t *p_digest_size,
33 			psa_write_callback_t callback, void *handle)
34 {
35 	uint8_t digest[32];
36 	psa_status_t status;
37 
38 	/* Check that secret_index is valid. */
39 	if (secret_index >= NUM_SECRETS) {
40 		return PSA_ERROR_INVALID_ARGUMENT;
41 	}
42 
43 	/* Check that digest_size is valid. */
44 	if (digest_size != sizeof(digest)) {
45 		return PSA_ERROR_INVALID_ARGUMENT;
46 	}
47 
48 	status = psa_hash_compute(PSA_ALG_SHA_256, secrets[secret_index].secret,
49 				sizeof(secrets[secret_index].secret), digest,
50 				digest_size, p_digest_size);
51 
52 	if (status != PSA_SUCCESS) {
53 		return status;
54 	}
55 	if (*p_digest_size != digest_size) {
56 		return PSA_ERROR_PROGRAMMER_ERROR;
57 	}
58 
59 	callback(handle, digest, digest_size);
60 
61 	return PSA_SUCCESS;
62 }
63 
64 typedef psa_status_t (*dp_func_t)(psa_msg_t *);
65 
psa_write_digest(void * handle,uint8_t * digest,uint32_t digest_size)66 static void psa_write_digest(void *handle, uint8_t *digest,
67 			     uint32_t digest_size)
68 {
69 	psa_write((psa_handle_t)handle, 0, digest, digest_size);
70 }
71 
tfm_dp_secret_digest_ipc(psa_msg_t * msg)72 static psa_status_t tfm_dp_secret_digest_ipc(psa_msg_t *msg)
73 {
74 	size_t num = 0;
75 	uint32_t secret_index;
76 
77 	if (msg->in_size[0] != sizeof(secret_index)) {
78 		/* The size of the argument is incorrect */
79 		return PSA_ERROR_PROGRAMMER_ERROR;
80 	}
81 
82 	num = psa_read(msg->handle, 0, &secret_index, msg->in_size[0]);
83 	if (num != msg->in_size[0]) {
84 		return PSA_ERROR_PROGRAMMER_ERROR;
85 	}
86 
87 	return tfm_dp_secret_digest(secret_index, msg->out_size[0],
88 				    &msg->out_size[0], psa_write_digest,
89 				    (void *)msg->handle);
90 }
91 
dp_signal_handle(psa_signal_t signal,dp_func_t pfn)92 static void dp_signal_handle(psa_signal_t signal, dp_func_t pfn)
93 {
94 	psa_status_t status;
95 	psa_msg_t msg;
96 
97 	status = psa_get(signal, &msg);
98 	switch (msg.type) {
99 	case PSA_IPC_CONNECT:
100 		psa_reply(msg.handle, PSA_SUCCESS);
101 		break;
102 	case PSA_IPC_CALL:
103 		status = pfn(&msg);
104 		psa_reply(msg.handle, status);
105 		break;
106 	case PSA_IPC_DISCONNECT:
107 		psa_reply(msg.handle, PSA_SUCCESS);
108 		break;
109 	default:
110 		psa_panic();
111 	}
112 }
113 
tfm_dp_req_mngr_init(void)114 psa_status_t tfm_dp_req_mngr_init(void)
115 {
116 	psa_signal_t signals = 0;
117 
118 	while (1) {
119 		signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
120 		if (signals & TFM_DP_SECRET_DIGEST_SIGNAL) {
121 			dp_signal_handle(TFM_DP_SECRET_DIGEST_SIGNAL,
122 					 tfm_dp_secret_digest_ipc);
123 		} else {
124 			psa_panic();
125 		}
126 	}
127 
128 	return PSA_ERROR_SERVICE_FAILURE;
129 }
130