1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test TDX guest features
4  *
5  * Copyright (C) 2022 Intel Corporation.
6  *
7  * Author: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
8  */
9 
10 #include <sys/ioctl.h>
11 
12 #include <errno.h>
13 #include <fcntl.h>
14 
15 #include <linux/tdx-guest.h>
16 #include "../kselftest_harness.h"
17 
18 #define TDX_GUEST_DEVNAME "/dev/tdx_guest"
19 #define HEX_DUMP_SIZE 8
20 #define DEBUG 0
21 
22 /**
23  * struct tdreport_type - Type header of TDREPORT_STRUCT.
24  * @type: Type of the TDREPORT (0 - SGX, 81 - TDX, rest are reserved)
25  * @sub_type: Subtype of the TDREPORT (Default value is 0).
26  * @version: TDREPORT version (Default value is 0).
27  * @reserved: Added for future extension.
28  *
29  * More details can be found in TDX v1.0 module specification, sec
30  * titled "REPORTTYPE".
31  */
32 struct tdreport_type {
33 	__u8 type;
34 	__u8 sub_type;
35 	__u8 version;
36 	__u8 reserved;
37 };
38 
39 /**
40  * struct reportmac - TDX guest report data, MAC and TEE hashes.
41  * @type: TDREPORT type header.
42  * @reserved1: Reserved for future extension.
43  * @cpu_svn: CPU security version.
44  * @tee_tcb_info_hash: SHA384 hash of TEE TCB INFO.
45  * @tee_td_info_hash: SHA384 hash of TDINFO_STRUCT.
46  * @reportdata: User defined unique data passed in TDG.MR.REPORT request.
47  * @reserved2: Reserved for future extension.
48  * @mac: CPU MAC ID.
49  *
50  * It is MAC-protected and contains hashes of the remainder of the
51  * report structure along with user provided report data. More details can
52  * be found in TDX v1.0 Module specification, sec titled "REPORTMACSTRUCT"
53  */
54 struct reportmac {
55 	struct tdreport_type type;
56 	__u8 reserved1[12];
57 	__u8 cpu_svn[16];
58 	__u8 tee_tcb_info_hash[48];
59 	__u8 tee_td_info_hash[48];
60 	__u8 reportdata[64];
61 	__u8 reserved2[32];
62 	__u8 mac[32];
63 };
64 
65 /**
66  * struct td_info - TDX guest measurements and configuration.
67  * @attr: TDX Guest attributes (like debug, spet_disable, etc).
68  * @xfam: Extended features allowed mask.
69  * @mrtd: Build time measurement register.
70  * @mrconfigid: Software-defined ID for non-owner-defined configuration
71  *              of the guest - e.g., run-time or OS configuration.
72  * @mrowner: Software-defined ID for the guest owner.
73  * @mrownerconfig: Software-defined ID for owner-defined configuration of
74  *                 the guest - e.g., specific to the workload.
75  * @rtmr: Run time measurement registers.
76  * @reserved: Added for future extension.
77  *
78  * It contains the measurements and initial configuration of the TDX guest
79  * that was locked at initialization and a set of measurement registers
80  * that are run-time extendable. More details can be found in TDX v1.0
81  * Module specification, sec titled "TDINFO_STRUCT".
82  */
83 struct td_info {
84 	__u8 attr[8];
85 	__u64 xfam;
86 	__u64 mrtd[6];
87 	__u64 mrconfigid[6];
88 	__u64 mrowner[6];
89 	__u64 mrownerconfig[6];
90 	__u64 rtmr[24];
91 	__u64 reserved[14];
92 };
93 
94 /*
95  * struct tdreport - Output of TDCALL[TDG.MR.REPORT].
96  * @reportmac: Mac protected header of size 256 bytes.
97  * @tee_tcb_info: Additional attestable elements in the TCB are not
98  *                reflected in the reportmac.
99  * @reserved: Added for future extension.
100  * @tdinfo: Measurements and configuration data of size 512 bytes.
101  *
102  * More details can be found in TDX v1.0 Module specification, sec
103  * titled "TDREPORT_STRUCT".
104  */
105 struct tdreport {
106 	struct reportmac reportmac;
107 	__u8 tee_tcb_info[239];
108 	__u8 reserved[17];
109 	struct td_info tdinfo;
110 };
111 
112 static void print_array_hex(const char *title, const char *prefix_str,
113 			    const void *buf, int len)
114 {
115 	int i, j, line_len, rowsize = HEX_DUMP_SIZE;
116 	const __u8 *ptr = buf;
117 
118 	printf("\t\t%s", title);
119 
120 	for (j = 0; j < len; j += rowsize) {
121 		line_len = rowsize < (len - j) ? rowsize : (len - j);
122 		printf("%s%.8x:", prefix_str, j);
123 		for (i = 0; i < line_len; i++)
124 			printf(" %.2x", ptr[j + i]);
125 		printf("\n");
126 	}
127 
128 	printf("\n");
129 }
130 
131 TEST(verify_report)
132 {
133 	struct tdx_report_req req;
134 	struct tdreport *tdreport;
135 	int devfd, i;
136 
137 	devfd = open(TDX_GUEST_DEVNAME, O_RDWR | O_SYNC);
138 	ASSERT_LT(0, devfd);
139 
140 	/* Generate sample report data */
141 	for (i = 0; i < TDX_REPORTDATA_LEN; i++)
142 		req.reportdata[i] = i;
143 
144 	/* Get TDREPORT */
145 	ASSERT_EQ(0, ioctl(devfd, TDX_CMD_GET_REPORT0, &req));
146 
147 	if (DEBUG) {
148 		print_array_hex("\n\t\tTDX report data\n", "",
149 				req.reportdata, sizeof(req.reportdata));
150 
151 		print_array_hex("\n\t\tTDX tdreport data\n", "",
152 				req.tdreport, sizeof(req.tdreport));
153 	}
154 
155 	/* Make sure TDREPORT data includes the REPORTDATA passed */
156 	tdreport = (struct tdreport *)req.tdreport;
157 	ASSERT_EQ(0, memcmp(&tdreport->reportmac.reportdata[0],
158 			    req.reportdata, sizeof(req.reportdata)));
159 
160 	ASSERT_EQ(0, close(devfd));
161 }
162 
163 TEST_HARNESS_MAIN
164