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(title: "\n\t\tTDX report data\n" , prefix_str: "" , |
149 | buf: req.reportdata, len: sizeof(req.reportdata)); |
150 | |
151 | print_array_hex(title: "\n\t\tTDX tdreport data\n" , prefix_str: "" , |
152 | buf: req.tdreport, len: 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 | |