Skip to content

Commit 81ac532

Browse files
committed
arch/x86: process DRTM policy
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
1 parent 62863e0 commit 81ac532

File tree

3 files changed

+217
-0
lines changed

3 files changed

+217
-0
lines changed

xen/arch/x86/include/asm/intel_txt.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <xen/multiboot.h>
2+
13
/*
24
* TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_BASE)
35
*/
@@ -380,4 +382,14 @@ extern void txt_restore_mtrrs(bool e820_verbose);
380382
void tpm_hash_extend(unsigned loc, unsigned pcr, uint8_t *buf, unsigned size,
381383
uint32_t type, uint8_t *log_data, unsigned log_data_size);
382384

385+
/* Measures essential parts of SLR table before making use of them. */
386+
void tpm_measure_slrt(void);
387+
388+
/* Takes measurements of DRTM policy entries except for MBI and SLRT which
389+
* should have been measured by the time this is called. Also performs sanity
390+
* checks of the policy and panics on failure. In particular, the function
391+
* verifies that DRTM is consistent with MultibootInfo (MBI) (the MBI address
392+
* is assumed to be virtual). */
393+
void tpm_process_drtm_policy(const multiboot_info_t *mbi);
394+
383395
#endif /* __ASSEMBLY__ */

xen/arch/x86/setup.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
11721172
{
11731173
/* Prepare for TXT-related code. */
11741174
map_txt_mem_regions();
1175+
/* Measure SLRT here because it gets used by init_e820(), the rest is
1176+
* measured below by tpm_process_drtm_policy(). */
1177+
tpm_measure_slrt();
11751178
/* Reserve TXT heap and SINIT. */
11761179
protect_txt_mem_regions();
11771180
}
@@ -1194,6 +1197,12 @@ void __init noreturn __start_xen(unsigned long mbi_p)
11941197
/* Create a temporary copy of the E820 map. */
11951198
memcpy(&boot_e820, &e820, sizeof(e820));
11961199

1200+
/* Process all yet unmeasured DRTM entries after E820 initialization to not
1201+
* do this while memory is uncached (too slow). This must also happen before
1202+
* fields of Multiboot modules change their format below. */
1203+
if ( slaunch_active )
1204+
tpm_process_drtm_policy(mbi);
1205+
11971206
/* Early kexec reservation (explicit static start address). */
11981207
nr_pages = 0;
11991208
for ( i = 0; i < e820.nr_map; i++ )

xen/arch/x86/tpm.c

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,4 +963,200 @@ void __stdcall tpm_extend_mbi(uint32_t *mbi)
963963
tpm_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)mbi, *mbi,
964964
TXT_EVTYPE_SLAUNCH, NULL, 0);
965965
}
966+
#else
967+
static struct slr_table *slr_get_table(void)
968+
{
969+
struct txt_os_mle_data *os_mle;
970+
struct slr_table *slrt;
971+
972+
os_mle = txt_os_mle_data_start(__va(read_txt_reg(TXTCR_HEAP_BASE)));
973+
974+
map_l2(os_mle->slrt, PAGE_SIZE);
975+
slrt = __va(os_mle->slrt);
976+
977+
if ( slrt->magic != SLR_TABLE_MAGIC )
978+
panic("SLRT has invalid magic value: %#08x!\n", slrt->magic);
979+
/* XXX: are newer revisions allowed? */
980+
if ( slrt->revision != SLR_TABLE_REVISION )
981+
panic("SLRT is of unsupported revision: %#04x!\n", slrt->revision);
982+
if ( slrt->architecture != SLR_INTEL_TXT )
983+
panic("SLRT is for unexpected architecture: %#04x!\n",
984+
slrt->architecture);
985+
if ( slrt->size > slrt->max_size )
986+
panic("SLRT is larger than its max size: %#08x > %#08x!\n",
987+
slrt->size, slrt->max_size);
988+
989+
if ( slrt->size > PAGE_SIZE )
990+
map_l2(os_mle->slrt, slrt->size);
991+
992+
return slrt;
993+
}
994+
995+
void tpm_measure_slrt(void)
996+
{
997+
struct slr_table *slrt = slr_get_table();
998+
999+
if ( slrt->revision == 1 ) {
1000+
/* In revision one of the SLRT, only Intel info table is measured. */
1001+
struct slr_entry_intel_info *intel_info =
1002+
(void *)slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO);
1003+
if ( intel_info == NULL )
1004+
panic("SLRT is missing Intel-specific information!\n");
1005+
1006+
tpm_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)intel_info,
1007+
sizeof(*intel_info), TXT_EVTYPE_SLAUNCH, NULL, 0);
1008+
} else {
1009+
/*
1010+
* slr_get_table() checks that the revision is valid, so we must not
1011+
* get here unless the code is wrong.
1012+
*/
1013+
panic("Unhandled SLRT revision: %d!\n", slrt->revision);
1014+
}
1015+
}
1016+
1017+
static struct slr_entry_policy *slr_get_policy(struct slr_table *slrt)
1018+
{
1019+
struct slr_entry_policy *policy;
1020+
1021+
policy = (struct slr_entry_policy *)
1022+
slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DRTM_POLICY);
1023+
if (policy == NULL)
1024+
panic("SLRT is missing DRTM policy!\n");
1025+
1026+
/* XXX: are newer revisions allowed? */
1027+
if ( policy->revision != SLR_POLICY_REVISION )
1028+
panic("DRTM policy in SLRT is of unsupported revision: %#04x!\n",
1029+
slrt->revision);
1030+
1031+
return policy;
1032+
}
1033+
1034+
static void check_drtm_policy(struct slr_table *slrt,
1035+
struct slr_entry_policy *policy,
1036+
struct slr_policy_entry *policy_entry,
1037+
const multiboot_info_t *mbi)
1038+
{
1039+
uint32_t i;
1040+
module_t *mods;
1041+
uint32_t num_mod_entries;
1042+
1043+
if ( policy->nr_entries < 2 )
1044+
panic("DRTM policy in SLRT contains less than 2 entries (%d)!\n",
1045+
policy->nr_entries);
1046+
1047+
/* MBI policy entry must be the first one, so that measuring order matches
1048+
* policy order. */
1049+
if ( policy_entry[0].entity_type != SLR_ET_MULTIBOOT2_INFO )
1050+
panic("First entry of DRTM policy in SLRT is not MBI: %#04x!\n",
1051+
policy_entry[0].entity_type);
1052+
if ( policy_entry[0].pcr != DRTM_DATA_PCR )
1053+
panic("MBI was measured to %d instead of %d PCR!\n", DRTM_DATA_PCR,
1054+
policy_entry[0].pcr);
1055+
1056+
/* SLRT policy entry must be the second one. */
1057+
if ( policy_entry[1].entity_type != SLR_ET_SLRT )
1058+
panic("Second entry of DRTM policy in SLRT is not SLRT: %#04x!\n",
1059+
policy_entry[1].entity_type);
1060+
if ( policy_entry[1].pcr != DRTM_DATA_PCR )
1061+
panic("SLRT was measured to %d instead of %d PCR!\n", DRTM_DATA_PCR,
1062+
policy_entry[1].pcr);
1063+
if ( policy_entry[1].entity != (uint64_t)__pa(slrt) )
1064+
panic("SLRT address (%#08lx) differes from its DRTM entry (%#08lx)\n",
1065+
__pa(slrt), policy_entry[1].entity);
1066+
1067+
mods = __va(mbi->mods_addr);
1068+
for ( i = 0; i < mbi->mods_count; i++ ) {
1069+
uint16_t j;
1070+
uint64_t start = mods[i].mod_start;
1071+
uint64_t size = mods[i].mod_end - mods[i].mod_start;
1072+
1073+
for ( j = 0; j < policy->nr_entries; j++ ) {
1074+
if ( policy_entry[j].entity_type != SLR_ET_MULTIBOOT2_MODULE )
1075+
continue;
1076+
1077+
if ( policy_entry[j].entity == start &&
1078+
policy_entry[j].size == size )
1079+
break;
1080+
}
1081+
1082+
if ( j >= policy->nr_entries ) {
1083+
panic("Couldn't find Multiboot module \"%s\" (at %d) in DRTM of Secure Launch\n",
1084+
(const char *)__va(mods[i].string), i);
1085+
}
1086+
}
1087+
1088+
num_mod_entries = 0;
1089+
for ( i = 0; i < policy->nr_entries; i++ ) {
1090+
if ( policy_entry[i].entity_type == SLR_ET_MULTIBOOT2_MODULE )
1091+
num_mod_entries++;
1092+
}
1093+
1094+
if ( mbi->mods_count != num_mod_entries ) {
1095+
panic("Unexpected number of Multiboot modules: %d instead of %d\n",
1096+
(int)mbi->mods_count, (int)num_mod_entries);
1097+
}
1098+
}
1099+
1100+
void tpm_process_drtm_policy(const multiboot_info_t *mbi)
1101+
{
1102+
struct slr_table *slrt;
1103+
struct slr_entry_policy *policy;
1104+
struct slr_policy_entry *policy_entry;
1105+
uint16_t i;
1106+
1107+
slrt = slr_get_table();
1108+
1109+
policy = slr_get_policy(slrt);
1110+
policy_entry = (struct slr_policy_entry *)
1111+
((uint8_t *)policy + sizeof(*policy));
1112+
1113+
check_drtm_policy(slrt, policy, policy_entry, mbi);
1114+
/* MBI was measured in tpm_extend_mbi(). */
1115+
policy_entry[0].flags |= SLR_POLICY_FLAG_MEASURED;
1116+
/* SLRT was measured in tpm_measure_slrt(). */
1117+
policy_entry[1].flags |= SLR_POLICY_FLAG_MEASURED;
1118+
1119+
for ( i = 2; i < policy->nr_entries; i++ ) {
1120+
uint64_t start = policy_entry[i].entity;
1121+
uint64_t size = policy_entry[i].size;
1122+
1123+
/* No already measured entries are expected here. */
1124+
if ( policy_entry[i].flags & SLR_POLICY_FLAG_MEASURED )
1125+
panic("DRTM entry at %d was measured out of order!\n", i);
1126+
1127+
switch ( policy_entry[i].entity_type ) {
1128+
case SLR_ET_MULTIBOOT2_INFO:
1129+
panic("Duplicated MBI entry in DRTM of Secure Launch at %d\n", i);
1130+
case SLR_ET_SLRT:
1131+
panic("Duplicated SLRT entry in DRTM of Secure Launch at %d\n", i);
1132+
1133+
case SLR_ET_UNSPECIFIED:
1134+
case SLR_ET_BOOT_PARAMS:
1135+
case SLR_ET_SETUP_DATA:
1136+
case SLR_ET_CMDLINE:
1137+
case SLR_ET_UEFI_MEMMAP:
1138+
case SLR_ET_RAMDISK:
1139+
case SLR_ET_MULTIBOOT2_MODULE:
1140+
case SLR_ET_TXT_OS2MLE:
1141+
/* Measure this entry below. */
1142+
break;
1143+
1144+
case SLR_ET_UNUSED:
1145+
/* Skip this entry. */
1146+
continue;
1147+
}
1148+
1149+
if ( policy_entry[i].flags & SLR_POLICY_IMPLICIT_SIZE )
1150+
panic("Unexpected implicitly-sized DRTM entry of Secure Launch at %d\n",
1151+
i);
1152+
1153+
map_l2(start, size);
1154+
tpm_hash_extend(DRTM_LOC, policy_entry[i].pcr, __va(start), size,
1155+
TXT_EVTYPE_SLAUNCH, (uint8_t *)policy_entry[i].evt_info,
1156+
strnlen(policy_entry[i].evt_info,
1157+
TPM_EVENT_INFO_LENGTH));
1158+
1159+
policy_entry[i].flags |= SLR_POLICY_FLAG_MEASURED;
1160+
}
1161+
}
9661162
#endif

0 commit comments

Comments
 (0)