Skip to content

Commit 8c3e899

Browse files
krystian-hebelrossphilipson
authored andcommitted
main: switch to SLRT
This removes different handling between boot protocols. Everything is reduced to one range of consecutive memory for DLME, as well as pointer to the entry point, which is measured to PCR 17 as an offset from DLME base to avoid attacks based on jumping to different parts of DLME. Signed-off-by: Krystian Hebel <[email protected]>
1 parent cc77fcf commit 8c3e899

File tree

2 files changed

+30
-215
lines changed

2 files changed

+30
-215
lines changed

head.S

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ GLOBAL(_entry)
6161

6262
/* Check if we have enough space available for stack. */
6363
lea bootloader_data(%ebp), %ebx
64-
/* TODO: below uses bootloader_data.size, must be changed for SLRT. */
65-
movzwl %ss:2(%ebx), %edx
64+
mov %ss:8(%ebx), %edx /* bootloader_data.size */
6665
add %edx, %ebx
6766
add $MAX_STACK_SIZE, %ebx
6867
cmp %ebx, %esp

main.c

Lines changed: 29 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#include <linux-bootparams.h>
2929
#include <event_log.h>
3030
#include <multiboot2.h>
31-
#include <tags.h>
31+
#include <slrt.h>
3232
#include <string.h>
3333
#include <printk.h>
3434
#include <dev.h>
@@ -276,181 +276,12 @@ typedef struct {
276276
void *dlme_arg; /* %edx */
277277
} asm_return_t;
278278

279-
static asm_return_t skl_linux(struct tpm *tpm, struct skl_tag_boot_linux *skl_tag)
280-
{
281-
struct boot_params *bp;
282-
struct kernel_info *ki;
283-
struct mle_header *mle_header;
284-
void *dlme_entry;
285-
286-
/* The Zero Page with the boot_params and legacy header */
287-
bp = _p(skl_tag->zero_page);
288-
289-
print("\ncode32_start ");
290-
print_p(_p(bp->code32_start));
291-
292-
if ( bp->version < 0x020f
293-
|| (ki = get_kernel_info(bp)) == NULL
294-
|| ki->header != KERNEL_INFO_HEADER
295-
|| (mle_header = get_mle_hdr(bp, ki)) == NULL
296-
|| mle_header->uuid[0] != MLE_UUID0
297-
|| mle_header->uuid[1] != MLE_UUID1
298-
|| mle_header->uuid[2] != MLE_UUID2
299-
|| mle_header->uuid[3] != MLE_UUID3 )
300-
{
301-
print("\nKernel is too old or MLE header not present.\n");
302-
reboot();
303-
}
304-
305-
print("\nmle_header\n");
306-
hexdump(mle_header, sizeof(struct mle_header));
307-
308-
dlme_entry = get_kernel_entry(bp, mle_header);
309-
310-
if ( dlme_entry == NULL )
311-
{
312-
print("\nBad kernel entry in MLE header.\n");
313-
reboot();
314-
}
315-
316-
/* extend TB Loader code segment into PCR17 */
317-
extend_pcr(tpm, _p(bp->code32_start), bp->syssize << 4, 17,
318-
"Measured Kernel into PCR17");
319-
320-
tpm_relinquish_locality(tpm);
321-
free_tpm(tpm);
322-
323-
/* End of the line, off to the protected mode entry into the kernel */
324-
print("dlme_entry:\n");
325-
hexdump(dlme_entry, 0x100);
326-
print("dlme_arg:\n");
327-
hexdump(bp, 0x280);
328-
print("skl_base:\n");
329-
hexdump(_start, 0x100);
330-
print("device_table:\n");
331-
hexdump(device_table, 0x100);
332-
print("command_buf:\n");
333-
hexdump(command_buf, 0x1000);
334-
print("event_log:\n");
335-
hexdump(event_log, 0x1000);
336-
337-
print("skl_main() is about to exit\n");
338-
339-
return (asm_return_t){ dlme_entry, bp };
340-
}
341-
342-
static asm_return_t skl_multiboot2(struct tpm *tpm, struct skl_tag_boot_mb2 *skl_tag)
343-
{
344-
void *kernel_entry;
345-
u32 kernel_size, mbi_len;
346-
struct multiboot_tag *tag;
347-
int i;
348-
349-
/* This is MBI header, not a tag, but their structures are similar enough.
350-
* Note that 'size' offsets are reversed in those two! */
351-
tag = _p(skl_tag->mbi);
352-
353-
/* skl_tag->kernel_size is either passed size of kernel from bootloader
354-
* or 0 */
355-
kernel_size = skl_tag->kernel_size;
356-
kernel_entry = _p(skl_tag->kernel_entry);
357-
358-
/* Extend PCR18 with MBI structure's hash; this includes all cmdlines.
359-
* Use 'type' and not 'size', as their offsets are swapped in the header! */
360-
mbi_len = tag->type;
361-
extend_pcr(tpm, &tag, mbi_len, 18, "Measured MBI into PCR18");
362-
363-
tag++;
364-
365-
while ( tag->type )
366-
{
367-
if ( kernel_entry && kernel_size )
368-
break;
369-
370-
/* If the entry point wasn't passed by a bootloader, we can only assume
371-
* that it starts at the kernel base address (true at least for Xen) */
372-
if ( !kernel_entry && tag->type == MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR )
373-
{
374-
struct multiboot_tag_load_base_addr *ba = (void *)tag;
375-
kernel_entry = _p(ba->load_base_addr);
376-
print("kernel_entry ");
377-
print_p(kernel_entry);
378-
print("\n");
379-
}
380-
381-
/* This assumes that ELF has only one PROGBITS section, and that section
382-
* is the first one (i.e. it is loaded at load_base_addr). It is true
383-
* for Xen, but may not always the case.
384-
*
385-
* Also, GRUB2 creates this tag after all module tags, so separate loop
386-
* is needed for consistent order of PCR extension operations. */
387-
if ( !kernel_size && tag->type == MULTIBOOT_TAG_TYPE_ELF_SECTIONS )
388-
{
389-
struct multiboot_tag_elf_sections *es_tag = (void *)tag;
390-
for ( i = 0; i < es_tag->num; i++ )
391-
{
392-
Elf32_Shdr *sh = (void *)&es_tag->sections[es_tag->entsize * i];
393-
if ( sh->sh_type == SHT_PROGBITS )
394-
{
395-
kernel_size = sh->sh_size;
396-
print("kernel_size ");
397-
print_p(_p(kernel_size));
398-
print("\n");
399-
break;
400-
}
401-
}
402-
}
403-
404-
tag = multiboot_next_tag(tag);
405-
}
406-
407-
extend_pcr(tpm, kernel_entry, kernel_size, 17,
408-
"Measured Kernel into PCR17");
409-
410-
tag = _p(skl_tag->mbi);
411-
tag++;
412-
413-
while ( tag->type )
414-
{
415-
if ( tag->type == MULTIBOOT_TAG_TYPE_MODULE )
416-
{
417-
struct multiboot_tag_module *mod = (void *)tag;
418-
print("Module '");
419-
print(mod->cmdline);
420-
print("' [");
421-
print_p(_p(mod->mod_start));
422-
print_p(_p(mod->mod_end));
423-
print("]\n");
424-
extend_pcr(tpm, _p(mod->mod_start), mod->mod_end - mod->mod_start,
425-
17, mod->cmdline);
426-
}
427-
428-
tag = multiboot_next_tag(tag);
429-
}
430-
431-
/* Safety checks */
432-
if ( tag->size != 8
433-
|| _p(multiboot_next_tag(tag)) > _p(skl_tag->mbi) + mbi_len )
434-
{
435-
print("MBI safety checks failed\n");
436-
reboot();
437-
}
438-
439-
return (asm_return_t){ kernel_entry, _p(skl_tag->mbi) };
440-
}
441-
442-
static asm_return_t skl_simple_payload(struct tpm *tpm, struct skl_tag_boot_simple_payload *skl_tag)
443-
{
444-
extend_pcr(tpm, _p(skl_tag->base), skl_tag->size, 17, "Measured payload into PCR17");
445-
446-
return (asm_return_t){ _p(skl_tag->entry), _p(skl_tag->arg) };
447-
}
448-
449279
asm_return_t skl_main(void)
450280
{
451-
asm_return_t ret;
452281
struct tpm *tpm;
453-
struct skl_tag_hdr *t = (struct skl_tag_hdr*) &bootloader_data;
282+
struct slr_entry_dl_info *dl_info;
283+
asm_return_t ret;
284+
u32 entry_offset;
454285

455286
/*
456287
* Now in 64b mode, paging is setup. This is the launching point. We can
@@ -464,16 +295,6 @@ asm_return_t skl_main(void)
464295
/* Disable memory protection and setup IOMMU */
465296
iommu_setup();
466297

467-
if ( t->type != SKL_TAG_TAGS_SIZE
468-
|| t->len != sizeof(struct skl_tag_tags_size)
469-
|| end_of_tags() > _p(_start + SLB_SIZE)
470-
|| (t = next_of_type(t, SKL_TAG_END)) == NULL
471-
|| _p(t) + t->len != end_of_tags())
472-
{
473-
print("Bad bootloader data format\n");
474-
reboot();
475-
}
476-
477298
/*
478299
* TODO Note these functions can fail but there is no clear way to
479300
* report the error unless SKINIT has some resource to do this. For
@@ -483,36 +304,39 @@ asm_return_t skl_main(void)
483304
tpm_request_locality(tpm, 2);
484305
event_log_init(tpm);
485306

486-
/* Now that we have TPM and event log, measure bootloader data */
487-
extend_pcr(tpm, &bootloader_data, bootloader_data.size, 18,
488-
"Measured bootloader data into PCR18");
489-
490-
t = next_of_class(&bootloader_data, SKL_TAG_BOOT_CLASS);
491-
if ( t == NULL || next_of_class(t, SKL_TAG_BOOT_CLASS) != NULL )
307+
/*
308+
* Now that we have TPM and event log, we can begin measuring. For parity
309+
* with what TXT does, we leave most of measuring for the DLME. Here, we
310+
* only have to measure DLME itself, as well as entry point offset - only
311+
* both of those measurements together tell that the proper code has been
312+
* started. Entry point offset may come from MLE header included in DLME,
313+
* but we can't trust that the bootloader passed it without modification.
314+
*/
315+
dl_info = next_entry_with_tag(NULL, SLR_ENTRY_DL_INFO);
316+
317+
if ( dl_info == NULL
318+
|| dl_info->hdr.size != sizeof(*dl_info)
319+
|| end_of_slrt() < _p(&dl_info[1])
320+
|| dl_info->dlme_base >= 0x100000000ULL
321+
|| dl_info->dlme_base + dl_info->dlme_size >= 0x100000000ULL
322+
|| dl_info->dlme_entry >= dl_info->dlme_size
323+
|| dl_info->bl_context.bootloader != SLR_BOOTLOADER_GRUB )
492324
{
493-
print("No boot tag or multiple boot tags\n");
325+
print("Bad bootloader data format\n");
494326
reboot();
495327
}
496328

497-
switch( t->type )
498-
{
499-
case SKL_TAG_BOOT_LINUX:
500-
ret = skl_linux(tpm, (struct skl_tag_boot_linux *)t);
501-
break;
502-
case SKL_TAG_BOOT_MB2:
503-
ret = skl_multiboot2(tpm, (struct skl_tag_boot_mb2 *)t);
504-
break;
505-
case SKL_TAG_BOOT_SIMPLE:
506-
ret = skl_simple_payload(tpm, (struct skl_tag_boot_simple_payload *)t);
507-
break;
508-
default:
509-
print("Unknown kernel boot protocol\n");
510-
reboot();
511-
}
329+
entry_offset = dl_info->dlme_entry;
330+
extend_pcr(tpm, &entry_offset, sizeof(entry_offset), 17,
331+
"DLME entry offset");
332+
extend_pcr(tpm, _p(dl_info->dlme_base), dl_info->dlme_size, 17, "DLME");
512333

513334
tpm_relinquish_locality(tpm);
514335
free_tpm(tpm);
515336

337+
ret.dlme_entry = _p(dl_info->dlme_base + dl_info->dlme_entry);
338+
ret.dlme_arg = _p(dl_info->bl_context.context);
339+
516340
/* End of the line, off to the protected mode entry into the kernel */
517341
print("dlme_entry:\n");
518342
hexdump(ret.dlme_entry, 0x100);
@@ -523,14 +347,6 @@ asm_return_t skl_main(void)
523347
print("bootloader_data:\n");
524348
hexdump(&bootloader_data, bootloader_data.size);
525349

526-
t = next_of_type(&bootloader_data, SKL_TAG_EVENT_LOG);
527-
if ( t != NULL )
528-
{
529-
print("TPM event log:\n");
530-
hexdump(_p(((struct skl_tag_evtlog *)t)->address),
531-
((struct skl_tag_evtlog *)t)->size);
532-
}
533-
534350
print("skl_main() is about to exit\n");
535351

536352
return ret;

0 commit comments

Comments
 (0)