[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 8/9] stubdom/grub: verify vTPM label if requested
This adds an optional argument --vtpm-label=<label> to the pv-grub command line. If specified, a vtpm device must be connected to the pv-grub domain and the backend of this device must have the given XSM label (which may start with a * to indicate a wildcard). Verifying the label of the vTPM before sending measurements prevents a disaggregated control domain that has access to xenstore but not to the guest domains from causing the measurements performed by pv-grub to be discarded, allowing the forgery of arbitrary kernel measurements in the TPM. Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> Cc: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx> --- stubdom/grub/kexec.c | 58 ++++++++++++++++++++++++++++++++++++++++++-------- stubdom/grub/mini-os.c | 8 ++++++- stubdom/grub/mini-os.h | 2 ++ 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/stubdom/grub/kexec.c b/stubdom/grub/kexec.c index cef357e..dc8db81 100644 --- a/stubdom/grub/kexec.c +++ b/stubdom/grub/kexec.c @@ -68,6 +68,14 @@ struct pcr_extend_cmd { unsigned char hash[20]; } __attribute__((packed)); +struct pcr_extend_rsp { + uint16_t tag; + uint32_t size; + uint32_t status; + + unsigned char hash[20]; +} __attribute__((packed)); + /* Not imported from polarssl's header since the prototype unhelpfully defines * the input as unsigned char, which causes pointer type mismatches */ void sha1(const void *input, size_t ilen, unsigned char output[20]); @@ -135,20 +143,49 @@ int kexec_allocate(struct xc_dom_image *dom, xen_vaddr_t up_to) return 0; } +/* Filled from mini-os command line or left as NULL */ +char *vtpm_label; + static void tpm_hash2pcr(struct xc_dom_image *dom, char *cmdline) { struct tpmfront_dev* tpm = init_tpmfront(NULL); - uint8_t *resp; + struct pcr_extend_rsp *resp; size_t resplen = 0; struct pcr_extend_cmd cmd; + int rv; - /* If all guests have access to a vTPM, it may be useful to replace this - * with ASSERT(tpm) to prevent configuration errors from allowing a guest - * to boot without a TPM (or with a TPM that has not been sent any - * measurements, which could allow forging the measurements). + /* + * If vtpm_label was specified on the command line, require a vTPM to be + * attached and for the domain providing the vTPM to have the given + * label. */ - if (!tpm) + if (vtpm_label) { + char ctx[128]; + if (!tpm) { + printf("No TPM found and vtpm_label specified, aborting!\n"); + do_exit(); + } + rv = evtchn_get_peercontext(tpm->evtchn, ctx, sizeof(ctx) - 1); + if (rv < 0) { + printf("Could not verify vtpm_label: %d\n", rv); + do_exit(); + } + ctx[127] = 0; + rv = strcmp(ctx, vtpm_label); + if (rv && vtpm_label[0] == '*') { + int match_len = strlen(vtpm_label) - 1; + int offset = strlen(ctx) - match_len; + if (offset > 0) + rv = strcmp(ctx + offset, vtpm_label + 1); + } + + if (rv) { + printf("Mismatched vtpm_label: '%s' != '%s'\n", ctx, vtpm_label); + do_exit(); + } + } else if (!tpm) { return; + } cmd.tag = bswap_16(TPM_TAG_RQU_COMMAND); cmd.size = bswap_32(sizeof(cmd)); @@ -156,15 +193,18 @@ static void tpm_hash2pcr(struct xc_dom_image *dom, char *cmdline) cmd.pcr = bswap_32(4); // PCR #4 for kernel sha1(dom->kernel_blob, dom->kernel_size, cmd.hash); - tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen); + rv = tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), (void*)&resp, &resplen); + ASSERT(rv == 0 && resp->status == 0); cmd.pcr = bswap_32(5); // PCR #5 for cmdline sha1(cmdline, strlen(cmdline), cmd.hash); - tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen); + rv = tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), (void*)&resp, &resplen); + ASSERT(rv == 0 && resp->status == 0); cmd.pcr = bswap_32(5); // PCR #5 for initrd sha1(dom->ramdisk_blob, dom->ramdisk_size, cmd.hash); - tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen); + rv = tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), (void*)&resp, &resplen); + ASSERT(rv == 0 && resp->status == 0); shutdown_tpmfront(tpm); } diff --git a/stubdom/grub/mini-os.c b/stubdom/grub/mini-os.c index 9d4bcc7..4fc052a 100644 --- a/stubdom/grub/mini-os.c +++ b/stubdom/grub/mini-os.c @@ -735,8 +735,14 @@ void __attribute__ ((noreturn)) grub_reboot (void) * for grub's 32bit pointers to work */ char grub_scratch_mem[SCRATCH_MEMSIZE] __attribute__((aligned(PAGE_SIZE))); -int main(int argc, char *argv[]) +int main(int argc, char **argv) { + if (argc > 1 && memcmp(argv[1], "--vtpm-label=", 13) == 0) { + vtpm_label = argv[1] + 13; + argc--; + argv++; + } + if (argc > 1) { strncpy(config_file, argv[1], sizeof(config_file) - 1); config_file[sizeof(config_file) - 1] = 0; diff --git a/stubdom/grub/mini-os.h b/stubdom/grub/mini-os.h index 6c68441..9ec2bda 100644 --- a/stubdom/grub/mini-os.h +++ b/stubdom/grub/mini-os.h @@ -3,3 +3,5 @@ extern struct blkfront_dev **blk_dev; extern struct netfront_dev *net_dev; extern struct kbdfront_dev *kbd_dev; extern struct fbfront_dev *fb_dev; + +extern char* vtpm_label; -- 1.9.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |