mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-23 14:07:42 +00:00
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 <yadong.qi@intel.com> Reviewed-by: Zhu Bing <bing.zhu@intel.com>
This commit is contained in:
parent
4d0419ed71
commit
95d1e40283
@ -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))
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <vmx.h>
|
||||
#include <security.h>
|
||||
#include <logmsg.h>
|
||||
#include <seed.h>
|
||||
|
||||
#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;
|
||||
|
||||
if (rkey != NULL) {
|
||||
(void)memcpy_s(key_info.rpmb_key, 64U, rkey, 64U);
|
||||
(void)memset(rkey, 0U, 64U);
|
||||
}
|
||||
|
||||
(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,
|
||||
ret = derive_virtual_seed(&key_info.dseed_list[0U], &key_info.num_seeds,
|
||||
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;
|
||||
}
|
||||
|
||||
vcpu->vm->GUID, sizeof(vcpu->vm->GUID));
|
||||
if (ret == true) {
|
||||
/* Derive encryption key of attestation keybox from dseed */
|
||||
ret = derive_attkb_enc_key(key_info.attkb_enc_key);
|
||||
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 {
|
||||
/* 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,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <vm.h>
|
||||
#include <logmsg.h>
|
||||
#include <firmware.h>
|
||||
#include <seed.h>
|
||||
|
||||
/* 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);
|
||||
|
252
hypervisor/arch/x86/seed/seed.c
Normal file
252
hypervisor/arch/x86/seed/seed.c
Normal file
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <hypervisor.h>
|
||||
#include <multiboot.h>
|
||||
#include <crypto_api.h>
|
||||
#include <seed.h>
|
||||
#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));
|
||||
}
|
||||
}
|
94
hypervisor/arch/x86/seed/seed_abl.c
Normal file
94
hypervisor/arch/x86/seed/seed_abl.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <hypervisor.h>
|
||||
#include <seed.h>
|
||||
#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;
|
||||
}
|
12
hypervisor/arch/x86/seed/seed_abl.h
Normal file
12
hypervisor/arch/x86/seed/seed_abl.h
Normal file
@ -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_ */
|
118
hypervisor/arch/x86/seed/seed_sbl.c
Normal file
118
hypervisor/arch/x86/seed/seed_sbl.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <hypervisor.h>
|
||||
#include <seed.h>
|
||||
#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;
|
||||
}
|
20
hypervisor/arch/x86/seed/seed_sbl.h
Normal file
20
hypervisor/arch/x86/seed/seed_sbl.h
Normal file
@ -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_ */
|
@ -7,8 +7,7 @@
|
||||
#include <hypervisor.h>
|
||||
#include <multiboot.h>
|
||||
#include <zeropage.h>
|
||||
#include <sbl_seed_parse.h>
|
||||
#include <abl_seed_parse.h>
|
||||
#include <seed.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
cmd_dst += off;
|
||||
(void)strncpy_s(cmd_dst, MEM_2K - off, (const char *)cmd_src,
|
||||
|
@ -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_ */
|
||||
|
25
hypervisor/include/arch/x86/seed.h
Normal file
25
hypervisor/include/arch/x86/seed.h
Normal file
@ -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_ */
|
Loading…
Reference in New Issue
Block a user