blob: c248136c2658c23c39ede669bf2d1a386cba49bb [file] [log] [blame]
Maulik Pateld3142702022-06-22 10:09:13 +01001/*
2 * Copyright (c) 2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <string.h>
9#include "measured_boot.h"
10#include "measured_boot_defs.h"
11#include "tfm_sp_log.h"
12
13#include "psa/service.h"
14#include "psa_manifest/pid.h"
15#include "psa/crypto.h"
16#include "psa_manifest/tfm_measured_boot.h"
17
18/* TODO: This info will be used later on as input to decide access control */
19static int32_t g_measured_boot_caller_id;
20
21static psa_status_t read_measurements(const psa_msg_t *msg)
22{
23 struct measured_boot_read_iovec_in_t read_iov_in;
24 struct measured_boot_read_iovec_out_t read_iov_out;
25 size_t signer_id_len, measurement_value_len;
26 size_t num;
27 size_t signer_id_size, measurement_value_size;
28 uint8_t signer_id[SIGNER_ID_MAX_SIZE] = {0};
29 uint8_t measurement_value[MEASUREMENT_VALUE_SIZE] = {0};
30 psa_status_t status;
31
32 /* store the client ID here for later use in service */
33 g_measured_boot_caller_id = msg->client_id;
34
35 signer_id_size = msg->out_size[1];
36 measurement_value_size = msg->out_size[2];
37
38 /* Check input parameter */
39 if ((msg->in_size[0] != sizeof(struct measured_boot_read_iovec_in_t)) ||
40 (msg->out_size[0] != sizeof(struct measured_boot_read_iovec_out_t))) {
41 return PSA_ERROR_PROGRAMMER_ERROR;
42 }
43
44 num = psa_read(msg->handle, 0, &read_iov_in, sizeof(read_iov_in));
45 if (num != sizeof(read_iov_in)) {
46 return PSA_ERROR_PROGRAMMER_ERROR;
47 }
48
49 /* Validate requested slot number */
50 if (read_iov_in.index >= NUM_OF_MEASUREMENT_SLOTS) {
51 return PSA_ERROR_INVALID_ARGUMENT;
52 }
53
54 memset(&read_iov_out, 0, sizeof(read_iov_out));
55
56 status = measured_boot_read_measurement(read_iov_in.index,
57 &signer_id[0],
58 signer_id_size,
59 &signer_id_len,
60 &read_iov_out.version[0],
61 read_iov_in.version_size,
62 &read_iov_out.version_len,
63 &read_iov_out.measurement_algo,
64 &read_iov_out.sw_type[0],
65 read_iov_in.sw_type_size,
66 &read_iov_out.sw_type_len,
67 &measurement_value[0],
68 measurement_value_size,
69 &measurement_value_len,
70 &read_iov_out.is_locked);
71
72 if (status == PSA_SUCCESS) {
73 psa_write(msg->handle, 0, &read_iov_out, sizeof(read_iov_out));
74 psa_write(msg->handle, 1, &signer_id[0], signer_id_len);
75 psa_write(msg->handle, 2, &measurement_value[0], measurement_value_len);
76 }
77
78 return status;
79}
80
81static psa_status_t extend_measurement(const psa_msg_t *msg)
82{
83 struct measured_boot_extend_iovec_t extend_iov;
84 size_t num;
85 size_t signer_id_size;
86 size_t version_size;
87 size_t measurement_value_size;
88 uint8_t signer_id[SIGNER_ID_MAX_SIZE] = {0};
89 uint8_t version[VERSION_MAX_SIZE] = {0};
90 uint8_t measurement_value[MEASUREMENT_VALUE_MAX_SIZE] = {0};
91
92 /* store the client ID here for later use in service */
93 g_measured_boot_caller_id = msg->client_id;
94
95 /* Check input parameter */
96 if (msg->in_size[0] != sizeof(struct measured_boot_extend_iovec_t)) {
97 return PSA_ERROR_PROGRAMMER_ERROR;
98 }
99
100 signer_id_size = msg->in_size[1];
101 version_size = msg->in_size[2];
102 measurement_value_size = msg->in_size[3];
103
104 memset(&extend_iov, 0, sizeof(extend_iov));
105 num = psa_read(msg->handle, 0, &extend_iov,
106 sizeof(struct measured_boot_extend_iovec_t));
107 if (num != sizeof(struct measured_boot_extend_iovec_t)) {
108 return PSA_ERROR_PROGRAMMER_ERROR;
109 }
110
111 /* Validate size limits of input parameters */
112 if ((signer_id_size < SIGNER_ID_MIN_SIZE) ||
113 (signer_id_size > SIGNER_ID_MAX_SIZE) ||
114 (version_size > VERSION_MAX_SIZE) ||
115 (measurement_value_size < MEASUREMENT_VALUE_MIN_SIZE) ||
116 (measurement_value_size > MEASUREMENT_VALUE_MAX_SIZE) ||
117 (extend_iov.sw_type_size > SW_TYPE_MAX_SIZE)) {
118 return PSA_ERROR_INVALID_ARGUMENT;
119 }
120
121 /* Validate requested slot number */
122 if (extend_iov.index >= NUM_OF_MEASUREMENT_SLOTS) {
123 return PSA_ERROR_INVALID_ARGUMENT;
124 }
125
126 num = psa_read(msg->handle, 1, signer_id, signer_id_size);
127 if (num != signer_id_size) {
128 return PSA_ERROR_PROGRAMMER_ERROR;
129 }
130
131 num = psa_read(msg->handle, 2, version, version_size);
132 if (num != version_size) {
133 return PSA_ERROR_PROGRAMMER_ERROR;
134 }
135
136 num = psa_read(msg->handle, 3, &measurement_value[0],
137 measurement_value_size);
138 if (num != measurement_value_size) {
139 return PSA_ERROR_PROGRAMMER_ERROR;
140 }
141
142 return measured_boot_extend_measurement(extend_iov.index,
143 signer_id,
144 signer_id_size,
145 version,
146 version_size,
147 extend_iov.measurement_algo,
148 &extend_iov.sw_type[0],
149 extend_iov.sw_type_size,
150 measurement_value,
151 measurement_value_size,
152 extend_iov.lock_measurement);
153}
154
155static void measured_boot_signal_handle(psa_signal_t signal)
156{
157 psa_status_t status;
158 psa_msg_t msg;
159
160 /* Retrieve the message corresponding to the measured_boot service signal */
161 status = psa_get(signal, &msg);
162 if (status != PSA_SUCCESS) {
163 return;
164 }
165
166 /* Decode the message */
167 switch (msg.type) {
168 case TFM_MEASURED_BOOT_READ:
169 status = read_measurements(&msg);
170 /* Reply with the message result status to unblock the client */
171 psa_reply(msg.handle, status);
172 break;
173 case TFM_MEASURED_BOOT_EXTEND:
174 status = extend_measurement(&msg);
175 /* Reply with the message result status to unblock the client */
176 psa_reply(msg.handle, status);
177 break;
178 default:
179 /* Invalid message type */
180 status = PSA_ERROR_NOT_SUPPORTED;
181 break;
182 }
183}
184
185/**
186 * \brief The measured_boot partition's entry function.
187 */
188psa_status_t tfm_measured_boot_init(void)
189{
190 psa_status_t status = PSA_SUCCESS;
191
192 /* Initialise all measurements & related metadata */
193 initialise_all_measurements();
194
195 LOG_DBGFMT("Measured Boot : selected algorithm: %x\r\n",
196 TFM_MEASURED_BOOT_HASH_ALG);
197
Jamie Fox5fb7a132022-08-01 17:26:03 +0100198#ifdef CONFIG_TFM_BOOT_STORE_MEASUREMENTS
Maulik Pateld3142702022-06-22 10:09:13 +0100199 status = collect_shared_measurements();
200#endif
201
202 if (status != PSA_SUCCESS) {
203 psa_panic();
204 }
205
206 psa_signal_t signals = 0;
207
208 while (1) {
209 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
210 if (signals & TFM_MEASURED_BOOT_SIGNAL) {
211 measured_boot_signal_handle(TFM_MEASURED_BOOT_SIGNAL);
212 } else {
213 psa_panic();
214 }
215 }
216}