162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Test TDX guest features 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2022 Intel Corporation. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <sys/ioctl.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <errno.h> 1362306a36Sopenharmony_ci#include <fcntl.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/tdx-guest.h> 1662306a36Sopenharmony_ci#include "../kselftest_harness.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define TDX_GUEST_DEVNAME "/dev/tdx_guest" 1962306a36Sopenharmony_ci#define HEX_DUMP_SIZE 8 2062306a36Sopenharmony_ci#define DEBUG 0 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/** 2362306a36Sopenharmony_ci * struct tdreport_type - Type header of TDREPORT_STRUCT. 2462306a36Sopenharmony_ci * @type: Type of the TDREPORT (0 - SGX, 81 - TDX, rest are reserved) 2562306a36Sopenharmony_ci * @sub_type: Subtype of the TDREPORT (Default value is 0). 2662306a36Sopenharmony_ci * @version: TDREPORT version (Default value is 0). 2762306a36Sopenharmony_ci * @reserved: Added for future extension. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * More details can be found in TDX v1.0 module specification, sec 3062306a36Sopenharmony_ci * titled "REPORTTYPE". 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_cistruct tdreport_type { 3362306a36Sopenharmony_ci __u8 type; 3462306a36Sopenharmony_ci __u8 sub_type; 3562306a36Sopenharmony_ci __u8 version; 3662306a36Sopenharmony_ci __u8 reserved; 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/** 4062306a36Sopenharmony_ci * struct reportmac - TDX guest report data, MAC and TEE hashes. 4162306a36Sopenharmony_ci * @type: TDREPORT type header. 4262306a36Sopenharmony_ci * @reserved1: Reserved for future extension. 4362306a36Sopenharmony_ci * @cpu_svn: CPU security version. 4462306a36Sopenharmony_ci * @tee_tcb_info_hash: SHA384 hash of TEE TCB INFO. 4562306a36Sopenharmony_ci * @tee_td_info_hash: SHA384 hash of TDINFO_STRUCT. 4662306a36Sopenharmony_ci * @reportdata: User defined unique data passed in TDG.MR.REPORT request. 4762306a36Sopenharmony_ci * @reserved2: Reserved for future extension. 4862306a36Sopenharmony_ci * @mac: CPU MAC ID. 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * It is MAC-protected and contains hashes of the remainder of the 5162306a36Sopenharmony_ci * report structure along with user provided report data. More details can 5262306a36Sopenharmony_ci * be found in TDX v1.0 Module specification, sec titled "REPORTMACSTRUCT" 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_cistruct reportmac { 5562306a36Sopenharmony_ci struct tdreport_type type; 5662306a36Sopenharmony_ci __u8 reserved1[12]; 5762306a36Sopenharmony_ci __u8 cpu_svn[16]; 5862306a36Sopenharmony_ci __u8 tee_tcb_info_hash[48]; 5962306a36Sopenharmony_ci __u8 tee_td_info_hash[48]; 6062306a36Sopenharmony_ci __u8 reportdata[64]; 6162306a36Sopenharmony_ci __u8 reserved2[32]; 6262306a36Sopenharmony_ci __u8 mac[32]; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/** 6662306a36Sopenharmony_ci * struct td_info - TDX guest measurements and configuration. 6762306a36Sopenharmony_ci * @attr: TDX Guest attributes (like debug, spet_disable, etc). 6862306a36Sopenharmony_ci * @xfam: Extended features allowed mask. 6962306a36Sopenharmony_ci * @mrtd: Build time measurement register. 7062306a36Sopenharmony_ci * @mrconfigid: Software-defined ID for non-owner-defined configuration 7162306a36Sopenharmony_ci * of the guest - e.g., run-time or OS configuration. 7262306a36Sopenharmony_ci * @mrowner: Software-defined ID for the guest owner. 7362306a36Sopenharmony_ci * @mrownerconfig: Software-defined ID for owner-defined configuration of 7462306a36Sopenharmony_ci * the guest - e.g., specific to the workload. 7562306a36Sopenharmony_ci * @rtmr: Run time measurement registers. 7662306a36Sopenharmony_ci * @reserved: Added for future extension. 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci * It contains the measurements and initial configuration of the TDX guest 7962306a36Sopenharmony_ci * that was locked at initialization and a set of measurement registers 8062306a36Sopenharmony_ci * that are run-time extendable. More details can be found in TDX v1.0 8162306a36Sopenharmony_ci * Module specification, sec titled "TDINFO_STRUCT". 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_cistruct td_info { 8462306a36Sopenharmony_ci __u8 attr[8]; 8562306a36Sopenharmony_ci __u64 xfam; 8662306a36Sopenharmony_ci __u64 mrtd[6]; 8762306a36Sopenharmony_ci __u64 mrconfigid[6]; 8862306a36Sopenharmony_ci __u64 mrowner[6]; 8962306a36Sopenharmony_ci __u64 mrownerconfig[6]; 9062306a36Sopenharmony_ci __u64 rtmr[24]; 9162306a36Sopenharmony_ci __u64 reserved[14]; 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/* 9562306a36Sopenharmony_ci * struct tdreport - Output of TDCALL[TDG.MR.REPORT]. 9662306a36Sopenharmony_ci * @reportmac: Mac protected header of size 256 bytes. 9762306a36Sopenharmony_ci * @tee_tcb_info: Additional attestable elements in the TCB are not 9862306a36Sopenharmony_ci * reflected in the reportmac. 9962306a36Sopenharmony_ci * @reserved: Added for future extension. 10062306a36Sopenharmony_ci * @tdinfo: Measurements and configuration data of size 512 bytes. 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * More details can be found in TDX v1.0 Module specification, sec 10362306a36Sopenharmony_ci * titled "TDREPORT_STRUCT". 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_cistruct tdreport { 10662306a36Sopenharmony_ci struct reportmac reportmac; 10762306a36Sopenharmony_ci __u8 tee_tcb_info[239]; 10862306a36Sopenharmony_ci __u8 reserved[17]; 10962306a36Sopenharmony_ci struct td_info tdinfo; 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic void print_array_hex(const char *title, const char *prefix_str, 11362306a36Sopenharmony_ci const void *buf, int len) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci int i, j, line_len, rowsize = HEX_DUMP_SIZE; 11662306a36Sopenharmony_ci const __u8 *ptr = buf; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci printf("\t\t%s", title); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci for (j = 0; j < len; j += rowsize) { 12162306a36Sopenharmony_ci line_len = rowsize < (len - j) ? rowsize : (len - j); 12262306a36Sopenharmony_ci printf("%s%.8x:", prefix_str, j); 12362306a36Sopenharmony_ci for (i = 0; i < line_len; i++) 12462306a36Sopenharmony_ci printf(" %.2x", ptr[j + i]); 12562306a36Sopenharmony_ci printf("\n"); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci printf("\n"); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ciTEST(verify_report) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct tdx_report_req req; 13462306a36Sopenharmony_ci struct tdreport *tdreport; 13562306a36Sopenharmony_ci int devfd, i; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci devfd = open(TDX_GUEST_DEVNAME, O_RDWR | O_SYNC); 13862306a36Sopenharmony_ci ASSERT_LT(0, devfd); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* Generate sample report data */ 14162306a36Sopenharmony_ci for (i = 0; i < TDX_REPORTDATA_LEN; i++) 14262306a36Sopenharmony_ci req.reportdata[i] = i; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci /* Get TDREPORT */ 14562306a36Sopenharmony_ci ASSERT_EQ(0, ioctl(devfd, TDX_CMD_GET_REPORT0, &req)); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (DEBUG) { 14862306a36Sopenharmony_ci print_array_hex("\n\t\tTDX report data\n", "", 14962306a36Sopenharmony_ci req.reportdata, sizeof(req.reportdata)); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci print_array_hex("\n\t\tTDX tdreport data\n", "", 15262306a36Sopenharmony_ci req.tdreport, sizeof(req.tdreport)); 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* Make sure TDREPORT data includes the REPORTDATA passed */ 15662306a36Sopenharmony_ci tdreport = (struct tdreport *)req.tdreport; 15762306a36Sopenharmony_ci ASSERT_EQ(0, memcmp(&tdreport->reportmac.reportdata[0], 15862306a36Sopenharmony_ci req.reportdata, sizeof(req.reportdata))); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci ASSERT_EQ(0, close(devfd)); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ciTEST_HARNESS_MAIN 164