1*03d6625fSDennis Ries // SPDX-License-Identifier: BSD-2-Clause
2*03d6625fSDennis Ries /*
3*03d6625fSDennis Ries * Copyright (C) 2025 Missing Link Electronics, Inc.
4*03d6625fSDennis Ries */
5*03d6625fSDennis Ries
6*03d6625fSDennis Ries #include <drivers/versal_mbox.h>
7*03d6625fSDennis Ries #include <drivers/versal_pmc.h>
8*03d6625fSDennis Ries #include <drivers/versal_ocp.h>
9*03d6625fSDennis Ries #include <kernel/panic.h>
10*03d6625fSDennis Ries #include <mm/core_memprot.h>
11*03d6625fSDennis Ries #include <stdint.h>
12*03d6625fSDennis Ries #include <string.h>
13*03d6625fSDennis Ries #include <tee_api_types.h>
14*03d6625fSDennis Ries #include <util.h>
15*03d6625fSDennis Ries
16*03d6625fSDennis Ries /* Protocol API with Versal PLM Firmware on PMC */
17*03d6625fSDennis Ries #define OCP_MODULE_SHIFT 8
18*03d6625fSDennis Ries #define OCP_MODULE 13
19*03d6625fSDennis Ries #define OCP_API_ID(_id) (SHIFT_U32(OCP_MODULE, OCP_MODULE_SHIFT) | (_id))
20*03d6625fSDennis Ries
21*03d6625fSDennis Ries /*
22*03d6625fSDennis Ries * The following symbols/types/definitions are taken from AMD/Xilinx
23*03d6625fSDennis Ries * embeddedsw::lib/sw_services/xilocp/src/common/xocp_def.h
24*03d6625fSDennis Ries * v2024.2
25*03d6625fSDennis Ries */
26*03d6625fSDennis Ries
27*03d6625fSDennis Ries enum versal_ocp_api_id {
28*03d6625fSDennis Ries API_FEATURES = 0,
29*03d6625fSDennis Ries EXTEND_HWPCR = 1,
30*03d6625fSDennis Ries GET_HWPCR = 2,
31*03d6625fSDennis Ries GET_HWPCRLOG = 3,
32*03d6625fSDennis Ries GENDMERESP = 4,
33*03d6625fSDennis Ries DEVAKINPUT = 5,
34*03d6625fSDennis Ries GETCERTUSERCFG = 6,
35*03d6625fSDennis Ries GETX509CERT = 7,
36*03d6625fSDennis Ries ATTESTWITHDEVAK = 8,
37*03d6625fSDennis Ries SET_SWPCRCONFIG = 9,
38*03d6625fSDennis Ries EXTEND_SWPCR = 10,
39*03d6625fSDennis Ries GET_SWPCR = 11,
40*03d6625fSDennis Ries GET_SWPCRLOG = 12,
41*03d6625fSDennis Ries GET_SWPCRDATA = 13,
42*03d6625fSDennis Ries GEN_SHARED_SECRET = 14,
43*03d6625fSDennis Ries ATTEST_WITH_KEYWRAP_DEVAK = 15,
44*03d6625fSDennis Ries API_MAX = 16
45*03d6625fSDennis Ries };
46*03d6625fSDennis Ries
47*03d6625fSDennis Ries #define VERSAL_OCP_EXTENDED_HASH_SIZE_IN_BYTES 48
48*03d6625fSDennis Ries
49*03d6625fSDennis Ries /*
50*03d6625fSDennis Ries * The following symbols/types/definitions are taken from AMD/Xilinx
51*03d6625fSDennis Ries * embeddedsw::lib/sw_services/xilocp/src/common/xocp_common.h
52*03d6625fSDennis Ries * v2024.2
53*03d6625fSDennis Ries */
54*03d6625fSDennis Ries
55*03d6625fSDennis Ries struct versal_ocp_swpcr_extend_params {
56*03d6625fSDennis Ries uint32_t pcr_num;
57*03d6625fSDennis Ries uint32_t measurement_idx;
58*03d6625fSDennis Ries uint32_t data_size;
59*03d6625fSDennis Ries uint32_t overwrite;
60*03d6625fSDennis Ries uint64_t data_addr;
61*03d6625fSDennis Ries };
62*03d6625fSDennis Ries
63*03d6625fSDennis Ries struct versal_ocp_swpcr_log_read_data {
64*03d6625fSDennis Ries uint32_t pcr_num;
65*03d6625fSDennis Ries uint32_t log_size;
66*03d6625fSDennis Ries uint64_t pcr_log_addr;
67*03d6625fSDennis Ries uint32_t digest_count;
68*03d6625fSDennis Ries };
69*03d6625fSDennis Ries
70*03d6625fSDennis Ries struct versal_ocp_swpcr_read_data {
71*03d6625fSDennis Ries uint32_t pcr_num;
72*03d6625fSDennis Ries uint32_t measurement_idx;
73*03d6625fSDennis Ries uint32_t data_start_idx;
74*03d6625fSDennis Ries uint32_t buf_size;
75*03d6625fSDennis Ries uint64_t buf_addr;
76*03d6625fSDennis Ries uint32_t returned_bytes;
77*03d6625fSDennis Ries };
78*03d6625fSDennis Ries
79*03d6625fSDennis Ries struct versal_ocp_x509_cert {
80*03d6625fSDennis Ries uint64_t cert_addr;
81*03d6625fSDennis Ries uint64_t actual_len_addr;
82*03d6625fSDennis Ries uint32_t cert_size;
83*03d6625fSDennis Ries enum versal_ocp_dev_key dev_key_sel;
84*03d6625fSDennis Ries uint32_t is_csr;
85*03d6625fSDennis Ries };
86*03d6625fSDennis Ries
87*03d6625fSDennis Ries struct versal_ocp_attest {
88*03d6625fSDennis Ries uint64_t hash_addr;
89*03d6625fSDennis Ries uint64_t signature_addr;
90*03d6625fSDennis Ries uint32_t reserved;
91*03d6625fSDennis Ries uint32_t hash_len;
92*03d6625fSDennis Ries };
93*03d6625fSDennis Ries
94*03d6625fSDennis Ries /*
95*03d6625fSDennis Ries * The following helper functions shall be regarded as a possible general API
96*03d6625fSDennis Ries * towards constructing "struct versal_ipi_cmd" instances. After extracting them
97*03d6625fSDennis Ries * into a separate drivers/ file, like drivers/versal_ipi_cmd.c, they may be
98*03d6625fSDennis Ries * used by other existing drivers in the future, too. For now, they shall live
99*03d6625fSDennis Ries * here, since versal_ocp.c is the only user [1].
100*03d6625fSDennis Ries *
101*03d6625fSDennis Ries * [1] https://github.com/OP-TEE/optee_os/pull/7726#issuecomment-4237954478
102*03d6625fSDennis Ries */
103*03d6625fSDennis Ries
versal_ipi_cmd_ibuf_alloc(struct versal_ipi_cmd * cmd,void * buf,size_t len,size_t * idx)104*03d6625fSDennis Ries static TEE_Result versal_ipi_cmd_ibuf_alloc(struct versal_ipi_cmd *cmd,
105*03d6625fSDennis Ries void *buf, size_t len, size_t *idx)
106*03d6625fSDennis Ries {
107*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
108*03d6625fSDennis Ries struct versal_mbox_mem mem = {};
109*03d6625fSDennis Ries
110*03d6625fSDennis Ries if (cmd->ibuf_count >= VERSAL_MAX_IPI_BUF)
111*03d6625fSDennis Ries panic();
112*03d6625fSDennis Ries
113*03d6625fSDennis Ries ret = versal_mbox_alloc(len, buf, &mem);
114*03d6625fSDennis Ries if (ret)
115*03d6625fSDennis Ries return ret;
116*03d6625fSDennis Ries
117*03d6625fSDennis Ries cmd->ibuf[cmd->ibuf_count].mem = mem;
118*03d6625fSDennis Ries if (idx)
119*03d6625fSDennis Ries *idx = cmd->ibuf_count;
120*03d6625fSDennis Ries cmd->ibuf_count++;
121*03d6625fSDennis Ries return ret;
122*03d6625fSDennis Ries }
123*03d6625fSDennis Ries
versal_ipi_cmd_free(struct versal_ipi_cmd * cmd)124*03d6625fSDennis Ries static void versal_ipi_cmd_free(struct versal_ipi_cmd *cmd)
125*03d6625fSDennis Ries {
126*03d6625fSDennis Ries memset(cmd->data, 0, sizeof(cmd->data));
127*03d6625fSDennis Ries cmd->data_count = 0;
128*03d6625fSDennis Ries
129*03d6625fSDennis Ries for (size_t idx = 0; idx < cmd->ibuf_count; idx++)
130*03d6625fSDennis Ries versal_mbox_free(&cmd->ibuf[idx].mem);
131*03d6625fSDennis Ries cmd->ibuf_count = 0;
132*03d6625fSDennis Ries }
133*03d6625fSDennis Ries
versal_ipi_cmd_data_push_val(struct versal_ipi_cmd * cmd,uint32_t val)134*03d6625fSDennis Ries static void versal_ipi_cmd_data_push_val(struct versal_ipi_cmd *cmd,
135*03d6625fSDennis Ries uint32_t val)
136*03d6625fSDennis Ries {
137*03d6625fSDennis Ries if (cmd->data_count >= VERSAL_MAX_IPI_DATA)
138*03d6625fSDennis Ries panic();
139*03d6625fSDennis Ries
140*03d6625fSDennis Ries cmd->data[cmd->data_count++] = val;
141*03d6625fSDennis Ries }
142*03d6625fSDennis Ries
versal_ipi_cmd_data_push_ptr(struct versal_ipi_cmd * cmd,void * ptr)143*03d6625fSDennis Ries static void versal_ipi_cmd_data_push_ptr(struct versal_ipi_cmd *cmd, void *ptr)
144*03d6625fSDennis Ries {
145*03d6625fSDennis Ries uint32_t low = 0;
146*03d6625fSDennis Ries uint32_t hi = 0;
147*03d6625fSDennis Ries
148*03d6625fSDennis Ries if (cmd->data_count >= (VERSAL_MAX_IPI_DATA - 1))
149*03d6625fSDennis Ries panic();
150*03d6625fSDennis Ries
151*03d6625fSDennis Ries reg_pair_from_64(virt_to_phys(ptr), &hi, &low);
152*03d6625fSDennis Ries cmd->data[cmd->data_count++] = low;
153*03d6625fSDennis Ries cmd->data[cmd->data_count++] = hi;
154*03d6625fSDennis Ries }
155*03d6625fSDennis Ries
versal_ipi_cmd_data_push_ibuf(struct versal_ipi_cmd * cmd,void * buf,size_t len,size_t * idx)156*03d6625fSDennis Ries static TEE_Result versal_ipi_cmd_data_push_ibuf(struct versal_ipi_cmd *cmd,
157*03d6625fSDennis Ries void *buf, size_t len,
158*03d6625fSDennis Ries size_t *idx)
159*03d6625fSDennis Ries {
160*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
161*03d6625fSDennis Ries size_t target_idx = 0;
162*03d6625fSDennis Ries
163*03d6625fSDennis Ries if (cmd->ibuf_count >= VERSAL_MAX_IPI_BUF)
164*03d6625fSDennis Ries panic();
165*03d6625fSDennis Ries if (cmd->data_count >= (VERSAL_MAX_IPI_DATA - 1))
166*03d6625fSDennis Ries panic();
167*03d6625fSDennis Ries
168*03d6625fSDennis Ries ret = versal_ipi_cmd_ibuf_alloc(cmd, buf, len, &target_idx);
169*03d6625fSDennis Ries if (ret)
170*03d6625fSDennis Ries return ret;
171*03d6625fSDennis Ries
172*03d6625fSDennis Ries if (idx)
173*03d6625fSDennis Ries *idx = target_idx;
174*03d6625fSDennis Ries
175*03d6625fSDennis Ries versal_ipi_cmd_data_push_ptr(cmd, cmd->ibuf[target_idx].mem.buf);
176*03d6625fSDennis Ries return ret;
177*03d6625fSDennis Ries }
178*03d6625fSDennis Ries
versal_ipi_cmd_ibuf_get(struct versal_ipi_cmd * cmd,size_t idx)179*03d6625fSDennis Ries static void *versal_ipi_cmd_ibuf_get(struct versal_ipi_cmd *cmd, size_t idx)
180*03d6625fSDennis Ries {
181*03d6625fSDennis Ries if (idx >= cmd->ibuf_count)
182*03d6625fSDennis Ries panic();
183*03d6625fSDennis Ries
184*03d6625fSDennis Ries return cmd->ibuf[idx].mem.buf;
185*03d6625fSDennis Ries }
186*03d6625fSDennis Ries
versal_ipi_cmd_ibuf_get_paddr(struct versal_ipi_cmd * cmd,size_t idx)187*03d6625fSDennis Ries static paddr_t versal_ipi_cmd_ibuf_get_paddr(struct versal_ipi_cmd *cmd,
188*03d6625fSDennis Ries size_t idx)
189*03d6625fSDennis Ries {
190*03d6625fSDennis Ries if (idx >= cmd->ibuf_count)
191*03d6625fSDennis Ries panic();
192*03d6625fSDennis Ries
193*03d6625fSDennis Ries return virt_to_phys(cmd->ibuf[idx].mem.buf);
194*03d6625fSDennis Ries }
195*03d6625fSDennis Ries
versal_ipi_cmd_ibuf_fetch(struct versal_ipi_cmd * cmd,void * dst,size_t len,size_t idx)196*03d6625fSDennis Ries static void versal_ipi_cmd_ibuf_fetch(struct versal_ipi_cmd *cmd,
197*03d6625fSDennis Ries void *dst, size_t len, size_t idx)
198*03d6625fSDennis Ries {
199*03d6625fSDennis Ries if (idx >= cmd->ibuf_count)
200*03d6625fSDennis Ries panic();
201*03d6625fSDennis Ries if (len > cmd->ibuf[idx].mem.len)
202*03d6625fSDennis Ries panic();
203*03d6625fSDennis Ries
204*03d6625fSDennis Ries memcpy(dst, cmd->ibuf[idx].mem.buf, len);
205*03d6625fSDennis Ries }
206*03d6625fSDennis Ries
207*03d6625fSDennis Ries /*
208*03d6625fSDennis Ries * The following functions shall mimic the XilOCP client side interface from
209*03d6625fSDennis Ries * AMD/Xilinx embeddedsw::lib/sw_services/xilocp/src/client/xocp_client.h
210*03d6625fSDennis Ries * v2024.2
211*03d6625fSDennis Ries */
212*03d6625fSDennis Ries
213*03d6625fSDennis Ries /* capture PLM status/error code */
214*03d6625fSDennis Ries static uint32_t plm_status;
215*03d6625fSDennis Ries struct mutex plm_status_lock = MUTEX_INITIALIZER;
216*03d6625fSDennis Ries
versal_ocp_plm_status_get(void)217*03d6625fSDennis Ries uint32_t versal_ocp_plm_status_get(void)
218*03d6625fSDennis Ries {
219*03d6625fSDennis Ries uint32_t status = 0;
220*03d6625fSDennis Ries
221*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
222*03d6625fSDennis Ries status = plm_status;
223*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
224*03d6625fSDennis Ries
225*03d6625fSDennis Ries return status;
226*03d6625fSDennis Ries }
227*03d6625fSDennis Ries
versal_ocp_status_get(void)228*03d6625fSDennis Ries uint32_t versal_ocp_status_get(void)
229*03d6625fSDennis Ries {
230*03d6625fSDennis Ries return versal_ocp_plm_status_get() & VERSAL_OCP_STATUS_MASK;
231*03d6625fSDennis Ries }
232*03d6625fSDennis Ries
versal_ocp_extend_hwpcr(enum versal_ocp_hwpcr pcr_num,void * data,uint32_t data_size)233*03d6625fSDennis Ries TEE_Result versal_ocp_extend_hwpcr(enum versal_ocp_hwpcr pcr_num,
234*03d6625fSDennis Ries void *data, uint32_t data_size)
235*03d6625fSDennis Ries {
236*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
237*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
238*03d6625fSDennis Ries
239*03d6625fSDennis Ries if (!data || !data_size)
240*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
241*03d6625fSDennis Ries
242*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(EXTEND_HWPCR));
243*03d6625fSDennis Ries
244*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, pcr_num);
245*03d6625fSDennis Ries
246*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, data, data_size, NULL);
247*03d6625fSDennis Ries if (ret)
248*03d6625fSDennis Ries goto out;
249*03d6625fSDennis Ries
250*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, data_size);
251*03d6625fSDennis Ries
252*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
253*03d6625fSDennis Ries plm_status = 0;
254*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
255*03d6625fSDennis Ries EMSG("Versal PLM API ID EXTEND_HWPCR failed: 0x%" PRIx32,
256*03d6625fSDennis Ries plm_status);
257*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
258*03d6625fSDennis Ries }
259*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
260*03d6625fSDennis Ries
261*03d6625fSDennis Ries out:
262*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
263*03d6625fSDennis Ries return ret;
264*03d6625fSDennis Ries }
265*03d6625fSDennis Ries
versal_ocp_get_hwpcr(uint32_t pcr_mask,void * pcr,uint32_t pcr_size)266*03d6625fSDennis Ries TEE_Result versal_ocp_get_hwpcr(uint32_t pcr_mask,
267*03d6625fSDennis Ries void *pcr, uint32_t pcr_size)
268*03d6625fSDennis Ries {
269*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
270*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
271*03d6625fSDennis Ries size_t idx = 0;
272*03d6625fSDennis Ries
273*03d6625fSDennis Ries if (!pcr || !pcr_size)
274*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
275*03d6625fSDennis Ries
276*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(GET_HWPCR));
277*03d6625fSDennis Ries
278*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, pcr_mask);
279*03d6625fSDennis Ries
280*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, NULL, pcr_size, &idx);
281*03d6625fSDennis Ries if (ret)
282*03d6625fSDennis Ries goto out;
283*03d6625fSDennis Ries
284*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, pcr_size);
285*03d6625fSDennis Ries
286*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
287*03d6625fSDennis Ries plm_status = 0;
288*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
289*03d6625fSDennis Ries EMSG("Versal PLM API ID GET_HWPCR failed: 0x%" PRIx32,
290*03d6625fSDennis Ries plm_status);
291*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
292*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
293*03d6625fSDennis Ries goto out;
294*03d6625fSDennis Ries }
295*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
296*03d6625fSDennis Ries
297*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, pcr, pcr_size, idx);
298*03d6625fSDennis Ries
299*03d6625fSDennis Ries out:
300*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
301*03d6625fSDennis Ries return ret;
302*03d6625fSDennis Ries }
303*03d6625fSDennis Ries
versal_ocp_get_hwpcr_log(struct versal_ocp_hwpcr_event * events,uint32_t events_size,struct versal_ocp_hwpcr_log_info * loginfo)304*03d6625fSDennis Ries TEE_Result versal_ocp_get_hwpcr_log(struct versal_ocp_hwpcr_event *events,
305*03d6625fSDennis Ries uint32_t events_size,
306*03d6625fSDennis Ries struct versal_ocp_hwpcr_log_info *loginfo)
307*03d6625fSDennis Ries {
308*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
309*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
310*03d6625fSDennis Ries size_t idx_events = 0;
311*03d6625fSDennis Ries size_t idx_loginfo = 0;
312*03d6625fSDennis Ries
313*03d6625fSDennis Ries if (!events || !events_size || (events_size % sizeof(*events)))
314*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
315*03d6625fSDennis Ries if (!loginfo)
316*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
317*03d6625fSDennis Ries
318*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(GET_HWPCRLOG));
319*03d6625fSDennis Ries
320*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, NULL, events_size,
321*03d6625fSDennis Ries &idx_events);
322*03d6625fSDennis Ries if (ret)
323*03d6625fSDennis Ries goto out;
324*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, NULL, sizeof(*loginfo),
325*03d6625fSDennis Ries &idx_loginfo);
326*03d6625fSDennis Ries if (ret)
327*03d6625fSDennis Ries goto out;
328*03d6625fSDennis Ries
329*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, events_size / sizeof(*events));
330*03d6625fSDennis Ries
331*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
332*03d6625fSDennis Ries plm_status = 0;
333*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
334*03d6625fSDennis Ries EMSG("Versal PLM API ID GET_HWPCRLOG failed: 0x%" PRIx32,
335*03d6625fSDennis Ries plm_status);
336*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
337*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
338*03d6625fSDennis Ries goto out;
339*03d6625fSDennis Ries }
340*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
341*03d6625fSDennis Ries
342*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, loginfo, sizeof(*loginfo), idx_loginfo);
343*03d6625fSDennis Ries
344*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, events, events_size, idx_events);
345*03d6625fSDennis Ries
346*03d6625fSDennis Ries out:
347*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
348*03d6625fSDennis Ries return ret;
349*03d6625fSDennis Ries }
350*03d6625fSDennis Ries
versal_ocp_extend_swpcr(uint32_t pcr_num,void * data,uint32_t data_size,uint32_t measurement_idx,bool overwrite)351*03d6625fSDennis Ries TEE_Result versal_ocp_extend_swpcr(uint32_t pcr_num,
352*03d6625fSDennis Ries void *data, uint32_t data_size,
353*03d6625fSDennis Ries uint32_t measurement_idx, bool overwrite)
354*03d6625fSDennis Ries {
355*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
356*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
357*03d6625fSDennis Ries struct versal_ocp_swpcr_extend_params params = {
358*03d6625fSDennis Ries .pcr_num = pcr_num,
359*03d6625fSDennis Ries .measurement_idx = measurement_idx,
360*03d6625fSDennis Ries .data_size = data_size,
361*03d6625fSDennis Ries .overwrite = overwrite,
362*03d6625fSDennis Ries .data_addr = 0,
363*03d6625fSDennis Ries };
364*03d6625fSDennis Ries size_t idx = 0;
365*03d6625fSDennis Ries
366*03d6625fSDennis Ries if (!data || !data_size)
367*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
368*03d6625fSDennis Ries
369*03d6625fSDennis Ries /*
370*03d6625fSDennis Ries * NOTE: AMD/Xilinx XilOCP client side code does this check explicitly
371*03d6625fSDennis Ries * before calling into PLM Firmware. Despite checking it again in
372*03d6625fSDennis Ries * PLM Firmware. It looks like hardware can handle data buffers
373*03d6625fSDennis Ries * beyond 48 Bytes, only, if within the first 4GiB of
374*03d6625fSDennis Ries * RAM. Probably some kind of DMA engine issue ...?
375*03d6625fSDennis Ries */
376*03d6625fSDennis Ries if (data_size > VERSAL_OCP_EXTENDED_HASH_SIZE_IN_BYTES)
377*03d6625fSDennis Ries if ((vaddr_t)data >> 32)
378*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
379*03d6625fSDennis Ries
380*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(EXTEND_SWPCR));
381*03d6625fSDennis Ries
382*03d6625fSDennis Ries ret = versal_ipi_cmd_ibuf_alloc(&cmd, data, data_size, &idx);
383*03d6625fSDennis Ries if (ret)
384*03d6625fSDennis Ries goto out;
385*03d6625fSDennis Ries
386*03d6625fSDennis Ries params.data_addr = (uint64_t)versal_ipi_cmd_ibuf_get_paddr(&cmd, idx);
387*03d6625fSDennis Ries
388*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, ¶ms, sizeof(params),
389*03d6625fSDennis Ries NULL);
390*03d6625fSDennis Ries if (ret)
391*03d6625fSDennis Ries goto out;
392*03d6625fSDennis Ries
393*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
394*03d6625fSDennis Ries plm_status = 0;
395*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
396*03d6625fSDennis Ries EMSG("Versal PLM API ID EXTEND_SWPCR failed: 0x%" PRIx32,
397*03d6625fSDennis Ries plm_status);
398*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
399*03d6625fSDennis Ries }
400*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
401*03d6625fSDennis Ries
402*03d6625fSDennis Ries out:
403*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
404*03d6625fSDennis Ries return ret;
405*03d6625fSDennis Ries }
406*03d6625fSDennis Ries
versal_ocp_get_swpcr(uint32_t pcr_mask,void * pcr,uint32_t pcr_size)407*03d6625fSDennis Ries TEE_Result versal_ocp_get_swpcr(uint32_t pcr_mask,
408*03d6625fSDennis Ries void *pcr, uint32_t pcr_size)
409*03d6625fSDennis Ries {
410*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
411*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
412*03d6625fSDennis Ries size_t idx = 0;
413*03d6625fSDennis Ries
414*03d6625fSDennis Ries if (!pcr || !pcr_size)
415*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
416*03d6625fSDennis Ries
417*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(GET_SWPCR));
418*03d6625fSDennis Ries
419*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, pcr_mask);
420*03d6625fSDennis Ries
421*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, NULL, pcr_size, &idx);
422*03d6625fSDennis Ries if (ret)
423*03d6625fSDennis Ries goto out;
424*03d6625fSDennis Ries
425*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, pcr_size);
426*03d6625fSDennis Ries
427*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
428*03d6625fSDennis Ries plm_status = 0;
429*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
430*03d6625fSDennis Ries EMSG("Versal PLM API ID GET_SWPCR failed: 0x%" PRIx32,
431*03d6625fSDennis Ries plm_status);
432*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
433*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
434*03d6625fSDennis Ries goto out;
435*03d6625fSDennis Ries }
436*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
437*03d6625fSDennis Ries
438*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, pcr, pcr_size, idx);
439*03d6625fSDennis Ries
440*03d6625fSDennis Ries out:
441*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
442*03d6625fSDennis Ries return ret;
443*03d6625fSDennis Ries }
444*03d6625fSDennis Ries
versal_ocp_get_swpcr_data(uint32_t pcr_num,uint32_t measurement_idx,uint32_t data_start_idx,void * data,uint32_t data_size,uint32_t * data_returned)445*03d6625fSDennis Ries TEE_Result versal_ocp_get_swpcr_data(uint32_t pcr_num, uint32_t measurement_idx,
446*03d6625fSDennis Ries uint32_t data_start_idx,
447*03d6625fSDennis Ries void *data, uint32_t data_size,
448*03d6625fSDennis Ries uint32_t *data_returned)
449*03d6625fSDennis Ries {
450*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
451*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
452*03d6625fSDennis Ries struct versal_ocp_swpcr_read_data param = {
453*03d6625fSDennis Ries .pcr_num = pcr_num,
454*03d6625fSDennis Ries .measurement_idx = measurement_idx,
455*03d6625fSDennis Ries .data_start_idx = data_start_idx,
456*03d6625fSDennis Ries .buf_size = data_size,
457*03d6625fSDennis Ries .buf_addr = 0,
458*03d6625fSDennis Ries .returned_bytes = 0,
459*03d6625fSDennis Ries };
460*03d6625fSDennis Ries size_t idx_buf = 0;
461*03d6625fSDennis Ries size_t idx_param = 0;
462*03d6625fSDennis Ries struct versal_ocp_swpcr_read_data *_param = NULL;
463*03d6625fSDennis Ries
464*03d6625fSDennis Ries if (!data || !data_size || !data_returned)
465*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
466*03d6625fSDennis Ries
467*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(GET_SWPCRDATA));
468*03d6625fSDennis Ries
469*03d6625fSDennis Ries ret = versal_ipi_cmd_ibuf_alloc(&cmd, NULL, data_size, &idx_buf);
470*03d6625fSDennis Ries if (ret)
471*03d6625fSDennis Ries goto out;
472*03d6625fSDennis Ries
473*03d6625fSDennis Ries param.buf_addr = versal_ipi_cmd_ibuf_get_paddr(&cmd, idx_buf);
474*03d6625fSDennis Ries
475*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, ¶m, sizeof(param),
476*03d6625fSDennis Ries &idx_param);
477*03d6625fSDennis Ries if (ret)
478*03d6625fSDennis Ries goto out;
479*03d6625fSDennis Ries
480*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
481*03d6625fSDennis Ries plm_status = 0;
482*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
483*03d6625fSDennis Ries EMSG("Versal PLM API ID GET_SWPCRDATA failed: 0x%" PRIx32,
484*03d6625fSDennis Ries plm_status);
485*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
486*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
487*03d6625fSDennis Ries goto out;
488*03d6625fSDennis Ries }
489*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
490*03d6625fSDennis Ries
491*03d6625fSDennis Ries _param = versal_ipi_cmd_ibuf_get(&cmd, idx_param);
492*03d6625fSDennis Ries *data_returned = _param->returned_bytes;
493*03d6625fSDennis Ries
494*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, data, *data_returned, idx_buf);
495*03d6625fSDennis Ries
496*03d6625fSDennis Ries out:
497*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
498*03d6625fSDennis Ries return ret;
499*03d6625fSDennis Ries }
500*03d6625fSDennis Ries
501*03d6625fSDennis Ries TEE_Result
versal_ocp_get_swpcr_log(uint32_t pcr_num,struct versal_ocp_pcr_measurement * measurements,uint32_t measurements_size,uint32_t * measurements_count)502*03d6625fSDennis Ries versal_ocp_get_swpcr_log(uint32_t pcr_num,
503*03d6625fSDennis Ries struct versal_ocp_pcr_measurement *measurements,
504*03d6625fSDennis Ries uint32_t measurements_size,
505*03d6625fSDennis Ries uint32_t *measurements_count)
506*03d6625fSDennis Ries {
507*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
508*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
509*03d6625fSDennis Ries struct versal_ocp_swpcr_log_read_data param = {
510*03d6625fSDennis Ries .pcr_num = pcr_num,
511*03d6625fSDennis Ries .log_size = measurements_size,
512*03d6625fSDennis Ries .pcr_log_addr = 0,
513*03d6625fSDennis Ries .digest_count = 0,
514*03d6625fSDennis Ries };
515*03d6625fSDennis Ries size_t idx_buf = 0;
516*03d6625fSDennis Ries size_t idx_param = 0;
517*03d6625fSDennis Ries struct versal_ocp_swpcr_log_read_data *_param = NULL;
518*03d6625fSDennis Ries
519*03d6625fSDennis Ries if (!measurements || !measurements_size ||
520*03d6625fSDennis Ries (measurements_size % sizeof(struct versal_ocp_pcr_measurement)))
521*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
522*03d6625fSDennis Ries
523*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(GET_SWPCRLOG));
524*03d6625fSDennis Ries
525*03d6625fSDennis Ries ret = versal_ipi_cmd_ibuf_alloc(&cmd, NULL, measurements_size,
526*03d6625fSDennis Ries &idx_buf);
527*03d6625fSDennis Ries if (ret)
528*03d6625fSDennis Ries goto out;
529*03d6625fSDennis Ries
530*03d6625fSDennis Ries param.pcr_log_addr = versal_ipi_cmd_ibuf_get_paddr(&cmd, idx_buf);
531*03d6625fSDennis Ries
532*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, ¶m, sizeof(param),
533*03d6625fSDennis Ries &idx_param);
534*03d6625fSDennis Ries if (ret)
535*03d6625fSDennis Ries goto out;
536*03d6625fSDennis Ries
537*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
538*03d6625fSDennis Ries plm_status = 0;
539*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
540*03d6625fSDennis Ries EMSG("Versal PLM API ID GET_SWPCRLOG failed: 0x%" PRIx32,
541*03d6625fSDennis Ries plm_status);
542*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
543*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
544*03d6625fSDennis Ries goto out;
545*03d6625fSDennis Ries }
546*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
547*03d6625fSDennis Ries
548*03d6625fSDennis Ries _param = versal_ipi_cmd_ibuf_get(&cmd, idx_param);
549*03d6625fSDennis Ries *measurements_count = _param->digest_count;
550*03d6625fSDennis Ries
551*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, measurements,
552*03d6625fSDennis Ries sizeof(*measurements) * *measurements_count,
553*03d6625fSDennis Ries idx_buf);
554*03d6625fSDennis Ries
555*03d6625fSDennis Ries out:
556*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
557*03d6625fSDennis Ries return ret;
558*03d6625fSDennis Ries }
559*03d6625fSDennis Ries
versal_ocp_gen_dme_resp(void * nonce,uint32_t nonce_size,struct versal_ocp_dme_response * response)560*03d6625fSDennis Ries TEE_Result versal_ocp_gen_dme_resp(void *nonce, uint32_t nonce_size,
561*03d6625fSDennis Ries struct versal_ocp_dme_response *response)
562*03d6625fSDennis Ries {
563*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
564*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
565*03d6625fSDennis Ries size_t idx = 0;
566*03d6625fSDennis Ries
567*03d6625fSDennis Ries if (!nonce || nonce_size != VERSAL_OCP_DME_NONCE_SIZE_BYTES)
568*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
569*03d6625fSDennis Ries
570*03d6625fSDennis Ries if (!response)
571*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
572*03d6625fSDennis Ries
573*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(GENDMERESP));
574*03d6625fSDennis Ries
575*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, nonce, nonce_size, NULL);
576*03d6625fSDennis Ries if (ret)
577*03d6625fSDennis Ries goto out;
578*03d6625fSDennis Ries
579*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, NULL, sizeof(*response),
580*03d6625fSDennis Ries &idx);
581*03d6625fSDennis Ries if (ret)
582*03d6625fSDennis Ries goto out;
583*03d6625fSDennis Ries
584*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
585*03d6625fSDennis Ries plm_status = 0;
586*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
587*03d6625fSDennis Ries EMSG("Versal PLM API ID GENDMERESP failed: 0x%" PRIx32,
588*03d6625fSDennis Ries plm_status);
589*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
590*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
591*03d6625fSDennis Ries goto out;
592*03d6625fSDennis Ries }
593*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
594*03d6625fSDennis Ries
595*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, response, sizeof(*response), idx);
596*03d6625fSDennis Ries
597*03d6625fSDennis Ries out:
598*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
599*03d6625fSDennis Ries return ret;
600*03d6625fSDennis Ries }
601*03d6625fSDennis Ries
versal_ocp_get_x509_cert(void * cert,uint32_t cert_size,uint32_t * actual_cert_size,enum versal_ocp_dev_key dev_key_sel,bool is_csr)602*03d6625fSDennis Ries TEE_Result versal_ocp_get_x509_cert(void *cert, uint32_t cert_size,
603*03d6625fSDennis Ries uint32_t *actual_cert_size,
604*03d6625fSDennis Ries enum versal_ocp_dev_key dev_key_sel,
605*03d6625fSDennis Ries bool is_csr)
606*03d6625fSDennis Ries {
607*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
608*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
609*03d6625fSDennis Ries /*
610*03d6625fSDennis Ries * NOTE: PLM Firmware (function XCert_GenerateX509Cert()) actually
611*03d6625fSDennis Ries * ignores member "cert_size" (called "MaxCertSize" there) and
612*03d6625fSDennis Ries * has a hard-coded internal buffer of 2000 Bytes, which is used
613*03d6625fSDennis Ries * to construct the certificate. The result is then copied to our
614*03d6625fSDennis Ries * ibuf:
615*03d6625fSDennis Ries */
616*03d6625fSDennis Ries struct versal_ocp_x509_cert param = {
617*03d6625fSDennis Ries .cert_addr = 0,
618*03d6625fSDennis Ries .actual_len_addr = 0,
619*03d6625fSDennis Ries .cert_size = 2000,
620*03d6625fSDennis Ries .dev_key_sel = dev_key_sel,
621*03d6625fSDennis Ries .is_csr = is_csr ? 1 : 0,
622*03d6625fSDennis Ries };
623*03d6625fSDennis Ries size_t idx_cert = 0;
624*03d6625fSDennis Ries size_t idx_size = 0;
625*03d6625fSDennis Ries
626*03d6625fSDennis Ries if (!cert)
627*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
628*03d6625fSDennis Ries
629*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(GETX509CERT));
630*03d6625fSDennis Ries
631*03d6625fSDennis Ries if (cert_size > param.cert_size)
632*03d6625fSDennis Ries param.cert_size = cert_size;
633*03d6625fSDennis Ries ret = versal_ipi_cmd_ibuf_alloc(&cmd, NULL, param.cert_size,
634*03d6625fSDennis Ries &idx_cert);
635*03d6625fSDennis Ries if (ret)
636*03d6625fSDennis Ries goto out;
637*03d6625fSDennis Ries
638*03d6625fSDennis Ries ret = versal_ipi_cmd_ibuf_alloc(&cmd, NULL, sizeof(*actual_cert_size),
639*03d6625fSDennis Ries &idx_size);
640*03d6625fSDennis Ries if (ret)
641*03d6625fSDennis Ries goto out;
642*03d6625fSDennis Ries
643*03d6625fSDennis Ries param.cert_addr = versal_ipi_cmd_ibuf_get_paddr(&cmd, idx_cert);
644*03d6625fSDennis Ries param.actual_len_addr = versal_ipi_cmd_ibuf_get_paddr(&cmd, idx_size);
645*03d6625fSDennis Ries
646*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, ¶m, sizeof(param), NULL);
647*03d6625fSDennis Ries if (ret)
648*03d6625fSDennis Ries goto out;
649*03d6625fSDennis Ries
650*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
651*03d6625fSDennis Ries plm_status = 0;
652*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
653*03d6625fSDennis Ries EMSG("Versal PLM API ID GETX509CERT failed: 0x%" PRIx32,
654*03d6625fSDennis Ries plm_status);
655*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
656*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
657*03d6625fSDennis Ries goto out;
658*03d6625fSDennis Ries }
659*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
660*03d6625fSDennis Ries
661*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, actual_cert_size,
662*03d6625fSDennis Ries sizeof(*actual_cert_size), idx_size);
663*03d6625fSDennis Ries if (param.cert_size < *actual_cert_size) {
664*03d6625fSDennis Ries EMSG("Versal PLM API ID GETX509CERT failed: wrote beyond X.509 certificate buffer, provided %u bytes, needed %u bytes",
665*03d6625fSDennis Ries param.cert_size, *actual_cert_size);
666*03d6625fSDennis Ries panic();
667*03d6625fSDennis Ries }
668*03d6625fSDennis Ries if (cert_size < *actual_cert_size) {
669*03d6625fSDennis Ries EMSG("Versal PLM API ID GETX509CERT failed: X.509 certificate buffer too small, need %u bytes",
670*03d6625fSDennis Ries *actual_cert_size);
671*03d6625fSDennis Ries return TEE_ERROR_GENERIC;
672*03d6625fSDennis Ries }
673*03d6625fSDennis Ries
674*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, cert, *actual_cert_size, idx_cert);
675*03d6625fSDennis Ries
676*03d6625fSDennis Ries out:
677*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
678*03d6625fSDennis Ries return ret;
679*03d6625fSDennis Ries }
680*03d6625fSDennis Ries
versal_ocp_attest_with_devak(void * hash,uint32_t hash_size,void * signature,uint32_t signature_size)681*03d6625fSDennis Ries TEE_Result versal_ocp_attest_with_devak(void *hash, uint32_t hash_size,
682*03d6625fSDennis Ries void *signature,
683*03d6625fSDennis Ries uint32_t signature_size)
684*03d6625fSDennis Ries {
685*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
686*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
687*03d6625fSDennis Ries struct versal_ocp_attest param = {
688*03d6625fSDennis Ries .hash_addr = 0,
689*03d6625fSDennis Ries .signature_addr = 0,
690*03d6625fSDennis Ries .reserved = 0,
691*03d6625fSDennis Ries .hash_len = hash_size,
692*03d6625fSDennis Ries };
693*03d6625fSDennis Ries size_t idx_hash = 0;
694*03d6625fSDennis Ries size_t idx_sign = 0;
695*03d6625fSDennis Ries
696*03d6625fSDennis Ries if (!hash || !hash_size)
697*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
698*03d6625fSDennis Ries
699*03d6625fSDennis Ries if (!signature ||
700*03d6625fSDennis Ries signature_size != VERSAL_OCP_ECC_P384_SIZE_BYTES)
701*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
702*03d6625fSDennis Ries
703*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(ATTESTWITHDEVAK));
704*03d6625fSDennis Ries
705*03d6625fSDennis Ries ret = versal_ipi_cmd_ibuf_alloc(&cmd, hash, hash_size, &idx_hash);
706*03d6625fSDennis Ries if (ret)
707*03d6625fSDennis Ries goto out;
708*03d6625fSDennis Ries
709*03d6625fSDennis Ries ret = versal_ipi_cmd_ibuf_alloc(&cmd, NULL, signature_size, &idx_sign);
710*03d6625fSDennis Ries if (ret)
711*03d6625fSDennis Ries goto out;
712*03d6625fSDennis Ries
713*03d6625fSDennis Ries param.hash_addr = versal_ipi_cmd_ibuf_get_paddr(&cmd, idx_hash);
714*03d6625fSDennis Ries param.signature_addr = versal_ipi_cmd_ibuf_get_paddr(&cmd, idx_sign);
715*03d6625fSDennis Ries
716*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, ¶m, sizeof(param), NULL);
717*03d6625fSDennis Ries if (ret)
718*03d6625fSDennis Ries goto out;
719*03d6625fSDennis Ries
720*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
721*03d6625fSDennis Ries plm_status = 0;
722*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
723*03d6625fSDennis Ries EMSG("Versal PLM API ID ATTESTWITHDEVAK failed: 0x%" PRIx32,
724*03d6625fSDennis Ries plm_status);
725*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
726*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
727*03d6625fSDennis Ries goto out;
728*03d6625fSDennis Ries }
729*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
730*03d6625fSDennis Ries
731*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, signature,
732*03d6625fSDennis Ries VERSAL_OCP_ECC_P384_SIZE_BYTES, idx_sign);
733*03d6625fSDennis Ries
734*03d6625fSDennis Ries out:
735*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
736*03d6625fSDennis Ries return ret;
737*03d6625fSDennis Ries }
738*03d6625fSDennis Ries
versal_ocp_attest_with_key_wrap_devak(void * attest_buf,uint32_t attest_buf_size,uint32_t pub_key_offset,void * signature,uint32_t signature_size)739*03d6625fSDennis Ries TEE_Result versal_ocp_attest_with_key_wrap_devak(void *attest_buf,
740*03d6625fSDennis Ries uint32_t attest_buf_size,
741*03d6625fSDennis Ries uint32_t pub_key_offset,
742*03d6625fSDennis Ries void *signature,
743*03d6625fSDennis Ries uint32_t signature_size)
744*03d6625fSDennis Ries {
745*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
746*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
747*03d6625fSDennis Ries size_t idx_buf = 0;
748*03d6625fSDennis Ries size_t idx_sign = 0;
749*03d6625fSDennis Ries void *_attest_buf = NULL;
750*03d6625fSDennis Ries
751*03d6625fSDennis Ries /*
752*03d6625fSDennis Ries * NOTE: The buffer with data to be attested has 2 "components":
753*03d6625fSDennis Ries * - the actual input data to be attested
754*03d6625fSDennis Ries * - the output RSA 3072 public key (768 Bytes, included in
755*03d6625fSDennis Ries * attestation)
756*03d6625fSDennis Ries *
757*03d6625fSDennis Ries * The space for the RSA public key is supposed to be located at
758*03d6625fSDennis Ries * the end of the buffer at the offset specified by argument
759*03d6625fSDennis Ries * "pub_key_offset".
760*03d6625fSDennis Ries *
761*03d6625fSDennis Ries * For an unknown reason PLM Firmware
762*03d6625fSDennis Ries * (XOcp_AttestWithKeyWrapDevAkIpi()) checks parameter
763*03d6625fSDennis Ries * "attest_buf_size" (called "AttnPloadSize" there) for being
764*03d6625fSDennis Ries * strictly _greater_ than:
765*03d6625fSDennis Ries * public key offset +
766*03d6625fSDennis Ries * half of struct versal_secure_rsapubkey() +
767*03d6625fSDennis Ries * 4 Bytes
768*03d6625fSDennis Ries *
769*03d6625fSDennis Ries * At the same time the code does copy the complete struct
770*03d6625fSDennis Ries * versal_secure_rsapubkey at the public key offset. Thus the size
771*03d6625fSDennis Ries * check is wrong! And why "greater than"? Why not "greater or
772*03d6625fSDennis Ries * equal"?
773*03d6625fSDennis Ries */
774*03d6625fSDennis Ries if (!attest_buf ||
775*03d6625fSDennis Ries (attest_buf_size <
776*03d6625fSDennis Ries (pub_key_offset + sizeof(struct versal_secure_rsapubkey))))
777*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
778*03d6625fSDennis Ries
779*03d6625fSDennis Ries if (!signature ||
780*03d6625fSDennis Ries signature_size != VERSAL_OCP_ECC_P384_SIZE_BYTES)
781*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
782*03d6625fSDennis Ries
783*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd,
784*03d6625fSDennis Ries OCP_API_ID(ATTEST_WITH_KEYWRAP_DEVAK));
785*03d6625fSDennis Ries
786*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, attest_buf, attest_buf_size,
787*03d6625fSDennis Ries &idx_buf);
788*03d6625fSDennis Ries if (ret)
789*03d6625fSDennis Ries goto out;
790*03d6625fSDennis Ries
791*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, attest_buf_size);
792*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, pub_key_offset);
793*03d6625fSDennis Ries
794*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, NULL, signature_size,
795*03d6625fSDennis Ries &idx_sign);
796*03d6625fSDennis Ries if (ret)
797*03d6625fSDennis Ries goto out;
798*03d6625fSDennis Ries
799*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
800*03d6625fSDennis Ries plm_status = 0;
801*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
802*03d6625fSDennis Ries EMSG("Versal PLM API ID ATTEST_WITH_KEYWRAP_DEVAK failed: 0x%" PRIx32,
803*03d6625fSDennis Ries plm_status);
804*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
805*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
806*03d6625fSDennis Ries goto out;
807*03d6625fSDennis Ries }
808*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
809*03d6625fSDennis Ries
810*03d6625fSDennis Ries _attest_buf = versal_ipi_cmd_ibuf_get(&cmd, idx_buf);
811*03d6625fSDennis Ries memcpy((uint8_t *)attest_buf + pub_key_offset,
812*03d6625fSDennis Ries (uint8_t *)_attest_buf + pub_key_offset,
813*03d6625fSDennis Ries sizeof(struct versal_secure_rsapubkey));
814*03d6625fSDennis Ries
815*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, signature,
816*03d6625fSDennis Ries VERSAL_OCP_ECC_P384_SIZE_BYTES, idx_sign);
817*03d6625fSDennis Ries
818*03d6625fSDennis Ries out:
819*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
820*03d6625fSDennis Ries return ret;
821*03d6625fSDennis Ries }
822*03d6625fSDennis Ries
versal_ocp_gen_shared_secret_with_devak(void * pub_key,uint32_t pub_key_size,void * shared_secret,uint32_t shared_secret_size)823*03d6625fSDennis Ries TEE_Result versal_ocp_gen_shared_secret_with_devak(void *pub_key,
824*03d6625fSDennis Ries uint32_t pub_key_size,
825*03d6625fSDennis Ries void *shared_secret,
826*03d6625fSDennis Ries uint32_t shared_secret_size)
827*03d6625fSDennis Ries {
828*03d6625fSDennis Ries TEE_Result ret = TEE_SUCCESS;
829*03d6625fSDennis Ries struct versal_ipi_cmd cmd = {};
830*03d6625fSDennis Ries size_t idx = 0;
831*03d6625fSDennis Ries
832*03d6625fSDennis Ries if (!pub_key ||
833*03d6625fSDennis Ries (pub_key_size != (VERSAL_OCP_ECC_P384_SIZE_BYTES * 2)))
834*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
835*03d6625fSDennis Ries
836*03d6625fSDennis Ries if (!shared_secret ||
837*03d6625fSDennis Ries (shared_secret_size != (VERSAL_OCP_ECC_P384_SIZE_BYTES * 2)))
838*03d6625fSDennis Ries return TEE_ERROR_BAD_PARAMETERS;
839*03d6625fSDennis Ries
840*03d6625fSDennis Ries versal_ipi_cmd_data_push_val(&cmd, OCP_API_ID(GEN_SHARED_SECRET));
841*03d6625fSDennis Ries
842*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, pub_key, pub_key_size, NULL);
843*03d6625fSDennis Ries if (ret)
844*03d6625fSDennis Ries goto out;
845*03d6625fSDennis Ries
846*03d6625fSDennis Ries ret = versal_ipi_cmd_data_push_ibuf(&cmd, NULL, shared_secret_size,
847*03d6625fSDennis Ries &idx);
848*03d6625fSDennis Ries if (ret)
849*03d6625fSDennis Ries goto out;
850*03d6625fSDennis Ries
851*03d6625fSDennis Ries mutex_lock(&plm_status_lock);
852*03d6625fSDennis Ries plm_status = 0;
853*03d6625fSDennis Ries if (versal_pmc_notify(&cmd, NULL, &plm_status)) {
854*03d6625fSDennis Ries EMSG("Versal PLM API ID GEN_SHARED_SECRET failed: 0x%" PRIx32,
855*03d6625fSDennis Ries plm_status);
856*03d6625fSDennis Ries ret = TEE_ERROR_GENERIC;
857*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
858*03d6625fSDennis Ries goto out;
859*03d6625fSDennis Ries }
860*03d6625fSDennis Ries mutex_unlock(&plm_status_lock);
861*03d6625fSDennis Ries
862*03d6625fSDennis Ries versal_ipi_cmd_ibuf_fetch(&cmd, shared_secret, shared_secret_size, idx);
863*03d6625fSDennis Ries
864*03d6625fSDennis Ries out:
865*03d6625fSDennis Ries versal_ipi_cmd_free(&cmd);
866*03d6625fSDennis Ries return ret;
867*03d6625fSDennis Ries }
868