From d9df6e93f35dcab8b6b173845754fc8b2ef548fe Mon Sep 17 00:00:00 2001 From: Qi Yadong Date: Mon, 8 Oct 2018 15:19:07 +0800 Subject: [PATCH] HV: parse seed from ABL ABL pass seed_lists to HV through different interface/structures. So, in this patch, add interface to retrieve seed from ABL and refactor the seed parsing logic. Tracked-On: #1488 Signed-off-by: Qi Yadong Acked-by: Zhu Bing --- hypervisor/Makefile | 3 +- hypervisor/boot/sbl/abl_seed_parse.c | 155 +++++++++++++++ hypervisor/boot/sbl/hob_parse.c | 69 ------- hypervisor/boot/sbl/multiboot.c | 106 ++-------- hypervisor/boot/sbl/sbl_seed_parse.c | 194 +++++++++++++++++++ hypervisor/include/arch/x86/abl_seed_parse.h | 12 ++ hypervisor/include/arch/x86/hob_parse.h | 46 ----- hypervisor/include/arch/x86/sbl_seed_parse.h | 12 ++ 8 files changed, 391 insertions(+), 206 deletions(-) create mode 100644 hypervisor/boot/sbl/abl_seed_parse.c delete mode 100644 hypervisor/boot/sbl/hob_parse.c create mode 100644 hypervisor/boot/sbl/sbl_seed_parse.c create mode 100644 hypervisor/include/arch/x86/abl_seed_parse.h delete mode 100644 hypervisor/include/arch/x86/hob_parse.h create mode 100644 hypervisor/include/arch/x86/sbl_seed_parse.h diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 75814a8f2..2779cef7a 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -193,7 +193,8 @@ C_SRCS += bsp/$(CONFIG_PLATFORM)/cmdline.c else ifeq ($(CONFIG_PLATFORM), sbl) C_SRCS += boot/sbl/multiboot.c -C_SRCS += boot/sbl/hob_parse.c +C_SRCS += boot/sbl/sbl_seed_parse.c +C_SRCS += boot/sbl/abl_seed_parse.c endif endif diff --git a/hypervisor/boot/sbl/abl_seed_parse.c b/hypervisor/boot/sbl/abl_seed_parse.c new file mode 100644 index 000000000..e7ce9992c --- /dev/null +++ b/hypervisor/boot/sbl/abl_seed_parse.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define ABL_SEED_LEN 32U +struct abl_seed_info { + uint8_t svn; + uint8_t reserved[3]; + uint8_t seed[ABL_SEED_LEN]; +}; + +#define ABL_SEED_LIST_MAX 4U +struct dev_sec_info { + uint32_t size_of_this_struct; + uint32_t version; + uint32_t num_seeds; + struct abl_seed_info seed_list[ABL_SEED_LIST_MAX]; +}; + +static const char *dev_sec_info_arg= "dev_sec_info.param_addr="; + +static void parse_seed_list_abl(void *param_addr) +{ + uint32_t i; + uint32_t legacy_seed_index = 0U; + struct seed_info dseed_list[BOOTLOADER_SEED_MAX_ENTRIES]; + struct dev_sec_info *sec_info = (struct dev_sec_info *)param_addr; + + if (sec_info == NULL) { + goto fail; + } + + if (sec_info->num_seeds < 2U || + sec_info->num_seeds > ABL_SEED_LIST_MAX) { + goto fail; + } + + /* + * The seed_list from ABL contains several seeds which based on SVN + * and one legacy seed which is not based on SVN. The legacy seed's + * svn value is minimum in the seed list. And CSE ensures at least two + * seeds will be generated which will contain the legacy seed. + * Here find the legacy seed index first. + */ + for (i = 1U; i < sec_info->num_seeds; i++) { + if (sec_info->seed_list[i].svn < + sec_info->seed_list[legacy_seed_index].svn) { + legacy_seed_index = i; + } + } + + /* + * Copy out abl_seed for trusty and clear the original seed in memory. + * The SOS requires the legacy seed to derive RPMB key. So skip the + * legacy seed when clear original seed. + */ + (void)memset((void *)dseed_list, 0U, sizeof(dseed_list)); + for (i = 0U; i < sec_info->num_seeds; i++) { + dseed_list[i].cse_svn = sec_info->seed_list[i].svn; + (void)memcpy_s((void *)dseed_list[i].seed, + sizeof(dseed_list[i].seed), + (void *)sec_info->seed_list[i].seed, + sizeof(sec_info->seed_list[i].seed)); + + if (i == legacy_seed_index) { + continue; + } + + (void)memset((void *)sec_info->seed_list[i].seed, 0U, + sizeof(sec_info->seed_list[i].seed)); + } + + trusty_set_dseed((void *)dseed_list, (uint8_t)(sec_info->num_seeds)); + (void)memset((void *)dseed_list, 0U, sizeof(dseed_list)); + return; +fail: + trusty_set_dseed(NULL, 0U); + (void)memset((void *)dseed_list, 0U, sizeof(dseed_list)); +} + +/* + * abl_seed_parse + * + * description: + * This function parse dev_sec_info from cmdline. Mainly on + * 1. parse structure address from cmdline + * 2. call parse_seed_list_abl to parse seed_list + * 3. convert address in the structure from HPA to SOS's GPA + * 4. clear original image_boot_params argument in cmdline since + * original address is HPA. + * + * input: + * vm pointer to vm structure + * cmdline pointer to cmdline string + * out_len the max len of out_arg + * + * output: + * out_arg the argument with SOS's GPA + * + * return value: + * true if parse successfully, otherwise false. + */ +bool abl_seed_parse(struct vm *vm, char *cmdline, char *out_arg, uint32_t out_len) +{ + char *arg, *arg_end; + char *param; + void *param_addr; + uint32_t len; + + if (cmdline == NULL) { + goto fail; + } + + len = strnlen_s(dev_sec_info_arg, MEM_1K); + arg = strstr_s(cmdline, MEM_2K, dev_sec_info_arg, len); + + if (arg == NULL) { + goto fail; + } + + param = arg + len; + param_addr = (void *)hpa2hva(strtoul_hex(param)); + if (param_addr == NULL) { + goto fail; + } + + parse_seed_list_abl(param_addr); + + /* + * Replace original arguments with spaces since SOS's GPA is not + * identity mapped to HPA. The argument will be appended later when + * compose cmdline for SOS. + */ + arg_end = strchr(arg, ' '); + len = (arg_end != NULL) ? (uint32_t)(arg_end - arg) : + strnlen_s(arg, MEM_2K); + (void)memset((void *)arg, ' ', len); + + /* Convert the param_addr to SOS GPA and copy to caller */ + if (out_arg) { + snprintf(out_arg, out_len, "%s0x%X ", + dev_sec_info_arg, hva2gpa(vm, param_addr)); + } + + return true; + +fail: + parse_seed_list_abl(NULL); + return false; +} diff --git a/hypervisor/boot/sbl/hob_parse.c b/hypervisor/boot/sbl/hob_parse.c deleted file mode 100644 index c028af668..000000000 --- a/hypervisor/boot/sbl/hob_parse.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include - -void parse_seed_list(struct seed_list_hob *seed_hob) -{ - uint8_t i; - uint8_t dseed_index = 0U; - struct seed_entry *entry; - struct seed_info dseed_list[BOOTLOADER_SEED_MAX_ENTRIES]; - - if (seed_hob == NULL) { - pr_warn("Invalid seed_list hob pointer. Use fake seed!"); - goto fail; - } - - if (seed_hob->total_seed_count == 0U) { - pr_warn("Total seed count is 0. Use fake seed!"); - goto fail; - } - - entry = (struct seed_entry *)((uint8_t *)seed_hob + - sizeof(struct seed_list_hob)); - - for (i = 0U; i < seed_hob->total_seed_count; i++) { - /* retrieve dseed */ - if ((SEED_ENTRY_TYPE_SVNSEED == entry->type) && - (SEED_ENTRY_USAGE_DSEED == entry->usage)) { - - /* The seed_entry with same type/usage are always - * arranged by index in order of 0~3. - */ - if (entry->index != dseed_index) { - pr_warn("Index mismatch. Use fake seed!"); - goto fail; - } - - if (entry->index >= BOOTLOADER_SEED_MAX_ENTRIES) { - pr_warn("Index exceed max number!"); - goto fail; - } - - (void)memcpy_s(&dseed_list[dseed_index], - sizeof(struct seed_info), - entry->seed, - sizeof(struct seed_info)); - dseed_index++; - - /* erase original seed in seed entry */ - (void)memset(entry->seed, 0U, sizeof(struct seed_info)); - } - - entry = (struct seed_entry *)((uint8_t *)entry + - entry->seed_entry_size); - } - - trusty_set_dseed(dseed_list, dseed_index); - (void)memset(dseed_list, 0U, sizeof(dseed_list)); - return; - -fail: - trusty_set_dseed(NULL, 0U); - (void)memset(dseed_list, 0U, sizeof(dseed_list)); -} diff --git a/hypervisor/boot/sbl/multiboot.c b/hypervisor/boot/sbl/multiboot.c index 8ae5d4da0..38e506b34 100644 --- a/hypervisor/boot/sbl/multiboot.c +++ b/hypervisor/boot/sbl/multiboot.c @@ -7,7 +7,8 @@ #include #include #include -#include +#include +#include #define BOOT_ARGS_LOAD_ADDR 0x24EFC000 @@ -63,16 +64,6 @@ int init_vm_boot_info(struct vm *vm) } #else -static const char *boot_params_arg = "ImageBootParamsAddr="; - -struct image_boot_params { - uint32_t size_of_this_struct; - uint32_t version; - uint64_t p_seed_list; - uint64_t p_platform_info; - uint64_t reserved; -}; - /* There are two sources for vm0 kernel cmdline: * - cmdline from sbl. mbi->cmdline * - cmdline from acrn stitching tool. mod[0].mm_string @@ -164,77 +155,6 @@ static void *get_kernel_load_addr(void *kernel_src_addr) return kernel_src_addr; } -/* - * parse_image_boot_params - * - * description: - * This function parse image_boot_params from cmdline. Mainly on - * 1. parse structure address from cmdline - * 2. get seed_list address and call function to parse seed - * 3. convert address in the structure from HPA to SOS's GPA - * 4. clear original image_boot_params argument in cmdline since - * original address is HPA, need to convert and append later - * when compose kernel command line. - * - * input: - * vm pointer to vm structure - * cmdline pointer to cmdline string - * - * return value: - * boot_params HVA of image_boot_params if parse success, or - * else a NULL pointer. - */ -static void *parse_image_boot_params(struct vm *vm, char *cmdline) -{ - char *arg, *arg_end; - char *param; - uint32_t len; - struct image_boot_params *boot_params; - - if (cmdline == NULL) { - goto fail; - } - - len = strnlen_s(boot_params_arg, MAX_BOOT_PARAMS_LEN); - arg = strstr_s(cmdline, MEM_2K, boot_params_arg, len); - if (arg == NULL) { - goto fail; - } - - param = arg + len; - boot_params = (struct image_boot_params *)hpa2hva(strtoul_hex(param)); - if (boot_params == NULL) { - goto fail; - } - - parse_seed_list((struct seed_list_hob *)hpa2hva( - boot_params->p_seed_list)); - - /* - * Convert the addresses to SOS GPA since this structure will be used - * in SOS. - */ - boot_params->p_seed_list = hpa2gpa(vm, boot_params->p_seed_list); - boot_params->p_platform_info = - hpa2gpa(vm, boot_params->p_platform_info); - - /* - * Replace original arguments with spaces since SOS's GPA is not - * identity mapped to HPA. The argument will be appended later when - * compose cmdline for SOS. - */ - arg_end = strchr(arg, ' '); - len = (arg_end != NULL) ? (uint32_t)(arg_end - arg) : - strnlen_s(arg, MEM_2K); - (void)memset(arg, ' ', len); - - return (void *)boot_params; - -fail: - parse_seed_list(NULL); - return NULL; -} - /** * @param[inout] vm pointer to a vm descriptor * @@ -287,21 +207,27 @@ int init_vm_boot_info(struct vm *vm) if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { char *cmd_src, *cmd_dst; uint32_t off = 0U; - void *boot_params_addr; + bool status = false; char buf[MAX_BOOT_PARAMS_LEN]; cmd_dst = kernel_cmdline; cmd_src = hpa2hva((uint64_t)mbi->mi_cmdline); - boot_params_addr = parse_image_boot_params(vm, cmd_src); + (void)memset(buf, 0U, sizeof(buf)); /* - * Convert ImageBootParamsAddr to SOS GPA and append to - * kernel cmdline + * The seed passing interface is different for ABL and SBL, + * so here first try to get seed from SBL, if fail then try + * ABL. */ - if (boot_params_addr != NULL) { - (void)memset(buf, 0U, sizeof(buf)); - snprintf(buf, MAX_BOOT_PARAMS_LEN, "%s0x%X ", - boot_params_arg, hva2gpa(vm, boot_params_addr)); + status = sbl_seed_parse(vm, cmd_src, buf, sizeof(buf)); + if (!status) { + status = abl_seed_parse(vm, cmd_src, buf, sizeof(buf)); + } + + if (status) { + /* + * append the seed argument to kernel cmdline + */ (void)strncpy_s(cmd_dst, MEM_2K, buf, MAX_BOOT_PARAMS_LEN); off = strnlen_s(cmd_dst, MEM_2K); diff --git a/hypervisor/boot/sbl/sbl_seed_parse.c b/hypervisor/boot/sbl/sbl_seed_parse.c new file mode 100644 index 000000000..4eaadbf09 --- /dev/null +++ b/hypervisor/boot/sbl/sbl_seed_parse.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define SEED_ENTRY_TYPE_SVNSEED 0x1U +#define SEED_ENTRY_TYPE_RPMBSEED 0x2U + +#define SEED_ENTRY_USAGE_USEED 0x1U +#define SEED_ENTRY_USAGE_DSEED 0x2U + +struct seed_list_hob { + uint8_t revision; + uint8_t reserved0[3]; + uint32_t buffer_size; + uint8_t total_seed_count; + uint8_t reserved1[3]; +}; + +struct seed_entry { + /* SVN based seed or RPMB seed or attestation key_box */ + uint8_t type; + /* For SVN seed: useed or dseed + * For RPMB seed: serial number based or not + */ + uint8_t usage; + /* index for the same type and usage seed */ + uint8_t index; + uint8_t reserved; + /* reserved for future use */ + uint16_t flags; + /* Total size of this seed entry */ + uint16_t seed_entry_size; + /* SVN seed: struct seed_info + * RPMB seed: uint8_t rpmb_key[key_len] + */ + uint8_t seed[0]; +}; + +struct image_boot_params { + uint32_t size_of_this_struct; + uint32_t version; + uint64_t p_seed_list; + uint64_t p_platform_info; + uint64_t reserved; +}; + +static const char *boot_params_arg = "ImageBootParamsAddr="; + +static void parse_seed_list_sbl(struct seed_list_hob *seed_hob) +{ + uint8_t i; + uint8_t dseed_index = 0U; + struct seed_entry *entry; + struct seed_info dseed_list[BOOTLOADER_SEED_MAX_ENTRIES]; + + if (seed_hob == NULL) { + goto fail; + } + + if (seed_hob->total_seed_count == 0U) { + goto fail; + } + + entry = (struct seed_entry *)((uint8_t *)seed_hob + + sizeof(struct seed_list_hob)); + + for (i = 0U; i < seed_hob->total_seed_count; i++) { + /* retrieve dseed */ + if ((SEED_ENTRY_TYPE_SVNSEED == entry->type) && + (SEED_ENTRY_USAGE_DSEED == entry->usage)) { + + /* The seed_entry with same type/usage are always + * arranged by index in order of 0~3. + */ + if (entry->index != dseed_index) { + pr_warn("Index mismatch. Use fake seed!"); + goto fail; + } + + if (entry->index >= BOOTLOADER_SEED_MAX_ENTRIES) { + pr_warn("Index exceed max number!"); + goto fail; + } + + (void)memcpy_s((void *)&dseed_list[dseed_index], + sizeof(struct seed_info), + (void *)entry->seed, + sizeof(struct seed_info)); + dseed_index++; + + /* erase original seed in seed entry */ + (void)memset(entry->seed, 0U, sizeof(struct seed_info)); + } + + entry = (struct seed_entry *)((uint8_t *)entry + + entry->seed_entry_size); + } + + trusty_set_dseed((void *)dseed_list, dseed_index); + (void)memset((void *)dseed_list, 0U, sizeof(dseed_list)); + return; + +fail: + trusty_set_dseed(NULL, 0U); + (void)memset((void *)dseed_list, 0U, sizeof(dseed_list)); +} + +/* + * sbl_seed_parse + * + * description: + * This function parse image_boot_params from cmdline. Mainly on + * 1. parse structure address from cmdline + * 2. get seed_list address and call parse_seed_list_sbl to parse seed + * 3. convert address in the structure from HPA to SOS's GPA + * 4. clear original image_boot_params argument in cmdline since + * original address is HPA. + * + * input: + * vm pointer to vm structure + * cmdline pointer to cmdline string + * out_len the max len of out_arg + * + * output: + * out_arg the argument with SOS's GPA + * + * return value: + * true if parse successfully, otherwise false. + */ +bool sbl_seed_parse(struct vm *vm, char *cmdline, char *out_arg, uint32_t out_len) +{ + char *arg, *arg_end; + char *param; + void *param_addr; + struct image_boot_params *boot_params; + uint32_t len; + + if (cmdline == NULL) { + goto fail; + } + + len = strnlen_s(boot_params_arg, MEM_1K); + arg = strstr_s(cmdline, MEM_2K, boot_params_arg, len); + + if (arg == NULL) { + goto fail; + } + + param = arg + len; + param_addr = (void *)hpa2hva(strtoul_hex(param)); + if (param_addr == NULL) { + goto fail; + } + + boot_params = (struct image_boot_params *)param_addr; + parse_seed_list_sbl((struct seed_list_hob *)hpa2hva( + boot_params->p_seed_list)); + + /* + * Convert the addresses to SOS GPA since this structure will + * be used in SOS. + */ + boot_params->p_seed_list = + hpa2gpa(vm, boot_params->p_seed_list); + boot_params->p_platform_info = + hpa2gpa(vm, boot_params->p_platform_info); + + /* + * Replace original arguments with spaces since SOS's GPA is not + * identity mapped to HPA. The argument will be appended later when + * compose cmdline for SOS. + */ + arg_end = strchr(arg, ' '); + len = (arg_end != NULL) ? (uint32_t)(arg_end - arg) : + strnlen_s(arg, MEM_2K); + (void)memset((void *)arg, ' ', len); + + /* Convert the param_addr to SOS GPA and copy to caller */ + if (out_arg) { + snprintf(out_arg, out_len, "%s0x%X ", + boot_params_arg, hva2gpa(vm, param_addr)); + } + + return true; + +fail: + parse_seed_list_sbl(NULL); + return false; +} diff --git a/hypervisor/include/arch/x86/abl_seed_parse.h b/hypervisor/include/arch/x86/abl_seed_parse.h new file mode 100644 index 000000000..721cc438f --- /dev/null +++ b/hypervisor/include/arch/x86/abl_seed_parse.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ABL_SEED_PARSE_H_ +#define ABL_SEED_PARSE_H_ + +bool abl_seed_parse(struct vm *vm, char *cmdline, char *out_arg, uint32_t out_len); + +#endif /* ABL_SEED_PARSE_H_ */ diff --git a/hypervisor/include/arch/x86/hob_parse.h b/hypervisor/include/arch/x86/hob_parse.h deleted file mode 100644 index 35f64b5a1..000000000 --- a/hypervisor/include/arch/x86/hob_parse.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef HOB_PARSE_H_ -#define HOB_PARSE_H_ - -#define SEED_ENTRY_TYPE_SVNSEED 0x1U -#define SEED_ENTRY_TYPE_RPMBSEED 0x2U - -#define SEED_ENTRY_USAGE_USEED 0x1U -#define SEED_ENTRY_USAGE_DSEED 0x2U - -struct seed_list_hob { - uint8_t revision; - uint8_t reserved0[3]; - uint32_t buffer_size; - uint8_t total_seed_count; - uint8_t reserved1[3]; -}; - -struct seed_entry { - /* SVN based seed or RPMB seed or attestation key_box */ - uint8_t type; - /* For SVN seed: useed or dseed - * For RPMB seed: serial number based or not - */ - uint8_t usage; - /* index for the same type and usage seed */ - uint8_t index; - uint8_t reserved; - /* reserved for future use */ - uint16_t flags; - /* Total size of this seed entry */ - uint16_t seed_entry_size; - /* SVN seed: struct seed_info - * RPMB seed: uint8_t rpmb_key[key_len] - */ - uint8_t seed[0]; -}; - -void parse_seed_list(struct seed_list_hob *seed_hob); - -#endif /* HOB_PARSE_H_ */ diff --git a/hypervisor/include/arch/x86/sbl_seed_parse.h b/hypervisor/include/arch/x86/sbl_seed_parse.h new file mode 100644 index 000000000..78c6b2fc1 --- /dev/null +++ b/hypervisor/include/arch/x86/sbl_seed_parse.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SBL_SEED_PARSE_H_ +#define SBL_SEED_PARSE_H_ + +bool sbl_seed_parse(struct vm *vm, char *cmdline, char *out_arg, uint32_t out_len); + +#endif /* SBL_SEED_PARSE_H_ */