From 95d1e40283d72750cac72e9260b5ad5804514b95 Mon Sep 17 00:00:00 2001 From: Qi Yadong Date: Wed, 6 Mar 2019 13:24:55 +0800 Subject: [PATCH] hv: refactor seed management New component to maintain seed retrieval and derivation: seed. 1. Retrieve seed from bootloader in Hypervisor's boot stage. 2. Derive virtual seed for Guest/Trusty if need. Tracked-On: #2724 Signed-off-by: Qi Yadong Reviewed-by: Zhu Bing --- hypervisor/Makefile | 6 +- hypervisor/arch/x86/guest/trusty.c | 147 ++++-------- hypervisor/arch/x86/init.c | 3 + hypervisor/arch/x86/seed/seed.c | 252 +++++++++++++++++++++ hypervisor/arch/x86/seed/seed_abl.c | 94 ++++++++ hypervisor/arch/x86/seed/seed_abl.h | 12 + hypervisor/arch/x86/seed/seed_sbl.c | 118 ++++++++++ hypervisor/arch/x86/seed/seed_sbl.h | 20 ++ hypervisor/boot/sbl/multiboot.c | 23 +- hypervisor/include/arch/x86/guest/trusty.h | 3 +- hypervisor/include/arch/x86/seed.h | 25 ++ 11 files changed, 572 insertions(+), 131 deletions(-) create mode 100644 hypervisor/arch/x86/seed/seed.c create mode 100644 hypervisor/arch/x86/seed/seed_abl.c create mode 100644 hypervisor/arch/x86/seed/seed_abl.h create mode 100644 hypervisor/arch/x86/seed/seed_sbl.c create mode 100644 hypervisor/arch/x86/seed/seed_sbl.h create mode 100644 hypervisor/include/arch/x86/seed.h diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 369edf141..d6d24160b 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -131,6 +131,10 @@ C_SRCS += boot/reloc.c # initilization component C_SRCS += arch/x86/init.c +C_SRCS += arch/x86/seed/seed.c +C_SRCS += arch/x86/seed/seed_abl.c +C_SRCS += arch/x86/seed/seed_sbl.c + # configuration component C_SRCS += arch/x86/configs/vm_config.c ifeq ($(CONFIG_PARTITION_MODE),y) @@ -234,8 +238,6 @@ C_SRCS += bsp/const_dmar.c C_SRCS += boot/uefi/uefi_boot.c C_SRCS += boot/sbl/multiboot.c -C_SRCS += boot/sbl/sbl_seed_parse.c -C_SRCS += boot/sbl/abl_seed_parse.c # retpoline support ifeq (true, $(shell [ $(GCC_MAJOR) -eq 7 ] && [ $(GCC_MINOR) -ge 3 ] && echo true)) diff --git a/hypervisor/arch/x86/guest/trusty.c b/hypervisor/arch/x86/guest/trusty.c index 54326009e..c3e202f96 100644 --- a/hypervisor/arch/x86/guest/trusty.c +++ b/hypervisor/arch/x86/guest/trusty.c @@ -16,6 +16,7 @@ #include #include #include +#include #define TRUSTY_VERSION 1U #define TRUSTY_VERSION_2 2U @@ -30,13 +31,6 @@ struct trusty_mem { /* The left memory is for trusty's code/data/heap/stack */ } __aligned(PAGE_SIZE); -static struct trusty_key_info g_key_info = { - .size_of_this_struct = sizeof(g_key_info), - .version = 0U, - .platform = 3U, - .num_seeds = 1U -}; - /** * @defgroup trusty_apis Trusty APIs * @@ -317,95 +311,40 @@ void switch_world(struct acrn_vcpu *vcpu, int32_t next_world) arch->cur_context = next_world; } -static inline uint32_t get_max_svn_index(void) -{ - uint32_t i, max_svn_idx = 0U; - - for (i = 1U; i < g_key_info.num_seeds; i++) { - if (g_key_info.dseed_list[i].cse_svn > g_key_info.dseed_list[i - 1U].cse_svn) { - max_svn_idx = i; - } - } - - return max_svn_idx; -} - -static bool derive_aek(uint8_t *attkb_key) -{ - bool ret = true; - const int8_t salt[] = "Attestation Keybox Encryption Key"; - const uint8_t *ikm; - uint32_t ikm_len; - uint32_t max_svn_idx; - - if ((attkb_key == NULL) || (g_key_info.num_seeds == 0U) || - (g_key_info.num_seeds > BOOTLOADER_SEED_MAX_ENTRIES)) { - ret = false; - } else { - max_svn_idx = get_max_svn_index(); - ikm = g_key_info.dseed_list[max_svn_idx].seed; - /* only the low 32 bits of seed are valid */ - ikm_len = 32U; - - if (hmac_sha256(attkb_key, ikm, ikm_len, - (const uint8_t *)salt, sizeof(salt)) != 1) { - pr_err("%s: failed to derive key!\n", __func__); - ret = false; - } - } - - return ret; -} - /* Put key_info and trusty_startup_param in the first Page of Trusty * runtime memory */ -static bool setup_trusty_info(struct acrn_vcpu *vcpu, - uint32_t mem_size, uint64_t mem_base_hpa) +static bool setup_trusty_info(struct acrn_vcpu *vcpu, uint32_t mem_size, uint64_t mem_base_hpa, uint8_t *rkey) { bool ret = true; - uint32_t i; struct trusty_mem *mem; - struct trusty_key_info *key_info; + struct trusty_key_info key_info; + struct trusty_startup_param startup_param; - mem = (struct trusty_mem *)(hpa2hva(mem_base_hpa)); + (void)memset(&key_info, 0U, sizeof(key_info)); - stac(); - /* copy key_info to the first page of trusty memory */ - (void)memcpy_s(&mem->first_page.key_info, sizeof(g_key_info), - &g_key_info, sizeof(g_key_info)); + key_info.size_of_this_struct = sizeof(struct trusty_key_info); + key_info.version = 0U; + key_info.platform = 3U; - (void)memset(&mem->first_page.key_info.dseed_list, 0U, - sizeof(mem->first_page.key_info.dseed_list)); - /* Derive dvseed from dseed for Trusty */ - key_info = &mem->first_page.key_info; - for (i = 0U; i < g_key_info.num_seeds; i++) { - if (hkdf_sha256(key_info->dseed_list[i].seed, - BUP_MKHI_BOOTLOADER_SEED_LEN, - g_key_info.dseed_list[i].seed, - BUP_MKHI_BOOTLOADER_SEED_LEN, - NULL, 0U, - vcpu->vm->GUID, sizeof(vcpu->vm->GUID)) == 0) { - (void)memset(key_info, 0U, sizeof(struct trusty_key_info)); - pr_err("%s: derive dvseed failed!", __func__); - ret = false; - break; - } - key_info->dseed_list[i].cse_svn = g_key_info.dseed_list[i].cse_svn; + if (rkey != NULL) { + (void)memcpy_s(key_info.rpmb_key, 64U, rkey, 64U); + (void)memset(rkey, 0U, 64U); } + /* Derive dvseed from dseed for Trusty */ + ret = derive_virtual_seed(&key_info.dseed_list[0U], &key_info.num_seeds, + NULL, 0U, + vcpu->vm->GUID, sizeof(vcpu->vm->GUID)); if (ret == true) { - /* Derive decryption key of attestation keybox from dseed */ - if (!derive_aek(key_info->attkb_enc_key)) { - (void)memset(key_info, 0U, sizeof(struct trusty_key_info)); - pr_err("%s: derive key of att keybox failed!", __func__); - ret = false; - } else { + /* Derive encryption key of attestation keybox from dseed */ + ret = derive_attkb_enc_key(key_info.attkb_enc_key); + if (ret == true) { /* Prepare trusty startup param */ - mem->first_page.startup_param.size_of_this_struct = sizeof(struct trusty_startup_param); - mem->first_page.startup_param.mem_size = mem_size; - mem->first_page.startup_param.tsc_per_ms = CYCLES_PER_MS; - mem->first_page.startup_param.trusty_mem_base = TRUSTY_EPT_REBASE_GPA; + startup_param.size_of_this_struct = sizeof(struct trusty_startup_param); + startup_param.mem_size = mem_size; + startup_param.tsc_per_ms = CYCLES_PER_MS; + startup_param.trusty_mem_base = TRUSTY_EPT_REBASE_GPA; /* According to trusty boot protocol, it will use RDI as the * address(GPA) of startup_param on boot. Currently, the startup_param @@ -413,10 +352,19 @@ static bool setup_trusty_info(struct acrn_vcpu *vcpu, */ vcpu->arch.contexts[SECURE_WORLD].run_ctx.guest_cpu_regs.regs.rdi = (uint64_t)TRUSTY_EPT_REBASE_GPA + sizeof(struct trusty_key_info); + + stac(); + mem = (struct trusty_mem *)(hpa2hva(mem_base_hpa)); + (void)memcpy_s(&mem->first_page.key_info, sizeof(struct trusty_key_info), + &key_info, sizeof(key_info)); + (void)memcpy_s(&mem->first_page.startup_param, sizeof(struct trusty_startup_param), + &startup_param, sizeof(startup_param)); + clac(); } } - clac(); + (void)memset(&key_info, 0U, sizeof(key_info)); + return ret; } @@ -428,7 +376,8 @@ static bool setup_trusty_info(struct acrn_vcpu *vcpu, static bool init_secure_world_env(struct acrn_vcpu *vcpu, uint64_t entry_gpa, uint64_t base_hpa, - uint32_t size) + uint32_t size, + uint8_t *rpmb_key) { uint32_t i; @@ -445,15 +394,16 @@ static bool init_secure_world_env(struct acrn_vcpu *vcpu, vcpu->arch.contexts[SECURE_WORLD].world_msrs[i] = vcpu->arch.guest_msrs[i]; } - return setup_trusty_info(vcpu, size, base_hpa); + return setup_trusty_info(vcpu, size, base_hpa, rpmb_key); } -bool initialize_trusty(struct acrn_vcpu *vcpu, const struct trusty_boot_param *boot_param) +bool initialize_trusty(struct acrn_vcpu *vcpu, struct trusty_boot_param *boot_param) { bool ret = true; uint64_t trusty_entry_gpa, trusty_base_gpa, trusty_base_hpa; uint32_t trusty_mem_size; struct acrn_vm *vm = vcpu->vm; + uint8_t *rpmb_key = NULL; switch (boot_param->version) { case TRUSTY_VERSION_2: @@ -461,9 +411,7 @@ bool initialize_trusty(struct acrn_vcpu *vcpu, const struct trusty_boot_param *b (((uint64_t)boot_param->entry_point_high) << 32U); trusty_base_gpa = ((uint64_t)boot_param->base_addr) | (((uint64_t)boot_param->base_addr_high) << 32U); - - /* copy rpmb_key from OSloader */ - (void)memcpy_s(&g_key_info.rpmb_key[0][0], 64U, &boot_param->rpmb_key[0], 64U); + rpmb_key = boot_param->rpmb_key; break; case TRUSTY_VERSION: trusty_entry_gpa = (uint64_t)boot_param->entry_point; @@ -495,7 +443,7 @@ bool initialize_trusty(struct acrn_vcpu *vcpu, const struct trusty_boot_param *b /* init secure world environment */ if (init_secure_world_env(vcpu, (trusty_entry_gpa - trusty_base_gpa) + TRUSTY_EPT_REBASE_GPA, - trusty_base_hpa, trusty_mem_size)) { + trusty_base_hpa, trusty_mem_size, rpmb_key)) { /* switch to Secure World */ vcpu->arch.cur_context = SECURE_WORLD; @@ -508,23 +456,6 @@ bool initialize_trusty(struct acrn_vcpu *vcpu, const struct trusty_boot_param *b return ret; } -void trusty_set_dseed(const void *dseed, uint8_t dseed_num) -{ - /* Use fake seed if input param is invalid */ - if ((dseed == NULL) || (dseed_num == 0U) || - (dseed_num > BOOTLOADER_SEED_MAX_ENTRIES)) { - - g_key_info.num_seeds = 1U; - (void)memset(&g_key_info.dseed_list[0].seed, 0xA5U, - sizeof(g_key_info.dseed_list[0].seed)); - } else { - g_key_info.num_seeds = dseed_num; - (void)memcpy_s(&g_key_info.dseed_list, - sizeof(struct seed_info) * dseed_num, - dseed, sizeof(struct seed_info) * dseed_num); - } -} - void save_sworld_context(struct acrn_vcpu *vcpu) { (void)memcpy_s(&vcpu->vm->sworld_snapshot, diff --git a/hypervisor/arch/x86/init.c b/hypervisor/arch/x86/init.c index dc5e4c160..67ecd5c88 100644 --- a/hypervisor/arch/x86/init.c +++ b/hypervisor/arch/x86/init.c @@ -15,6 +15,7 @@ #include #include #include +#include /* Push sp magic to top of stack for call trace */ #define SWITCH_TO(rsp, to) \ @@ -70,6 +71,8 @@ static void init_primary_cpu_post(void) init_cpu_post(BOOT_CPU_ID); + init_seed(); + init_debug_post(BOOT_CPU_ID); enter_guest_mode(BOOT_CPU_ID); diff --git a/hypervisor/arch/x86/seed/seed.c b/hypervisor/arch/x86/seed/seed.c new file mode 100644 index 000000000..923b25d4d --- /dev/null +++ b/hypervisor/arch/x86/seed/seed.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "seed_abl.h" +#include "seed_sbl.h" + +#define BOOTLOADER_SBL 0U +#define BOOTLOADER_ABL 1U +#define BOOTLOADER_INVD (~0U) + +struct seed_argument { + const char *str; + uint32_t bootloader_id; + uint64_t addr; +}; + +#define SEED_ARG_NUM 4U +static struct seed_argument seed_arg[SEED_ARG_NUM] = { + { "ImageBootParamsAddr=", BOOTLOADER_SBL, 0UL }, + { "ABL.svnseed=", BOOTLOADER_ABL, 0UL }, + { "dev_sec_info.param_addr=", BOOTLOADER_ABL, 0UL }, + { NULL, BOOTLOADER_INVD, 0UL } +}; + +static struct physical_seed g_phy_seed; + +static uint32_t parse_seed_arg(void) +{ + char *cmd_src = NULL; + char *arg, *arg_end; + struct multiboot_info *mbi = NULL; + uint32_t i = SEED_ARG_NUM - 1U; + uint32_t len; + + stac(); + + if (boot_regs[0U] == MULTIBOOT_INFO_MAGIC) { + mbi = (struct multiboot_info *)hpa2hva((uint64_t)boot_regs[1U]); + if (mbi != NULL) { + if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { + cmd_src = (char *)hpa2hva((uint64_t)mbi->mi_cmdline); + } + } + } + + if (cmd_src != NULL) { + for (i = 0U; seed_arg[i].str != NULL; i++) { + len = strnlen_s(seed_arg[i].str, MEM_1K); + arg = strstr_s((const char *)cmd_src, MEM_2K, seed_arg[i].str, len); + if (arg != NULL) { + arg += len; + seed_arg[i].addr = strtoul_hex(arg); + + /* + * Replace original arguments with spaces since Guest's GPA might not + * identity mapped to HPA. The argument will be appended later when + * compose cmdline for Guest. + */ + arg_end = strchr(arg, ' '); + arg -= len; + len = (arg_end != NULL) ? (uint32_t)(arg_end - arg) : strnlen_s(arg, MEM_2K); + (void)memset((void *)arg, (char)' ', len); + break; + } + } + } + + clac(); + + return i; +} + +/* + * append_seed_arg + * + * description: + * append seed argument to Guest's cmdline + * + * input: + * vm pointer to target VM + * + * output: + * cmd_dst pointer to cmdline for Guest + * + * return value: + * none + */ +void append_seed_arg(char *cmd_dst, bool vm_is_sos) +{ + uint32_t i; + char buf[MEM_1K]; + + if ((cmd_dst != NULL) && vm_is_sos) { + for (i = 0U; seed_arg[i].str != NULL; i++) { + if (seed_arg[i].addr != 0ULL) { + (void)memset(buf, 0U, sizeof(buf)); + + snprintf(buf, sizeof(buf), "%s0x%X ", seed_arg[i].str, + sos_vm_hpa2gpa(seed_arg[i].addr)); + + if (seed_arg[i].bootloader_id == BOOTLOADER_SBL) { + struct image_boot_params *boot_params = + (struct image_boot_params *)hpa2hva(seed_arg[i].addr); + + boot_params->p_seed_list = sos_vm_hpa2gpa(boot_params->p_seed_list); + + boot_params->p_platform_info = sos_vm_hpa2gpa(boot_params->p_platform_info); + } + + (void)strncpy_s(cmd_dst, MEM_2K, buf, strnlen_s(buf, MEM_1K)); + + break; + } + } + } +} + +/* + * derive_virtual_seed + * + * description: + * derive virtual seed list from physical seed list + * + * input: + * salt pointer to salt + * salt_len length of salt + * info pointer to info + * info_len length of info + * + * output: + * seed_list pointer to seed_list + * num_seed seed number in seed_list + * + * return value: + * true if derive successfully, otherwise false + */ +bool derive_virtual_seed(struct seed_info *seed_list, uint32_t *num_seeds, + const uint8_t *salt, size_t salt_len, const uint8_t *info, size_t info_len) +{ + uint32_t i; + bool ret = true; + + if ((seed_list == NULL) || (g_phy_seed.num_seeds == 0U)) { + ret = false; + } else { + for (i = 0U; i < g_phy_seed.num_seeds; i++) { + if (hkdf_sha256(seed_list[i].seed, + sizeof(seed_list[i].seed), + g_phy_seed.seed_list[i].seed, + sizeof(g_phy_seed.seed_list[i].seed), + salt, salt_len, + info, info_len) == 0) { + *num_seeds = 0U; + (void)memset(seed_list, 0U, sizeof(struct seed_info) * BOOTLOADER_SEED_MAX_ENTRIES); + pr_err("%s: derive virtual seed list failed!", __func__); + ret = false; + break; + } + seed_list[i].cse_svn = g_phy_seed.seed_list[i].cse_svn; + } + *num_seeds = g_phy_seed.num_seeds; + } + + return ret; +} + +static inline uint32_t get_max_svn_index(void) +{ + uint32_t i, max_svn_idx = 0U; + + for (i = 1U; i < g_phy_seed.num_seeds; i++) { + if (g_phy_seed.seed_list[i].cse_svn > g_phy_seed.seed_list[i - 1U].cse_svn) { + max_svn_idx = i; + } + } + + return max_svn_idx; +} + +/* + * derive_attkb_enc_key + * + * description: + * derive attestation keybox encryption key from physical seed(max svn) + * + * input: + * none + * + * output: + * out_key pointer to output key + * + * return value: + * true if derive successfully, otherwise false + */ +bool derive_attkb_enc_key(uint8_t *out_key) +{ + bool ret = true; + const uint8_t *ikm; + uint32_t ikm_len; + uint32_t max_svn_idx; + const uint8_t salt[] = "Attestation Keybox Encryption Key"; + + if ((out_key == NULL) || (g_phy_seed.num_seeds == 0U) || + (g_phy_seed.num_seeds > BOOTLOADER_SEED_MAX_ENTRIES)) { + ret = false; + } else { + max_svn_idx = get_max_svn_index(); + ikm = &(g_phy_seed.seed_list[max_svn_idx].seed[0]); + /* only the low 32 bytes of seed are valid */ + ikm_len = 32U; + + if (hmac_sha256(out_key, ikm, ikm_len, salt, sizeof(salt)) != 1) { + pr_err("%s: failed to derive key!\n", __func__); + ret = false; + } + } + + return ret; +} + +void init_seed(void) +{ + bool status; + uint32_t index; + + index = parse_seed_arg(); + + switch (seed_arg[index].bootloader_id) { + case BOOTLOADER_SBL: + status = parse_seed_sbl(seed_arg[index].addr, &g_phy_seed); + break; + case BOOTLOADER_ABL: + status = parse_seed_abl(seed_arg[index].addr, &g_phy_seed); + break; + default: + status = false; + break; + } + + /* Failed to parse seed from Bootloader, using dummy seed */ + if (status == false) { + g_phy_seed.num_seeds = 1U; + (void)memset(&g_phy_seed.seed_list[0], 0xA5U, sizeof(g_phy_seed.seed_list)); + } +} diff --git a/hypervisor/arch/x86/seed/seed_abl.c b/hypervisor/arch/x86/seed/seed_abl.c new file mode 100644 index 000000000..74f86628a --- /dev/null +++ b/hypervisor/arch/x86/seed/seed_abl.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "seed_abl.h" + +#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 abl_svn_seed { + uint32_t size_of_this_struct; + uint32_t version; + uint32_t num_seeds; + struct abl_seed_info seed_list[ABL_SEED_LIST_MAX]; +}; + +/* + * parse_seed_abl + * + * description: + * This function parse seed_list which provided by ABL. + * + * input: + * cmdline pointer to cmdline string + * + * output: + * phy_seed pointer to physical seed structure + * + * return value: + * true if parse successfully, otherwise false. + */ +bool parse_seed_abl(uint64_t addr, struct physical_seed *phy_seed) +{ + uint32_t i; + uint32_t legacy_seed_index = 0U; + struct seed_info *seed_list; + struct abl_svn_seed *abl_seed = (struct abl_svn_seed *)hpa2hva(addr); + bool status = false; + + stac(); + + if ((phy_seed != NULL) && (abl_seed != NULL) && + (abl_seed->num_seeds >= 2U) && (abl_seed->num_seeds <= ABL_SEED_LIST_MAX)) { + + seed_list = phy_seed->seed_list; + /* + * 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 < abl_seed->num_seeds; i++) { + if (abl_seed->seed_list[i].svn < abl_seed->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 *)&phy_seed->seed_list[0U], 0U, sizeof(phy_seed->seed_list)); + for (i = 0U; i < abl_seed->num_seeds; i++) { + seed_list[i].cse_svn = abl_seed->seed_list[i].svn; + (void)memcpy_s((void *)&seed_list[i].seed[0U], sizeof(seed_list[i].seed), + (void *)&abl_seed->seed_list[i].seed[0U], sizeof(abl_seed->seed_list[i].seed)); + + if (i == legacy_seed_index) { + continue; + } + + (void)memset((void *)&abl_seed->seed_list[i].seed[0U], 0U, + sizeof(abl_seed->seed_list[i].seed)); + } + + phy_seed->num_seeds = abl_seed->num_seeds; + status = true; + } + + clac(); + + return status; +} diff --git a/hypervisor/arch/x86/seed/seed_abl.h b/hypervisor/arch/x86/seed/seed_abl.h new file mode 100644 index 000000000..a87647939 --- /dev/null +++ b/hypervisor/arch/x86/seed/seed_abl.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SEED_ABL_H_ +#define SEED_ABL_H_ + +bool parse_seed_abl(uint64_t addr, struct physical_seed *phy_seed); + +#endif /* SEED_ABL_H_ */ diff --git a/hypervisor/arch/x86/seed/seed_sbl.c b/hypervisor/arch/x86/seed/seed_sbl.c new file mode 100644 index 000000000..8c70b7e4a --- /dev/null +++ b/hypervisor/arch/x86/seed/seed_sbl.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "seed_sbl.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]; +}; + +/* + * parse_seed_sbl + * + * description: + * This function parse seed_list which provided by SBL + * + * input: + * cmdline pointer to cmdline string + * + * return value: + * true if parse successfully, otherwise false. + */ +bool parse_seed_sbl(uint64_t addr, struct physical_seed *phy_seed) +{ + uint8_t i; + uint8_t dseed_index = 0U; + struct image_boot_params *boot_params; + struct seed_list_hob *seed_hob = NULL; + struct seed_entry *entry; + struct seed_info *seed_list; + bool status = false; + + stac(); + + boot_params = (struct image_boot_params *)hpa2hva(addr); + + if ((boot_params != NULL) || (phy_seed != NULL)) { + seed_hob = (struct seed_list_hob *)hpa2hva(boot_params->p_seed_list); + } + + if (seed_hob != NULL) { + status = true; + + seed_list = phy_seed->seed_list; + + entry = (struct seed_entry *)((uint8_t *)seed_hob + sizeof(struct seed_list_hob)); + + for (i = 0U; i < seed_hob->total_seed_count; i++) { + if (entry != NULL) { + /* 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) || + (entry->index >= BOOTLOADER_SEED_MAX_ENTRIES)) { + pr_warn("%s: Invalid seed index.", __func__); + status = false; + break; + } + + (void)memcpy_s((void *)&seed_list[dseed_index], sizeof(struct seed_info), + (void *)&entry->seed[0U], sizeof(struct seed_info)); + dseed_index++; + + /* erase original seed in seed entry */ + (void)memset((void *)&entry->seed[0U], 0U, sizeof(struct seed_info)); + } + } + + entry = (struct seed_entry *)((uint8_t *)entry + entry->seed_entry_size); + } + + if (status) { + phy_seed->num_seeds = dseed_index; + } + } + + clac(); + + return status; +} diff --git a/hypervisor/arch/x86/seed/seed_sbl.h b/hypervisor/arch/x86/seed/seed_sbl.h new file mode 100644 index 000000000..a0668170f --- /dev/null +++ b/hypervisor/arch/x86/seed/seed_sbl.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SEED_SBL_H_ +#define SEED_SBL_H_ + +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; +}; + +bool parse_seed_sbl(uint64_t addr, struct physical_seed *phy_seed); + +#endif /* SEED_SBL_H_ */ diff --git a/hypervisor/boot/sbl/multiboot.c b/hypervisor/boot/sbl/multiboot.c index a3903ae8e..da634eb74 100644 --- a/hypervisor/boot/sbl/multiboot.c +++ b/hypervisor/boot/sbl/multiboot.c @@ -7,8 +7,7 @@ #include #include #include -#include -#include +#include #define ACRN_DBG_BOOT 6U @@ -162,30 +161,16 @@ int32_t sbl_init_vm_boot_info(struct acrn_vm *vm) if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { char *cmd_src, *cmd_dst; uint32_t off = 0U; - bool status = false; - char buf[MAX_BOOT_PARAMS_LEN]; cmd_dst = kernel_cmdline; cmd_src = (char *)hpa2hva((uint64_t)mbi->mi_cmdline); - (void)memset(buf, 0U, sizeof(buf)); /* - * The seed passing interface is different for ABL and SBL, - * so here first try to get seed from SBL, if fail then try - * ABL. + * Append seed argument for SOS */ - status = sbl_seed_parse(is_sos_vm(vm), cmd_src, buf, sizeof(buf)); - if (!status) { - status = abl_seed_parse(cmd_src, buf, sizeof(buf)); - } + append_seed_arg(cmd_dst, is_sos_vm(vm)); - 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); - } + off = strnlen_s(cmd_dst, MEM_2K); cmd_dst += off; (void)strncpy_s(cmd_dst, MEM_2K - off, (const char *)cmd_src, diff --git a/hypervisor/include/arch/x86/guest/trusty.h b/hypervisor/include/arch/x86/guest/trusty.h index c8568e478..4584404dd 100644 --- a/hypervisor/include/arch/x86/guest/trusty.h +++ b/hypervisor/include/arch/x86/guest/trusty.h @@ -131,10 +131,9 @@ struct trusty_startup_param { }; void switch_world(struct acrn_vcpu *vcpu, int32_t next_world); -bool initialize_trusty(struct acrn_vcpu *vcpu, const struct trusty_boot_param *boot_param); +bool initialize_trusty(struct acrn_vcpu *vcpu, struct trusty_boot_param *boot_param); void destroy_secure_world(struct acrn_vm *vm, bool need_clr_mem); void save_sworld_context(struct acrn_vcpu *vcpu); void restore_sworld_context(struct acrn_vcpu *vcpu); -void trusty_set_dseed(const void *dseed, uint8_t dseed_num); #endif /* TRUSTY_H_ */ diff --git a/hypervisor/include/arch/x86/seed.h b/hypervisor/include/arch/x86/seed.h new file mode 100644 index 000000000..c7c75bb5f --- /dev/null +++ b/hypervisor/include/arch/x86/seed.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SEED_H_ +#define SEED_H_ + +struct physical_seed { + struct seed_info seed_list[BOOTLOADER_SEED_MAX_ENTRIES]; + uint32_t num_seeds; + uint32_t pad; +}; + +void init_seed(void); + +void append_seed_arg(char *cmd_dst, bool vm_is_sos); + +bool derive_virtual_seed(struct seed_info *seed_list, uint32_t *num_seeds, + const uint8_t *salt, size_t salt_len, const uint8_t *info, size_t info_len); + +bool derive_attkb_enc_key(uint8_t *out_key); + +#endif /* SEED_H_ */