summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/tdx/tdx_guest_test.c
blob: 2a2afd856798b4bcf74820709796c1b5f0187579 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// SPDX-License-Identifier: GPL-2.0
/*
 * Test TDX guest features
 *
 * Copyright (C) 2022 Intel Corporation.
 *
 * Author: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
 */

#include <sys/ioctl.h>

#include <errno.h>
#include <fcntl.h>

#include "../kselftest_harness.h"
#include "../../../../include/uapi/linux/tdx-guest.h"

#define TDX_GUEST_DEVNAME "/dev/tdx_guest"
#define HEX_DUMP_SIZE 8
#define DEBUG 0

/**
 * struct tdreport_type - Type header of TDREPORT_STRUCT.
 * @type: Type of the TDREPORT (0 - SGX, 81 - TDX, rest are reserved)
 * @sub_type: Subtype of the TDREPORT (Default value is 0).
 * @version: TDREPORT version (Default value is 0).
 * @reserved: Added for future extension.
 *
 * More details can be found in TDX v1.0 module specification, sec
 * titled "REPORTTYPE".
 */
struct tdreport_type {
	__u8 type;
	__u8 sub_type;
	__u8 version;
	__u8 reserved;
};

/**
 * struct reportmac - TDX guest report data, MAC and TEE hashes.
 * @type: TDREPORT type header.
 * @reserved1: Reserved for future extension.
 * @cpu_svn: CPU security version.
 * @tee_tcb_info_hash: SHA384 hash of TEE TCB INFO.
 * @tee_td_info_hash: SHA384 hash of TDINFO_STRUCT.
 * @reportdata: User defined unique data passed in TDG.MR.REPORT request.
 * @reserved2: Reserved for future extension.
 * @mac: CPU MAC ID.
 *
 * It is MAC-protected and contains hashes of the remainder of the
 * report structure along with user provided report data. More details can
 * be found in TDX v1.0 Module specification, sec titled "REPORTMACSTRUCT"
 */
struct reportmac {
	struct tdreport_type type;
	__u8 reserved1[12];
	__u8 cpu_svn[16];
	__u8 tee_tcb_info_hash[48];
	__u8 tee_td_info_hash[48];
	__u8 reportdata[64];
	__u8 reserved2[32];
	__u8 mac[32];
};

/**
 * struct td_info - TDX guest measurements and configuration.
 * @attr: TDX Guest attributes (like debug, spet_disable, etc).
 * @xfam: Extended features allowed mask.
 * @mrtd: Build time measurement register.
 * @mrconfigid: Software-defined ID for non-owner-defined configuration
 *              of the guest - e.g., run-time or OS configuration.
 * @mrowner: Software-defined ID for the guest owner.
 * @mrownerconfig: Software-defined ID for owner-defined configuration of
 *                 the guest - e.g., specific to the workload.
 * @rtmr: Run time measurement registers.
 * @reserved: Added for future extension.
 *
 * It contains the measurements and initial configuration of the TDX guest
 * that was locked at initialization and a set of measurement registers
 * that are run-time extendable. More details can be found in TDX v1.0
 * Module specification, sec titled "TDINFO_STRUCT".
 */
struct td_info {
	__u8 attr[8];
	__u64 xfam;
	__u64 mrtd[6];
	__u64 mrconfigid[6];
	__u64 mrowner[6];
	__u64 mrownerconfig[6];
	__u64 rtmr[24];
	__u64 reserved[14];
};

/*
 * struct tdreport - Output of TDCALL[TDG.MR.REPORT].
 * @reportmac: Mac protected header of size 256 bytes.
 * @tee_tcb_info: Additional attestable elements in the TCB are not
 *                reflected in the reportmac.
 * @reserved: Added for future extension.
 * @tdinfo: Measurements and configuration data of size 512 bytes.
 *
 * More details can be found in TDX v1.0 Module specification, sec
 * titled "TDREPORT_STRUCT".
 */
struct tdreport {
	struct reportmac reportmac;
	__u8 tee_tcb_info[239];
	__u8 reserved[17];
	struct td_info tdinfo;
};

static void print_array_hex(const char *title, const char *prefix_str,
			    const void *buf, int len)
{
	int i, j, line_len, rowsize = HEX_DUMP_SIZE;
	const __u8 *ptr = buf;

	printf("\t\t%s", title);

	for (j = 0; j < len; j += rowsize) {
		line_len = rowsize < (len - j) ? rowsize : (len - j);
		printf("%s%.8x:", prefix_str, j);
		for (i = 0; i < line_len; i++)
			printf(" %.2x", ptr[j + i]);
		printf("\n");
	}

	printf("\n");
}

TEST(verify_report)
{
	struct tdx_report_req req;
	struct tdreport *tdreport;
	int devfd, i;

	devfd = open(TDX_GUEST_DEVNAME, O_RDWR | O_SYNC);
	ASSERT_LT(0, devfd);

	/* Generate sample report data */
	for (i = 0; i < TDX_REPORTDATA_LEN; i++)
		req.reportdata[i] = i;

	/* Get TDREPORT */
	ASSERT_EQ(0, ioctl(devfd, TDX_CMD_GET_REPORT0, &req));

	if (DEBUG) {
		print_array_hex("\n\t\tTDX report data\n", "",
				req.reportdata, sizeof(req.reportdata));

		print_array_hex("\n\t\tTDX tdreport data\n", "",
				req.tdreport, sizeof(req.tdreport));
	}

	/* Make sure TDREPORT data includes the REPORTDATA passed */
	tdreport = (struct tdreport *)req.tdreport;
	ASSERT_EQ(0, memcmp(&tdreport->reportmac.reportdata[0],
			    req.reportdata, sizeof(req.reportdata)));

	ASSERT_EQ(0, close(devfd));
}

TEST_HARNESS_MAIN