Skip to content

Commit cf90ad6

Browse files
committed
arch/x86: process DRTM policy
Go through entires in the DRTM policy of SLRT to hash and extend data that they describe into corresponding PCRs. Addresses are being zeroed on measuring platform-specific data to prevent measurements from changing when the only thing that has changed is an address. Addresses can vary due to bootloader, firmware or user doing something differently or just if GRUB gets bigger in size due to inclusion of more modules and ends up offsetting newly allocated memory. Signed-off-by: Krystian Hebel <[email protected]> Signed-off-by: Sergii Dmytruk <[email protected]>
1 parent bd81df3 commit cf90ad6

File tree

3 files changed

+236
-0
lines changed

3 files changed

+236
-0
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <xen/slr_table.h>
1111
#include <xen/types.h>
12+
#include <asm/bootinfo.h>
1213

1314
#define DRTM_LOC 2
1415
#define DRTM_CODE_PCR 17
@@ -58,6 +59,18 @@ void slaunch_map_mem_regions(void);
5859
/* Marks regions of memory as used to avoid their corruption. */
5960
void slaunch_reserve_mem_regions(void);
6061

62+
/* Measures essential parts of SLR table before making use of them. */
63+
void slaunch_measure_slrt(void);
64+
65+
/*
66+
* Takes measurements of DRTM policy entries except for MBI and SLRT which
67+
* should have been measured by the time this is called. Also performs sanity
68+
* checks of the policy and panics on failure. In particular, the function
69+
* verifies that DRTM is consistent with modules obtained from MultibootInfo
70+
* (MBI) and written to struct boot_info in setup.c.
71+
*/
72+
void slaunch_process_drtm_policy(const struct boot_info *bi);
73+
6174
/*
6275
* This helper function is used to map memory using L2 page tables by aligning
6376
* mapped regions to 2MB. This way page allocator (which at this point isn't

xen/arch/x86/setup.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,13 @@ void asmlinkage __init noreturn __start_xen(void)
13961396
if ( slaunch_active )
13971397
{
13981398
slaunch_map_mem_regions();
1399+
1400+
/*
1401+
* SLRT needs to be measured here because it is used by init_e820(), the
1402+
* rest is measured slightly below by slaunch_process_drtm_policy().
1403+
*/
1404+
slaunch_measure_slrt();
1405+
13991406
slaunch_reserve_mem_regions();
14001407
}
14011408

@@ -1417,6 +1424,14 @@ void asmlinkage __init noreturn __start_xen(void)
14171424
/* Create a temporary copy of the E820 map. */
14181425
memcpy(&boot_e820, &e820, sizeof(e820));
14191426

1427+
/*
1428+
* Process all yet unmeasured DRTM entries after E820 initialization to not
1429+
* do this while memory is uncached (too slow). This must also happen before
1430+
* modules are relocated or used.
1431+
*/
1432+
if ( slaunch_active )
1433+
slaunch_process_drtm_policy(bi);
1434+
14201435
/* Early kexec reservation (explicit static start address). */
14211436
nr_pages = 0;
14221437
for ( i = 0; i < e820.nr_map; i++ )

xen/arch/x86/slaunch.c

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
#include <xen/macros.h>
1010
#include <xen/mm.h>
1111
#include <xen/types.h>
12+
#include <asm/bootinfo.h>
1213
#include <asm/e820.h>
1314
#include <asm/intel_txt.h>
1415
#include <asm/page.h>
16+
#include <asm/processor.h>
1517
#include <asm/slaunch.h>
1618
#include <asm/tpm.h>
1719

@@ -106,3 +108,209 @@ void __init slaunch_reserve_mem_regions(void)
106108
/* Vendor-specific part. */
107109
txt_reserve_mem_regions();
108110
}
111+
112+
void slaunch_measure_slrt(void)
113+
{
114+
struct slr_table *slrt = get_slrt();
115+
116+
if ( slrt->revision == 1 )
117+
{
118+
/*
119+
* In revision one of the SLRT, only platform-specific info table is
120+
* measured.
121+
*/
122+
struct slr_entry_intel_info tmp;
123+
struct slr_entry_intel_info *entry;
124+
125+
entry = (struct slr_entry_intel_info *)
126+
slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO);
127+
if ( entry == NULL )
128+
panic("SLRT is missing Intel-specific information!\n");
129+
130+
tmp = *entry;
131+
tmp.boot_params_base = 0;
132+
tmp.txt_heap = 0;
133+
134+
tpm_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)&tmp,
135+
sizeof(tmp), DLE_EVTYPE_SLAUNCH, NULL, 0);
136+
}
137+
else
138+
{
139+
/*
140+
* get_slrt() checks that the revision is valid, so we must not get
141+
* here unless the code is wrong.
142+
*/
143+
panic("Unhandled SLRT revision: %d!\n", slrt->revision);
144+
}
145+
}
146+
147+
static struct slr_entry_policy *slr_get_policy(struct slr_table *slrt)
148+
{
149+
struct slr_entry_policy *policy;
150+
151+
policy = (struct slr_entry_policy *)
152+
slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DRTM_POLICY);
153+
if (policy == NULL)
154+
panic("SLRT is missing DRTM policy!\n");
155+
156+
/* XXX: are newer revisions allowed? */
157+
if ( policy->revision != SLR_POLICY_REVISION )
158+
panic("DRTM policy in SLRT is of unsupported revision: %#04x!\n",
159+
slrt->revision);
160+
161+
return policy;
162+
}
163+
164+
static void check_slrt_policy_entry(struct slr_policy_entry *policy_entry,
165+
int idx,
166+
struct slr_table *slrt)
167+
{
168+
if ( policy_entry->entity_type != SLR_ET_SLRT )
169+
panic("Expected DRTM policy entry #%d to describe SLRT, got %#04x!\n",
170+
idx, policy_entry->entity_type);
171+
if ( policy_entry->pcr != DRTM_DATA_PCR )
172+
panic("SLRT was measured to PCR-%d instead of PCR-%d!\n", DRTM_DATA_PCR,
173+
policy_entry->pcr);
174+
if ( policy_entry->entity != (uint64_t)__pa(slrt) )
175+
panic("SLRT address (%#08lx) differs from its DRTM entry (%#08lx)\n",
176+
__pa(slrt), policy_entry->entity);
177+
}
178+
179+
/* Returns number of policy entries that were already measured. */
180+
static unsigned int check_drtm_policy(struct slr_table *slrt,
181+
struct slr_entry_policy *policy,
182+
struct slr_policy_entry *policy_entry,
183+
const struct boot_info *bi)
184+
{
185+
uint32_t i;
186+
uint32_t num_mod_entries;
187+
188+
if ( policy->nr_entries < 2 )
189+
panic("DRTM policy in SLRT contains less than 2 entries (%d)!\n",
190+
policy->nr_entries);
191+
192+
/*
193+
* MBI policy entry must be the first one, so that measuring order matches
194+
* policy order.
195+
*/
196+
if ( policy_entry[0].entity_type != SLR_ET_MULTIBOOT2_INFO )
197+
panic("First entry of DRTM policy in SLRT is not MBI: %#04x!\n",
198+
policy_entry[0].entity_type);
199+
if ( policy_entry[0].pcr != DRTM_DATA_PCR )
200+
panic("MBI was measured to %d instead of %d PCR!\n", DRTM_DATA_PCR,
201+
policy_entry[0].pcr);
202+
203+
/* SLRT policy entry must be the second one. */
204+
check_slrt_policy_entry(&policy_entry[1], 1, slrt);
205+
206+
for ( i = 0; i < bi->nr_modules; i++ )
207+
{
208+
uint16_t j;
209+
const struct boot_module *mod = &bi->mods[i];
210+
211+
if (mod->relocated || mod->released)
212+
{
213+
panic("Multiboot module \"%s\" (at %d) was consumed before measurement\n",
214+
(const char *)__va(mod->cmdline_pa), i);
215+
}
216+
217+
for ( j = 2; j < policy->nr_entries; j++ )
218+
{
219+
if ( policy_entry[j].entity_type != SLR_ET_MULTIBOOT2_MODULE )
220+
continue;
221+
222+
if ( policy_entry[j].entity == mod->start &&
223+
policy_entry[j].size == mod->size )
224+
break;
225+
}
226+
227+
if ( j >= policy->nr_entries )
228+
{
229+
panic("Couldn't find Multiboot module \"%s\" (at %d) in DRTM of Secure Launch\n",
230+
(const char *)__va(mod->cmdline_pa), i);
231+
}
232+
}
233+
234+
num_mod_entries = 0;
235+
for ( i = 0; i < policy->nr_entries; i++ )
236+
{
237+
if ( policy_entry[i].entity_type == SLR_ET_MULTIBOOT2_MODULE )
238+
num_mod_entries++;
239+
}
240+
241+
if ( bi->nr_modules != num_mod_entries )
242+
{
243+
panic("Unexpected number of Multiboot modules: %d instead of %d\n",
244+
(int)bi->nr_modules, (int)num_mod_entries);
245+
}
246+
247+
/*
248+
* MBI was measured in tpm_extend_mbi().
249+
* SLRT was measured in tpm_measure_slrt().
250+
*/
251+
return 2;
252+
}
253+
254+
void slaunch_process_drtm_policy(const struct boot_info *bi)
255+
{
256+
struct slr_table *slrt;
257+
struct slr_entry_policy *policy;
258+
struct slr_policy_entry *policy_entry;
259+
uint16_t i;
260+
unsigned int measured;
261+
262+
slrt = get_slrt();
263+
264+
policy = slr_get_policy(slrt);
265+
policy_entry = (struct slr_policy_entry *)
266+
((uint8_t *)policy + sizeof(*policy));
267+
268+
measured = check_drtm_policy(slrt, policy, policy_entry, bi);
269+
for ( i = 0; i < measured; i++ )
270+
policy_entry[i].flags |= SLR_POLICY_FLAG_MEASURED;
271+
272+
for ( i = measured; i < policy->nr_entries; i++ )
273+
{
274+
uint64_t start = policy_entry[i].entity;
275+
uint64_t size = policy_entry[i].size;
276+
277+
/* No already measured entries are expected here. */
278+
if ( policy_entry[i].flags & SLR_POLICY_FLAG_MEASURED )
279+
panic("DRTM entry at %d was measured out of order!\n", i);
280+
281+
switch ( policy_entry[i].entity_type )
282+
{
283+
case SLR_ET_MULTIBOOT2_INFO:
284+
panic("Duplicated MBI entry in DRTM of Secure Launch at %d\n", i);
285+
case SLR_ET_SLRT:
286+
panic("Duplicated SLRT entry in DRTM of Secure Launch at %d\n", i);
287+
288+
case SLR_ET_UNSPECIFIED:
289+
case SLR_ET_BOOT_PARAMS:
290+
case SLR_ET_SETUP_DATA:
291+
case SLR_ET_CMDLINE:
292+
case SLR_ET_UEFI_MEMMAP:
293+
case SLR_ET_RAMDISK:
294+
case SLR_ET_MULTIBOOT2_MODULE:
295+
case SLR_ET_TXT_OS2MLE:
296+
/* Measure this entry below. */
297+
break;
298+
299+
case SLR_ET_UNUSED:
300+
/* Skip this entry. */
301+
continue;
302+
}
303+
304+
if ( policy_entry[i].flags & SLR_POLICY_IMPLICIT_SIZE )
305+
panic("Unexpected implicitly-sized DRTM entry of Secure Launch at %d (type %d, info: %s)\n",
306+
i, policy_entry[i].entity_type, policy_entry[i].evt_info);
307+
308+
slaunch_map_l2(start, size);
309+
tpm_hash_extend(DRTM_LOC, policy_entry[i].pcr, __va(start), size,
310+
DLE_EVTYPE_SLAUNCH, (uint8_t *)policy_entry[i].evt_info,
311+
strnlen(policy_entry[i].evt_info,
312+
TPM_EVENT_INFO_LENGTH));
313+
314+
policy_entry[i].flags |= SLR_POLICY_FLAG_MEASURED;
315+
}
316+
}

0 commit comments

Comments
 (0)