mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-21 16:57:20 +00:00
hv: keylocker: Support Key Locker feature for guest VM
KeyLocker is a new security feature available in new Intel CPUs that protects data-encryption keys for the Advanced Encryption Standard (AES) algorithm. These keys are more valuable than what they guard. If stolen once, the key can be repeatedly used even on another system and even after vulnerability closed. It also introduces a CPU-internal wrapping key (IWKey), which is a key- encryption key to wrap AES keys into handles. While the IWKey is inaccessible to software, randomizing the value during the boot-time helps its value unpredictable. Keylocker usage: - New “ENCODEKEY” instructions take original key input and returns HANDLE crypted by an internal wrap key (IWKey, init by “LOADIWKEY” instruction) - Software can then delete the original key from memory - Early in boot/software, less likely to have vulnerability that allows stealing original key - Later encrypt/decrypt can use the HANDLE through new AES KeyLocker instructions - Note: * Software can use original key without knowing it (use HANDLE) * HANDLE cannot be used on other systems or after warm/cold reset * IWKey cannot be read from CPU after it's loaded (this is the nature of this feature) and only 1 copy of IWKey inside CPU. The virtualization implementation of Key Locker on ACRN is: - Each vCPU has a 'struct iwkey' to store its IWKey in struct acrn_vcpu_arch. - At initilization, every vCPU is created with a random IWKey. - Hypervisor traps the execution of LOADIWKEY (by 'LOADIWKEY exiting' VM-exectuion control) of vCPU to capture and save the IWKey if guest set a new IWKey. Don't support randomization (emulate CPUID to disable) of the LOADIWKEY as hypervisor cannot capture and save the random IWKey. From keylocker spec: "Note that a VMM may wish to enumerate no support for HW random IWKeys to the guest (i.e. enumerate CPUID.19H:ECX[1] as 0) as such IWKeys cannot be easily context switched. A guest ENCODEKEY will return the type of IWKey used (IWKey.KeySource) and thus will notice if a VMM virtualized a HW random IWKey with a SW specified IWKey." - In context_switch_in() of each vCPU, hypervisor loads that vCPU's IWKey into pCPU by LOADIWKEY instruction. - There is an assumption that ACRN hypervisor will never use the KeyLocker feature itself. This patch implements the vCPU's IWKey management and the next patch implements host context save/restore IWKey logic. Tracked-On: #5695 Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
@@ -659,6 +659,11 @@ static inline void xrstors(const struct xsave_area *region_addr, uint64_t mask)
|
||||
"memory");
|
||||
}
|
||||
|
||||
static inline void loadiwkey(uint32_t eax)
|
||||
{
|
||||
asm volatile(".byte 0xf3, 0x0f, 0x38, 0xdc, 0xd1;": : "a" (eax));
|
||||
}
|
||||
|
||||
/*
|
||||
* stac/clac pair is used to access guest's memory protected by SMAP,
|
||||
* following below flow:
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#define X86_FEATURE_XSAVE ((FEAT_1_ECX << 5U) + 26U)
|
||||
#define X86_FEATURE_OSXSAVE ((FEAT_1_ECX << 5U) + 27U)
|
||||
#define X86_FEATURE_AVX ((FEAT_1_ECX << 5U) + 28U)
|
||||
#define X86_FEATURE_RDRAND ((FEAT_1_ECX << 5U) + 30U)
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000001 (EDX)*/
|
||||
#define X86_FEATURE_FPU ((FEAT_1_EDX << 5U) + 0U)
|
||||
|
@@ -203,6 +203,13 @@ struct msr_store_area {
|
||||
uint32_t count; /* actual count of entries to be loaded/restored during VMEntry/VMExit */
|
||||
};
|
||||
|
||||
struct iwkey {
|
||||
/* 256bit encryption key */
|
||||
uint64_t encryption_key[4];
|
||||
/* 128bit integration key */
|
||||
uint64_t integrity_key[2];
|
||||
};
|
||||
|
||||
struct acrn_vcpu_arch {
|
||||
/* vmcs region for this vcpu, MUST be 4KB-aligned */
|
||||
uint8_t vmcs[PAGE_SIZE];
|
||||
@@ -261,6 +268,7 @@ struct acrn_vcpu_arch {
|
||||
uint64_t eoi_exit_bitmap[EOI_EXIT_BITMAP_SIZE >> 6U];
|
||||
|
||||
/* Keylocker */
|
||||
struct iwkey IWKey;
|
||||
bool cr4_kl_enabled;
|
||||
} __aligned(PAGE_SIZE);
|
||||
|
||||
|
@@ -22,6 +22,7 @@ void cpu_l1d_flush(void);
|
||||
bool check_cpu_security_cap(void);
|
||||
void cpu_internal_buffers_clear(void);
|
||||
bool is_ept_force_4k_ipage(void);
|
||||
uint64_t get_random_value(void);
|
||||
|
||||
#ifdef STACK_PROTECTOR
|
||||
struct stack_canary {
|
||||
|
@@ -64,6 +64,10 @@
|
||||
|
||||
#define VMX_XSS_EXITING_BITMAP_FULL 0x0000202CU
|
||||
#define VMX_XSS_EXITING_BITMAP_HIGH 0x0000202DU
|
||||
|
||||
#define VMX_PROC_VM_EXEC_CONTROLS3_FULL 0x00002034U
|
||||
#define VMX_PROC_VM_EXEC_CONTROLS3_HIGH 0x00002035U
|
||||
|
||||
/* 64-bit read-only data fields */
|
||||
#define VMX_GUEST_PHYSICAL_ADDR_FULL 0x00002400U
|
||||
#define VMX_GUEST_PHYSICAL_ADDR_HIGH 0x00002401U
|
||||
@@ -263,6 +267,7 @@
|
||||
#define VMX_EXIT_REASON_PAGE_MODIFICATION_LOG_FULL 0x0000003EU
|
||||
#define VMX_EXIT_REASON_XSAVES 0x0000003FU
|
||||
#define VMX_EXIT_REASON_XRSTORS 0x00000040U
|
||||
#define VMX_EXIT_REASON_LOADIWKEY 0x00000045U
|
||||
|
||||
/* VMX execution control bits (pin based) */
|
||||
#define VMX_PINBASED_CTLS_IRQ_EXIT (1U<<0U)
|
||||
@@ -312,6 +317,7 @@
|
||||
#define VMX_PROCBASED_CTLS2_RDSEED (1U<<16U)
|
||||
#define VMX_PROCBASED_CTLS2_EPT_VE (1U<<18U)
|
||||
#define VMX_PROCBASED_CTLS2_XSVE_XRSTR (1U<<20U)
|
||||
#define VMX_PROCBASED_CTLS3_LOADIWKEY (1U<<0U)
|
||||
|
||||
/* MSR_IA32_VMX_EPT_VPID_CAP: EPT and VPID capability bits */
|
||||
#define VMX_EPT_EXECUTE_ONLY (1U << 0U)
|
||||
|
Reference in New Issue
Block a user