From d7e1f5d82331a625ad9ddaa3f0b92333fed62702 Mon Sep 17 00:00:00 2001 From: Wojciech Ozga Date: Mon, 7 Oct 2024 10:28:16 -0500 Subject: [PATCH] cleaning up Signed-off-by: Wojciech Ozga --- .gitignore | 2 +- Makefile | 8 +-- confidential-vms/linux_vm/Makefile | 18 +++-- .../hypervisor_rootfs/run_linux_vm.sh | 5 +- .../linux_vm/overlay/root/ace_module/Makefile | 27 ++++++++ .../linux_vm/overlay/root/ace_module/ace.c | 39 +++++++++++ .../root/this_is_confidential_vm_filesystem | 1 + .../this_is_confidential_vm_filesystem | 1 + .../rust-crates/cove_tap/src/error.rs | 8 +-- .../rust-crates/cove_tap/src/lib.rs | 4 +- .../rust-crates/cove_tap/src/parser.rs | 32 +++++---- .../rust-crates/cove_tap/src/serializer.rs | 20 +++--- .../rust-crates/cove_tap/src/spec.rs | 45 ++++++------ .../handlers/attestation/retrieve_secret.rs | 18 +++-- .../src/core/control_data/confidential_vm.rs | 15 ++-- security-monitor/src/error.rs | 2 + .../promote_to_confidential_vm.rs | 66 ++++++++---------- .../Cargo.toml | 4 +- .../Makefile | 10 +-- .../README.md | 0 tools/cove_tap_tool/src/attach.rs | 54 +++++++++++++++ .../src/error.rs | 2 + .../src/generate.rs | 53 ++++++--------- .../src/main.rs | 12 ++-- tools/local_attestation/src/append.rs | 68 ------------------- 25 files changed, 283 insertions(+), 231 deletions(-) create mode 100644 confidential-vms/linux_vm/overlay/root/ace_module/Makefile create mode 100644 confidential-vms/linux_vm/overlay/root/ace_module/ace.c rename tools/{local_attestation => cove_tap_tool}/Cargo.toml (88%) rename tools/{local_attestation => cove_tap_tool}/Makefile (90%) rename tools/{local_attestation => cove_tap_tool}/README.md (100%) create mode 100644 tools/cove_tap_tool/src/attach.rs rename tools/{local_attestation => cove_tap_tool}/src/error.rs (94%) rename tools/{local_attestation => cove_tap_tool}/src/generate.rs (58%) rename tools/{local_attestation => cove_tap_tool}/src/main.rs (89%) delete mode 100644 tools/local_attestation/src/append.rs diff --git a/.gitignore b/.gitignore index 3c48340c..86d8269b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ build/* target/* -tools/local_attestation/target +tools/cove_tap_tool/target security-monitor/target configurations/overlay/root/harness/baremetal diff --git a/Makefile b/Makefile index 56d1291f..e5ff42e1 100644 --- a/Makefile +++ b/Makefile @@ -51,11 +51,11 @@ hypervisor: setup devtools confidential_vms: setup devtools hypervisor tools BIN_DIR="$(OVERLAY_ROOT_DIR)/" RELEASE="" $(MAKE) -C $(CONFIDENTIAL_VMS_SOURCE_DIR)/baremetal/ ;\ - PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" ACE_DIR=$(ACE_DIR) $(MAKE) -C $(CONFIDENTIAL_VMS_SOURCE_DIR)/linux_vm/ buildroot ;\ - PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" ACE_DIR=$(ACE_DIR) $(MAKE) -C $(CONFIDENTIAL_VMS_SOURCE_DIR)/linux_vm/ overlay ;\ + # PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" ACE_DIR=$(ACE_DIR) $(MAKE) -C $(CONFIDENTIAL_VMS_SOURCE_DIR)/linux_vm/ buildroot ;\ + PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" ACE_DIR=$(ACE_DIR) $(MAKE) -C $(CONFIDENTIAL_VMS_SOURCE_DIR)/linux_vm/ rootfs ;\ PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" ACE_DIR=$(ACE_DIR) $(MAKE) -C hypervisor rootfs; -hypervisor_dev: +hypervisor_dev: PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" ACE_DIR=$(ACE_DIR) $(MAKE) -C hypervisor dev dev: tools @@ -79,7 +79,7 @@ emulator: setup devtools tools: setup mkdir -p $(TOOLS_WORK_DIR) - PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" ACE_DIR=$(ACE_DIR) CROSS_COMPILE=$(CROSS_COMPILE) $(MAKE) -C tools/local_attestation build + PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" ACE_DIR=$(ACE_DIR) CROSS_COMPILE=$(CROSS_COMPILE) $(MAKE) -C tools/cove_tap_tool build cp -rf $(TOOLS_SOURCE_DIR)/*.sh $(TOOLS_WORK_DIR)/ cp -rf $(TOOLS_SOURCE_DIR)/ace $(TOOLS_WORK_DIR)/ diff --git a/confidential-vms/linux_vm/Makefile b/confidential-vms/linux_vm/Makefile index 0af293b1..45a5b08b 100644 --- a/confidential-vms/linux_vm/Makefile +++ b/confidential-vms/linux_vm/Makefile @@ -23,12 +23,11 @@ LINUX_VM_KERNEL_CONFIG ?= $(CONFIDENTIAL_VMS_LINUX_SOURCE_DIR)/configurations LINUX_VM_BUILDROOT_CONFIG ?= $(CONFIDENTIAL_VMS_LINUX_SOURCE_DIR)/configurations/qemu_riscv64_virt_defconfig LINUX_VM_BUILDROOT_OVERRIDE_DIR ?= $(CONFIDENTIAL_VMS_LINUX_SOURCE_DIR)/configurations/package_override.dev LINUX_VM_PATCHES_DIR ?= $(CONFIDENTIAL_VMS_LINUX_SOURCE_DIR)/patches/linux/6.3-rc4 +LINUX_DIR ?= $(LINUX_VM_BUILDROOT_WORK_DIR)/build/linux-6.3-rc4/ # overlays HYPERVISOR_OVERLAY_DIR ?= $(ACE_DIR)/hypervisor/overlay/ HYPERVISOR_OVERLAY_ROOT_DIR ?= $(HYPERVISOR_OVERLAY_DIR)/root/ HYPERVISOR_OVERLAY_LINUX_VM_DIR ?= $(HYPERVISOR_OVERLAY_ROOT_DIR)/linux_vm/ -# -LOCAL_ATTESTATION_UTILS_DIR ?= $(CONFIDENTIAL_VMS_LINUX_SOURCE_DIR)/../../tools/local_attestation RISCV_GNU_TOOLCHAIN_WORK_DIR ?= $(ACE_DIR)/riscv-gnu-toolchain/ export PATH := $(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH) @@ -60,6 +59,7 @@ buildroot: setup dev: echo "Rebuilding buildroot"; \ + sed "s@^BR2_ROOTFS_OVERLAY=.*@BR2_ROOTFS_OVERLAY=\"$(LINUX_VM_OVERLAY_WORK_DIR)\"@g" -i $(LINUX_VM_BUILDROOT_WORK_DIR)/.config; \ sed "s@^BR2_PACKAGE_OVERRIDE_FILE=.*@BR2_PACKAGE_OVERRIDE_FILE=\"$(LINUX_VM_BUILDROOT_OVERRIDE_DIR)\"@g" -i $(LINUX_VM_BUILDROOT_WORK_DIR)/.config ;\ sed "s@^BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=.*@BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=\"$(LINUX_VM_KERNEL_CONFIG)\"@g" -i $(LINUX_VM_BUILDROOT_WORK_DIR)/.config; \ sed "s@^BR2_TARGET_ROOTFS_EXT2_SIZE=.*@BR2_TARGET_ROOTFS_EXT2_SIZE=\"$(LINUX_VM_BUILDROOT_ROOTFS_SIZE)\"@g" -i $(LINUX_VM_BUILDROOT_WORK_DIR)/.config; \ @@ -67,18 +67,22 @@ dev: overlay: setup mkdir -p $(LINUX_VM_OVERLAY_WORK_DIR) ;\ + mkdir -p $(LINUX_VM_OVERLAY_WORK_ROOT_DIR); \ cp -r $(LINUX_VM_OVERLAY_SOURCE_DIR)/* $(LINUX_VM_OVERLAY_WORK_DIR)/ ;\ + PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" $(MAKE) -s -C $(LINUX_VM_OVERLAY_WORK_ROOT_DIR)/ace_module/ RISCV=$(RISCV_GNU_TOOLCHAIN_WORK_DIR) PATH=$(PATH) ARCH=riscv KDIR=$(LINUX_DIR) CROSS_COMPILE=$(CROSS_COMPILE) CC="riscv64-unknown-linux-gnu-gcc" O=$(LINUX_DIR) ;\ mkdir -p $(HYPERVISOR_OVERLAY_ROOT_DIR) ;\ cp $(LINUX_VM_ROOTFS_SOURCE_DIR)/*.sh $(HYPERVISOR_OVERLAY_ROOT_DIR)/ ;\ - rm -rf $(HYPERVISOR_OVERLAY_LINUX_VM_DIR) ;\ - mkdir -p $(HYPERVISOR_OVERLAY_LINUX_VM_DIR) ;\ + rm -rf $(HYPERVISOR_OVERLAY_LINUX_VM_DIR) && mkdir -p $(HYPERVISOR_OVERLAY_LINUX_VM_DIR) ;\ cp -r $(LINUX_VM_IMAGE) $(HYPERVISOR_OVERLAY_LINUX_VM_DIR)/ ;\ cp -r $(LINUX_VM_BUILDROOT_ROOTFS) $(HYPERVISOR_OVERLAY_LINUX_VM_DIR) ;\ cp -r $(LINUX_VM_BUILDROOT_WORK_DIR)/images/rootfs.cpio $(HYPERVISOR_OVERLAY_LINUX_VM_DIR) ;\ - mkdir -p $(LINUX_VM_OVERLAY_WORK_ROOT_DIR); \ - cp $(ACE_DIR)/tools/ace-tap $(LINUX_VM_OVERLAY_WORK_ROOT_DIR)/ + +rootfs: overlay + PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" $(MAKE) -s -C $(LINUX_VM_BUILDROOT_SOURCE_DIR) RISCV=$(RISCV_GNU_TOOLCHAIN_WORK_DIR) PATH=$(PATH) ARCH=riscv64 KDIR=$(LINUX_DIR) CROSS_COMPILE=$(CROSS_COMPILE) O=$(LINUX_VM_BUILDROOT_WORK_DIR) rootfs-ext2; \ + cp -r $(LINUX_VM_BUILDROOT_WORK_DIR)/images/rootfs.cpio $(HYPERVISOR_OVERLAY_LINUX_VM_DIR); + clean: rm -rf $(ACE_DIR) -.PHONY: all buildroot linux clean overlay rootfs +.PHONY: all buildroot linux clean overlay diff --git a/confidential-vms/linux_vm/hypervisor_rootfs/run_linux_vm.sh b/confidential-vms/linux_vm/hypervisor_rootfs/run_linux_vm.sh index b4153072..3319a8dd 100755 --- a/confidential-vms/linux_vm/hypervisor_rootfs/run_linux_vm.sh +++ b/confidential-vms/linux_vm/hypervisor_rootfs/run_linux_vm.sh @@ -32,7 +32,7 @@ for i in "$@"; do -m=*|--memory=*) MEMORY="${i#*=}" shift - ;; + ;; --daemonize*) INTERACTIVE="-daemonize" shift @@ -55,11 +55,10 @@ ${QEMU_CMD} ${DEBUG_OPTIONS} \ -machine virt -cpu rv64,f=true -smp ${SMP} -m ${MEMORY} \ -kernel ${KERNEL} \ -seed 0 \ - -initrd ${INITRAMFS} \ -global virtio-mmio.force-legacy=false \ -append "console=ttyS0 ro swiotlb=mmnn,force promote_to_cove_guest" \ -device virtio-blk-pci,drive=hd0,iommu_platform=on,disable-legacy=on,disable-modern=off \ -drive if=none,format=raw,file=${DRIVE},id=hd0 \ -device virtio-net-pci,netdev=net0,iommu_platform=on,disable-legacy=on,disable-modern=off \ -netdev user,id=net0,net=192.168.100.1/24,dhcpstart=192.168.100.128,hostfwd=tcp::${HOST_PORT}-:22 \ - -nographic + -nographic diff --git a/confidential-vms/linux_vm/overlay/root/ace_module/Makefile b/confidential-vms/linux_vm/overlay/root/ace_module/Makefile new file mode 100644 index 00000000..12d8028b --- /dev/null +++ b/confidential-vms/linux_vm/overlay/root/ace_module/Makefile @@ -0,0 +1,27 @@ +CONFIG_MODULE_SIG=n + +startstop-objs := start.o stop.o +obj-m += ace.o + +ifeq ($(CONFIG_STATUS_CHECK_GCC),y) + CC=$(STATUS_CHECK_GCC) + ccflags-y += -fanalyzer +endif + +KDIR ?= /lib/modules/$(shell uname -r)/build +PWD := $(CURDIR) + +default: + $(MAKE) -C $(KDIR) CC="$(CC)" M="$(PWD)" modules + rm -f .Module* .modules* .ace* *.symvers *.order ace.mod.* *.o *.mod + +load: + @insmod ace.ko + +clean: + $(MAKE) -C /lib/modules/$(shell uname -r)/build CC="$(CC)" M="$(PWD)" clean + $(RM) other/cat_noblock *.plist + +indent: + clang-format -i *[.ch] + clang-format -i other/*[.ch] \ No newline at end of file diff --git a/confidential-vms/linux_vm/overlay/root/ace_module/ace.c b/confidential-vms/linux_vm/overlay/root/ace_module/ace.c new file mode 100644 index 00000000..287ea693 --- /dev/null +++ b/confidential-vms/linux_vm/overlay/root/ace_module/ace.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include /* usleep_range */ +#include +#include /* single_open, single_release */ +#include /* kmalloc, kfree */ + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Wojciech Ozga "); + +static int ace_init(void){ + volatile u8 *secret; + struct sbiret ret; + int i; + + printk(KERN_ALERT "Requesting secret from the security monitor\n"); + secret = kmalloc(1024*sizeof(u8), GFP_KERNEL); + ret = sbi_ecall(0x434F5647, 9, virt_to_phys((void *) secret), 1024, 0, 0, 0, 0); + if (!ret.error) { + printk(KERN_ALERT "Secret=0x"); + for (i=0; i Result { Ok(Self { pointer, size }) } - pub fn parse_and_verify(&mut self) -> Result { - if self.read_u16()? != ACE_MAGIC_TAP_START { + pub fn parse_and_verify(&mut self) -> Result { + if self.read_u32()? != ACE_MAGIC_TAP_START { return Err(TapError::InvalidMagicStart()); } self.read_u16()?; @@ -32,7 +32,7 @@ impl TeeAttestationPayloadParser { for _ in 0..number_of_lockboxes { let size = self.read_u16()? as usize; let name = self.read_u64()?; - let algorithm = TapLockboxAlgorithm::from_u16(self.read_u16()?)?; + let algorithm = LockboxAlgorithm::from_u16(self.read_u16()?)?; let value = self.read_exact(size-10)?; lockboxes.push(Lockbox { name, @@ -43,10 +43,10 @@ impl TeeAttestationPayloadParser { // TODO: recover symmetric key let symmetric_key = [0u8; 32]; - let payload_encryption_algorithm = TapPayloadEncryptionAlgorithm::from_u16(self.read_u16()?)?; + let payload_encryption_algorithm = PayloadEncryptionAlgorithm::from_u16(self.read_u16()?)?; match payload_encryption_algorithm { - TapPayloadEncryptionAlgorithm::Debug => {}, - TapPayloadEncryptionAlgorithm::AesGcm256 => self.decrypt_aes_gcm_256(symmetric_key)?, + PayloadEncryptionAlgorithm::Debug => {}, + PayloadEncryptionAlgorithm::AesGcm256 => self.decrypt_aes_gcm_256(symmetric_key)?, } let number_of_digests = self.read_u16()?; @@ -54,9 +54,9 @@ impl TeeAttestationPayloadParser { for _ in 0..number_of_digests { let size = self.read_u16()? as usize; let pcr_id = self.read_u16()?; - let algorithm = TapDigestAlgorithm::from_u16(self.read_u16()?)?; + let algorithm = DigestAlgorithm::from_u16(self.read_u16()?)?; let value = self.read_exact(size-4)?; - digests.push(TapDigest { + digests.push(Digest { pcr_id, algorithm, value @@ -69,10 +69,10 @@ impl TeeAttestationPayloadParser { let size = self.read_u16()? as usize; let name = self.read_u64()? as u64; let value = self.read_exact(size-10)?; - secrets.push(TapSecret { name, value }); + secrets.push(Secret { name, value }); } - Ok(TeeAttestationPayload { + Ok(AttestationPayload { lockboxes, digests, secrets, @@ -91,7 +91,7 @@ impl TeeAttestationPayloadParser { let key: Key = symmetric_key.into(); let cipher = Aes256Gcm::new(&key); let nonce = Nonce::from_slice(&nonce); - let tag = Tag::from_slice(&tag); + let tag = Tag::from_slice(&tag); let mut data_slice = unsafe{ core::slice::from_raw_parts_mut(self.pointer as *mut u8, payload_size) }; cipher.decrypt_in_place_detached(nonce, b"", &mut data_slice, &tag)?; Ok(()) @@ -103,6 +103,12 @@ impl TeeAttestationPayloadParser { Ok(value) } + fn read_u32(&mut self) -> Result { + let value = unsafe { (self.pointer as *const u32).read_volatile() }; + self.pointer = self.pointer.wrapping_add(4); + Ok(value) + } + fn read_u64(&mut self) -> Result { let value = unsafe { (self.pointer as *const u64).read_volatile() }; self.pointer = self.pointer.wrapping_add(8); diff --git a/security-monitor/rust-crates/cove_tap/src/serializer.rs b/security-monitor/rust-crates/cove_tap/src/serializer.rs index 87121bb5..a5b21c35 100644 --- a/security-monitor/rust-crates/cove_tap/src/serializer.rs +++ b/security-monitor/rust-crates/cove_tap/src/serializer.rs @@ -6,35 +6,35 @@ use alloc::vec; use crate::spec::*; use alloc::vec::Vec; -pub struct TeeAttestationPayloadSerializer { +pub struct AttestationPayloadSerializer { } -impl TeeAttestationPayloadSerializer { +impl AttestationPayloadSerializer { pub fn new() -> Self { Self {} } - pub fn serialize(&self, mut payload: TeeAttestationPayload) -> Result, TapError> { + pub fn serialize(&self, mut payload: AttestationPayload) -> Result, TapError> { let digests = self.serialize_digests(&mut payload)?; let secrets = self.serialize_secrets(&mut payload)?; let mut encrypted_part = self.encrypt_aes_gcm_256(digests, secrets)?; let mut lockboxes = self.serialize_lockboxes(&mut payload)?; - let total_size = lockboxes.len() + encrypted_part.len() + ACE_FOOTER_SIZE; // 4 bytes for footer + let total_size = lockboxes.len() + encrypted_part.len(); let mut result = vec![]; result.append(&mut ACE_MAGIC_TAP_START.to_le_bytes().to_vec()); result.append(&mut (total_size as u16).to_le_bytes().to_vec()); result.append(&mut lockboxes); result.append(&mut encrypted_part); - result.append(&mut ACE_MAGIC_TAP_END.to_le_bytes().to_vec()); - result.append(&mut ((total_size + ACE_HEADER_SIZE) as u16).to_le_bytes().to_vec()); + // result.append(&mut ACE_MAGIC_TAP_END.to_le_bytes().to_vec()); + // result.append(&mut ((total_size + ACE_HEADER_SIZE) as u16).to_le_bytes().to_vec()); Ok(result) } - fn serialize_lockboxes(&self, payload: &mut TeeAttestationPayload) -> Result, TapError> { + fn serialize_lockboxes(&self, payload: &mut AttestationPayload) -> Result, TapError> { // TODO: sanity check: lockboxes < 1024 let mut result = vec![]; result.append(&mut (payload.lockboxes.len() as u16).to_le_bytes().to_vec()); @@ -48,7 +48,7 @@ impl TeeAttestationPayloadSerializer { Ok(result) } - fn serialize_digests(&self, payload: &mut TeeAttestationPayload) -> Result, TapError> { + fn serialize_digests(&self, payload: &mut AttestationPayload) -> Result, TapError> { // TODO: sanity check: digests < 1024 let mut result = vec![]; result.append(&mut (payload.digests.len() as u16).to_le_bytes().to_vec()); @@ -62,7 +62,7 @@ impl TeeAttestationPayloadSerializer { Ok(result) } - fn serialize_secrets(&self, payload: &mut TeeAttestationPayload) -> Result, TapError> { + fn serialize_secrets(&self, payload: &mut AttestationPayload) -> Result, TapError> { // TODO: sanity check: secrets < 1024 let mut result = vec![]; result.append(&mut (payload.secrets.len() as u16).to_le_bytes().to_vec()); @@ -96,7 +96,7 @@ impl TeeAttestationPayloadSerializer { .unwrap(); let mut result = vec![]; - result.append(&mut (TapPayloadEncryptionAlgorithm::AesGcm256 as u16).to_le_bytes().to_vec()); + result.append(&mut (PayloadEncryptionAlgorithm::AesGcm256 as u16).to_le_bytes().to_vec()); result.append(&mut (nonce.as_slice().len() as u16).to_le_bytes().to_vec()); result.append(&mut nonce.as_slice().to_vec()); result.append(&mut (tag.as_slice().len() as u16).to_le_bytes().to_vec()); diff --git a/security-monitor/rust-crates/cove_tap/src/spec.rs b/security-monitor/rust-crates/cove_tap/src/spec.rs index 7757c4b2..6538be04 100644 --- a/security-monitor/rust-crates/cove_tap/src/spec.rs +++ b/security-monitor/rust-crates/cove_tap/src/spec.rs @@ -4,47 +4,48 @@ use crate::error::TapError; use alloc::vec::Vec; -pub const ACE_HEADER_SIZE: usize = 4; -pub const ACE_FOOTER_SIZE: usize = 4; -pub const ACE_MAGIC_TAP_START: u16 = 0xACE0; -pub const ACE_MAGIC_TAP_END: u16 = 0xACE1; +pub const ACE_HEADER_SIZE: usize = 8; +pub const ACE_FOOTER_SIZE: usize = 8; +pub const ACE_MAGIC_TAP_START: u32 = 0xACE0ACE0; +pub const ACE_MAGIC_TAP_END: u32 = 0xACE1ACE1; +pub const ACE_MAX_TAP_SIZE: usize = 4096; // size of the 4KiB page -pub struct TeeAttestationPayload { +pub struct AttestationPayload { pub lockboxes: Vec, - pub digests: Vec, - pub secrets: Vec, + pub digests: Vec, + pub secrets: Vec, } pub struct Lockbox { pub name: u64, - pub algorithm: TapLockboxAlgorithm, + pub algorithm: LockboxAlgorithm, pub value: Vec, } #[repr(u16)] #[derive(Debug)] -pub enum TapLockboxAlgorithm { +pub enum LockboxAlgorithm { Debug = 0, Rsa2048Sha256Oasp = 1, } -impl TapLockboxAlgorithm { +impl LockboxAlgorithm { pub fn from_u16(value: u16) -> Result { match value { 0 => Ok(Self::Debug), 1 => Ok(Self::Rsa2048Sha256Oasp), - v => Err(TapError::UnsupportedTapLockboxAlgorithm(v)), + v => Err(TapError::UnsupportedLockboxAlgorithm(v)), } } } -pub struct TapDigest { +pub struct Digest { pub pcr_id: u16, - pub algorithm: TapDigestAlgorithm, + pub algorithm: DigestAlgorithm, pub value: Vec, } -impl TapDigest { +impl Digest { pub fn value_in_hex(&self) -> alloc::string::String { use crate::alloc::string::ToString; self.value.iter().map(|b| alloc::format!("{:02x}", b).to_string()).collect::>().join("") @@ -56,18 +57,18 @@ impl TapDigest { } #[repr(u16)] -#[derive(Debug)] -pub enum TapDigestAlgorithm { +#[derive(Debug, PartialEq, Eq)] +pub enum DigestAlgorithm { Debug = 0, Sha512 = 1, } -impl TapDigestAlgorithm { +impl DigestAlgorithm { pub fn from_u16(value: u16) -> Result { match value { 0 => Ok(Self::Debug), 1 => Ok(Self::Sha512), - v => Err(TapError::UnsupportedTapDigestAlgorithm(v)), + v => Err(TapError::UnsupportedDigestAlgorithm(v)), } } @@ -79,24 +80,24 @@ impl TapDigestAlgorithm { } } -pub struct TapSecret { +pub struct Secret { pub name: u64, pub value: Vec, } #[repr(u16)] #[derive(Debug)] -pub enum TapPayloadEncryptionAlgorithm { +pub enum PayloadEncryptionAlgorithm { Debug = 0, AesGcm256 = 1, } -impl TapPayloadEncryptionAlgorithm { +impl PayloadEncryptionAlgorithm { pub fn from_u16(value: u16) -> Result { match value { 0 => Ok(Self::Debug), 1 => Ok(Self::AesGcm256), - v => Err(TapError::UnsupportedTapPayloadEncryptionAlgorithm(v)), + v => Err(TapError::UnsupportedPayloadEncryptionAlgorithm(v)), } } } \ No newline at end of file diff --git a/security-monitor/src/confidential_flow/handlers/attestation/retrieve_secret.rs b/security-monitor/src/confidential_flow/handlers/attestation/retrieve_secret.rs index 4c9009e1..78470abc 100644 --- a/security-monitor/src/confidential_flow/handlers/attestation/retrieve_secret.rs +++ b/security-monitor/src/confidential_flow/handlers/attestation/retrieve_secret.rs @@ -25,22 +25,20 @@ impl RetrieveSecretRequest { pub fn handle(self, confidential_flow: ConfidentialFlow) -> ! { let transformation = ControlDataStorage::try_confidential_vm(confidential_flow.confidential_vm_id(), |ref mut confidential_vm| { - ensure!(self.output_buffer_address.is_aligned_to(PageSize::Size4KiB.in_bytes()), Error::AddressNotAligned())?; + // ensure!(self.output_buffer_address.is_aligned_to(PageSize::Size4KiB.in_bytes()), Error::AddressNotAligned())?; ensure!(self.output_buffer_size <= PageSize::Size4KiB.in_bytes(), Error::AddressNotAligned())?; - let secret = confidential_vm.secret(0); + let secret = confidential_vm.secret(0)?; ensure!(secret.len() <= self.output_buffer_size, Error::AddressNotAligned())?; - - let number_of_usize_elements = secret.len().div_ceil(8); - for offset in 0..number_of_usize_elements { + let mut buffer = [0u8; 8]; + for offset in 0..secret.len().div_ceil(8) { let end_boundary = core::cmp::min(secret.len(), offset + 8); - let mut bytes: [u8; 8] = secret[offset..end_boundary].to_vec().try_into().unwrap(); - (end_boundary..8).for_each(|i| bytes[i] = 0u8); - let value = usize::from_le_bytes(bytes); + (0..end_boundary).for_each(|i| buffer[i] = secret[offset + i]); + (end_boundary..8).for_each(|i| buffer[i] = 0u8); let confidential_memory_address = confidential_vm.memory_protector().translate_address(&self.output_buffer_address.add(offset))?; - unsafe { confidential_memory_address.write_volatile(value) }; + unsafe { confidential_memory_address.write_volatile(usize::from_le_bytes(buffer)) }; } - Ok(SbiResponse::success()) + Ok(SbiResponse::success_with_code(secret.len())) }) .unwrap_or_else(|error| SbiResponse::error(error)); confidential_flow.apply_and_exit_to_confidential_hart(ApplyToConfidentialHart::SbiResponse(transformation)) diff --git a/security-monitor/src/core/control_data/confidential_vm.rs b/security-monitor/src/core/control_data/confidential_vm.rs index e2abdd6a..75e69524 100644 --- a/security-monitor/src/core/control_data/confidential_vm.rs +++ b/security-monitor/src/core/control_data/confidential_vm.rs @@ -11,13 +11,13 @@ use crate::error::Error; use alloc::collections::BTreeMap; use alloc::vec::Vec; use spin::{Mutex, MutexGuard}; -use tap::TapSecret; +use tap::Secret; pub struct ConfidentialVm { id: ConfidentialVmId, confidential_harts: Vec, _measurements: StaticMeasurements, - secrets: Vec, + secrets: Vec, remote_commands: BTreeMap>>, memory_protector: ConfidentialVmMemoryProtector, allowed_external_interrupts: usize, @@ -39,7 +39,7 @@ impl ConfidentialVm { /// /// The id of the confidential VM must be unique. pub fn new( - id: ConfidentialVmId, mut confidential_harts: Vec, _measurements: StaticMeasurements, secrets: Vec, + id: ConfidentialVmId, mut confidential_harts: Vec, _measurements: StaticMeasurements, secrets: Vec, mut memory_protector: ConfidentialVmMemoryProtector, ) -> Self { memory_protector.set_confidential_vm_id(id); @@ -74,8 +74,13 @@ impl ConfidentialVm { &mut self.memory_protector } - pub fn secret(&self, secret_id: usize) -> Vec { - self.secrets.iter().find(|&s| s.name == secret_id as u64).and_then(|s| Some(s.value.to_vec())).unwrap_or(alloc::vec![]) + pub fn secret(&self, secret_id: usize) -> Result, Error> { + for secret in self.secrets.iter() { + if secret.name == secret_id as u64 { + return Ok(secret.value.to_vec()); + } + } + Err(Error::InvalidParameter()) } pub(super) fn deallocate(self) { diff --git a/security-monitor/src/error.rs b/security-monitor/src/error.rs index 6d2ce65f..5e937194 100644 --- a/security-monitor/src/error.rs +++ b/security-monitor/src/error.rs @@ -49,6 +49,8 @@ pub enum Error { AttestationPayloadParsingError(#[from] tap::TapError), #[error("Local attestation failed. Invalid measurements")] LocalAttestationFailed(), + #[error("Local attestation failed. Not supported digest type")] + LocalAttestationNotSupportedDigest(), /* SBI invalid address */ #[error("Address is not aligned")] diff --git a/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs b/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs index aefffe5c..cc5572cc 100644 --- a/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs +++ b/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs @@ -14,7 +14,7 @@ use crate::non_confidential_flow::handlers::supervisor_binary_interface::SbiResp use crate::non_confidential_flow::{ApplyToHypervisorHart, NonConfidentialFlow}; use alloc::vec::Vec; use flattened_device_tree::FlattenedDeviceTree; -use tap::{TapSecret, TeeAttestationPayload, TeeAttestationPayloadParser}; +use tap::{AttestationPayload, AttestationPayloadParser, Secret}; /// Creates a confidential VM in a single-step. This handler implements the Promote to TVM call defined by the COVH ABI in the CoVE /// specification. With this call, the hypervisor presents a state of a virtual machine, requesting the security monitor to promote it to a @@ -28,7 +28,7 @@ use tap::{TapSecret, TeeAttestationPayload, TeeAttestationPayloadParser}; /// * The address of the authentication blob must be either `0` or aligned to 8 bytes. pub struct PromoteToConfidentialVm { fdt_address: ConfidentialVmPhysicalAddress, - tee_attestation_payload_address: Option, + attestation_payload_address: Option, program_counter: usize, hgatp: Hgatp, } @@ -40,13 +40,13 @@ impl PromoteToConfidentialVm { pub fn from_hypervisor_hart(hypervisor_hart: &HypervisorHart) -> Self { let fdt_address = ConfidentialVmPhysicalAddress::new(hypervisor_hart.gprs().read(GeneralPurposeRegister::a0)); - let tee_attestation_payload_address = match hypervisor_hart.gprs().read(GeneralPurposeRegister::a1) { + let attestation_payload_address = match hypervisor_hart.gprs().read(GeneralPurposeRegister::a1) { 0 => None, address => Some(ConfidentialVmPhysicalAddress::new(address)), }; let program_counter = hypervisor_hart.gprs().read(GeneralPurposeRegister::a2); let hgatp = Hgatp::from(hypervisor_hart.csrs().hgatp.read()); - Self { fdt_address, tee_attestation_payload_address, program_counter, hgatp } + Self { fdt_address, attestation_payload_address, program_counter, hgatp } } pub fn handle(self, non_confidential_flow: NonConfidentialFlow) -> ! { @@ -83,14 +83,11 @@ impl PromoteToConfidentialVm { }) .collect(); - let tee_attestation_payload = self.read_tee_attestation_payload(&memory_protector)?; - - let measured_pages_digest = memory_protector.measure()?; - let confidential_hart_digest = confidential_harts[Self::BOOT_HART_ID].measure(); - let measurements = StaticMeasurements::new(measured_pages_digest, confidential_hart_digest); + let attestation_payload = self.read_attestation_payload(&memory_protector).unwrap_or(None); + let measurements = StaticMeasurements::new(memory_protector.measure()?, confidential_harts[Self::BOOT_HART_ID].measure()); debug!("VM measurements: {:?}", measurements); - let secrets = self.authenticate_and_authorize_vm(tee_attestation_payload, &measurements)?; + let secrets = self.authenticate_and_authorize_vm(attestation_payload, &measurements).unwrap_or(alloc::vec![]); ControlDataStorage::try_write(|control_data| { // We have a write lock on the entire control data! Spend here as little time as possible because we are @@ -101,7 +98,7 @@ impl PromoteToConfidentialVm { } fn process_device_tree(&self, memory_protector: &ConfidentialVmMemoryProtector) -> Result { - debug!("Reading flatten device tree (FDT) at memory address 0x{:?}", self.fdt_address); + debug!("Reading flatten device tree (FDT) at memory address {:?}", self.fdt_address); let address_in_confidential_memory = memory_protector.translate_address(&self.fdt_address)?; // Make sure that the address is 8-bytes aligned. Once we ensure this, we can safely read 8 bytes because they must be within // the page boundary. These 8 bytes should contain the `magic` (first 4 bytes) and `size` (next 4 bytes). @@ -131,35 +128,30 @@ impl PromoteToConfidentialVm { Ok(number_of_confidential_harts) } - fn read_tee_attestation_payload( - &self, memory_protector: &ConfidentialVmMemoryProtector, - ) -> Result, Error> { - match self.tee_attestation_payload_address { - Some(tee_attestation_payload_address) => { - debug!("Reading TEE attestation payload (TAP) at memory address {:?}", tee_attestation_payload_address); - let address_in_confidential_memory = memory_protector.translate_address(&tee_attestation_payload_address)?; + fn read_attestation_payload(&self, memory_protector: &ConfidentialVmMemoryProtector) -> Result, Error> { + match self.attestation_payload_address { + Some(attestation_payload_address) => { + debug!("Reading TEE attestation payload (TAP) at memory address {:?}", attestation_payload_address); + let address_in_confidential_memory = memory_protector.translate_address(&attestation_payload_address)?; // Make sure that the address is 8-bytes aligned. Once we ensure this, we can safely read 8 bytes because they must be - // within the page boundary. These 8 bytes should contain the `magic` (first 4 bytes) and `size` (next 4 + // within the page boundary. These 8 bytes should contain the `magic` (first 4 bytes) and `size` (next 2 // bytes). ensure!(address_in_confidential_memory.is_aligned_to(Self::TAP_ALIGNMENT_IN_BYTES), Error::AuthBlobNotAlignedTo32Bits())?; // Below use of unsafe is ok because (1) the security monitor owns the memory region containing the data of the // not-yet-created confidential VM's and (2) there is only one physical hart executing this code. let header: u64 = unsafe { address_in_confidential_memory.read_volatile().try_into().map_err(|_| Error::AuthBlobNotAlignedTo32Bits())? }; - let total_size = ((header >> 16) & 0xFFFF) as usize + tap::ACE_HEADER_SIZE; + let total_size = tap::ACE_HEADER_SIZE + ((header >> 32) & 0xFFFF) as usize; // To work with the authentication blob, we must have it as a continous chunk of memory. We accept only authentication blobs // that fit within 2MiB ensure!(total_size.div_ceil(PageSize::Size2MiB.in_bytes()) == 1, Error::AuthBlobInvalidSize())?; - let large_page = Self::relocate(memory_protector, &tee_attestation_payload_address, total_size, true)?; - + let large_page = Self::relocate(memory_protector, &attestation_payload_address, total_size, true)?; // TODO: we should parse to the blob key that will allow to unlock the lockbox. - let mut parser = unsafe { TeeAttestationPayloadParser::from_raw_pointer(large_page.address().to_ptr(), total_size)? }; - let tee_attestation_payload = parser.parse_and_verify()?; - + let mut parser = unsafe { AttestationPayloadParser::from_raw_pointer(large_page.address().to_ptr(), total_size)? }; + let attestation_payload = parser.parse_and_verify()?; // Clean up, deallocate pages PageAllocator::release_pages(alloc::vec![large_page.deallocate()]); - - Ok(Some(tee_attestation_payload)) + Ok(Some(attestation_payload)) } None => Ok(None), } @@ -168,20 +160,20 @@ impl PromoteToConfidentialVm { /// Performs local attestation. It decides if the VM can be promote into a confidential VM and decrypts the attestation secret intended /// for this confidential VM. fn authenticate_and_authorize_vm( - &self, tee_attestation_payload: Option, measurements: &StaticMeasurements, - ) -> Result, Error> { + &self, attestation_payload: Option, measurements: &StaticMeasurements, + ) -> Result, Error> { use crate::core::control_data::MeasurementDigest; - match tee_attestation_payload { - Some(tee_attestation_payload) => { - debug!("Authenticating and authorizing the confidential VM"); - for digest in tee_attestation_payload.digests.iter() { - debug!("Reference measurement: {:?}={:?}=0x{}", digest.pcr_id, digest.algorithm, digest.value_in_hex()); - // TODO: make sure we compare digests of the same algorithm... + match attestation_payload { + Some(attestation_payload) => { + ensure!(attestation_payload.digests.len() > 1, Error::LocalAttestationFailed())?; + for digest in attestation_payload.digests.iter() { + debug!("Reference PCR{:?}={:?}=0x{}", digest.pcr_id, digest.algorithm, digest.value_in_hex()); + ensure!(digest.algorithm == tap::DigestAlgorithm::Sha512, Error::LocalAttestationNotSupportedDigest())?; let pcr_value = MeasurementDigest::clone_from_slice(&digest.value); ensure!(measurements.compare(digest.pcr_id() as usize, pcr_value)?, Error::LocalAttestationFailed())?; } - debug!("Attestation successful, read {} secrets", tee_attestation_payload.secrets.len()); - Ok(tee_attestation_payload.secrets) + debug!("Attestation succeeded, read {} secrets", attestation_payload.secrets.len()); + Ok(attestation_payload.secrets) } None => Ok(alloc::vec![]), } diff --git a/tools/local_attestation/Cargo.toml b/tools/cove_tap_tool/Cargo.toml similarity index 88% rename from tools/local_attestation/Cargo.toml rename to tools/cove_tap_tool/Cargo.toml index a65d5204..17086406 100644 --- a/tools/local_attestation/Cargo.toml +++ b/tools/cove_tap_tool/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "ace-tap" +name = "cove-tap-tool" version = "0.1.0" authors = ["Wojciech Ozga "] -description = "Tool to create TEE attestation payload for a confidential VM" +description = "Tool to create TVM attestation payload for CoVE's confidential VM" edition = "2021" [dependencies] diff --git a/tools/local_attestation/Makefile b/tools/cove_tap_tool/Makefile similarity index 90% rename from tools/local_attestation/Makefile rename to tools/cove_tap_tool/Makefile index 7a1a8fa7..3d011ced 100644 --- a/tools/local_attestation/Makefile +++ b/tools/cove_tap_tool/Makefile @@ -7,21 +7,21 @@ RELEASE = --release CHAIN=riscv64gc-unknown-linux-gnu TARGET = --target=$(CHAIN) RUSTFLAGS = -C linker=riscv64-unknown-linux-gnu-gcc -EXEC_NAME = ace-tap +EXEC_NAME = cove-tap-tool MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) MAKEFILE_SOURCE_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) ACE_DIR := $(if $(ACE_DIR),$(ACE_DIR),$(MAKEFILE_SOURCE_DIR)../build/target/) -WORK_DIR=$(ACE_DIR)/local_attestation +WORK_DIR=$(ACE_DIR)/cove_tap_tool TOOLS_DIR=$(ACE_DIR)/tools -PLATFORM_RISCV_ABI ?= lp64d +PLATFORM_RISCV_ABI ?= lp64d PLATFORM_RISCV_ISA ?= rv64gc -PLATFORM_RISCV_XLEN ?= 64 +PLATFORM_RISCV_XLEN ?= 64 CROSS_COMPILE ?= riscv64-unknown-linux-gnu- -all: build +all: build build: fmt echo "Building Local Attestation utility" ;\ diff --git a/tools/local_attestation/README.md b/tools/cove_tap_tool/README.md similarity index 100% rename from tools/local_attestation/README.md rename to tools/cove_tap_tool/README.md diff --git a/tools/cove_tap_tool/src/attach.rs b/tools/cove_tap_tool/src/attach.rs new file mode 100644 index 00000000..ecada79c --- /dev/null +++ b/tools/cove_tap_tool/src/attach.rs @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: 2024 IBM Corporation +// SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich +// SPDX-License-Identifier: Apache-2.0 +use crate::error::Error; +use byteorder::WriteBytesExt; +use std::fs::OpenOptions; +use std::io::BufReader; +use std::io::Read; +use std::io::Seek; +use std::io::SeekFrom; + +pub fn attach_tap( + input_file: String, + tap_file_name: String, + output_file: Option, +) -> Result<(), Error> { + let output_file_name = match output_file { + Some(f) if input_file != f => { + std::fs::copy(input_file, f.clone())?; + f + } + Some(f) => f, + None => input_file, + }; + let offset = find_placehoder(&output_file_name)?; + // clear the placeholder + let mut output_file = OpenOptions::new().write(true).open(output_file_name)?; + output_file.seek(SeekFrom::Start(offset))?; + (tap::ACE_HEADER_SIZE..tap::ACE_MAX_TAP_SIZE).try_for_each(|_| output_file.write_u8(0u8))?; + // write expected TAP from the beginning of the offset + output_file.seek(SeekFrom::Start(offset))?; + let mut tap_file = OpenOptions::new().read(true).open(tap_file_name)?; + std::io::copy(&mut tap_file, &mut output_file)?; + println!("TAP attached successfully"); + Ok(()) +} + +fn find_placehoder(output_file_name: &str) -> Result { + let output_file = OpenOptions::new().read(true).open(output_file_name)?; + let mut buf = BufReader::new(output_file); + let mut buffer = [0u8; 4]; + let mut offset = 0u64; + while let Ok(bytes_read) = buf.read(&mut buffer) { + if bytes_read == 0 { + break; + } + if u32::from_le_bytes(buffer) == tap::ACE_MAGIC_TAP_START { + println!("Found TAP placeholder at offset: {:x}", offset); + return Ok(offset); + } + offset += bytes_read as u64; + } + Err(Error::PlaceholderError()) +} diff --git a/tools/local_attestation/src/error.rs b/tools/cove_tap_tool/src/error.rs similarity index 94% rename from tools/local_attestation/src/error.rs rename to tools/cove_tap_tool/src/error.rs index 781c7781..6dee00fe 100644 --- a/tools/local_attestation/src/error.rs +++ b/tools/cove_tap_tool/src/error.rs @@ -20,6 +20,8 @@ pub enum Error { CannotOpenFile(String), #[error("Could not parse int")] IntParseError(#[from] core::num::ParseIntError), + #[error("Placeholder error")] + PlaceholderError(), } impl From for Error { diff --git a/tools/local_attestation/src/generate.rs b/tools/cove_tap_tool/src/generate.rs similarity index 58% rename from tools/local_attestation/src/generate.rs rename to tools/cove_tap_tool/src/generate.rs index 83138c83..b6829e3b 100644 --- a/tools/local_attestation/src/generate.rs +++ b/tools/cove_tap_tool/src/generate.rs @@ -5,17 +5,17 @@ use crate::ensure; use crate::error::Error; use std::fs::OpenOptions; use std::io::Write; +use tap::AttestationPayload; +use tap::AttestationPayloadSerializer; +use tap::Digest; +use tap::DigestAlgorithm; use tap::Lockbox; -use tap::TapDigest; -use tap::TapDigestAlgorithm; -use tap::TapLockboxAlgorithm; -use tap::TapSecret; -use tap::TeeAttestationPayload; -use tap::TeeAttestationPayloadSerializer; +use tap::LockboxAlgorithm; +use tap::Secret; pub fn generate_tap( pcrs: Vec<(u16, Vec)>, - confidential_vm_secrets: Vec<(usize, Vec)>, + confidential_vm_secrets: Vec<(u64, Vec)>, tee_public_keys_files: Vec, output_file: String, ) -> Result<(), Error> { @@ -25,7 +25,7 @@ pub fn generate_tap( )?; ensure!( tee_public_keys_files.len() < 1024, - Error::InvalidParameter(format!("Confidential VM TAP support max 1024 lockboxes")) + Error::InvalidParameter(format!("Confidential VM TAP supports max 1024 lockboxes")) )?; // let symmetric_key = [0u8; 32]; @@ -33,15 +33,15 @@ pub fn generate_tap( let mut lockboxes = vec![]; lockboxes.push(Lockbox { name: 0u64, - algorithm: TapLockboxAlgorithm::Debug, + algorithm: LockboxAlgorithm::Debug, value: [0xFF; 16].to_vec(), }); let mut digests = vec![]; for (pcr_id, pcr_value) in pcrs.into_iter() { - let tap_digest = TapDigest { + let tap_digest = Digest { pcr_id, - algorithm: TapDigestAlgorithm::Sha512, + algorithm: DigestAlgorithm::Sha512, value: pcr_value, }; println!("Writing PCR{}={}", pcr_id, tap_digest.value_in_hex()); @@ -49,18 +49,22 @@ pub fn generate_tap( } let mut secrets = vec![]; - secrets.push(TapSecret { - name: 0, - value: [0xFF; 16].to_vec(), - }); + for (secret_name, secret_value) in confidential_vm_secrets.into_iter() { + let secret = Secret { + name: secret_name, + value: secret_value, + }; + println!("Writing secret {}", secret_name); + secrets.push(secret); + } - let tap = TeeAttestationPayload { + let tap = AttestationPayload { lockboxes, digests, secrets, }; - let serializer = TeeAttestationPayloadSerializer::new(); + let serializer = AttestationPayloadSerializer::new(); let serialized = serializer.serialize(tap)?; // write the entire TAP to the output file @@ -73,20 +77,5 @@ pub fn generate_tap( .map_err(|_| Error::CannotOpenFile(output_file.clone()))?; output.write(&serialized)?; - // test if everything went well - use std::io::Read; - use std::io::{Seek, SeekFrom}; - output.seek(SeekFrom::End(-1 * (serialized.len() as i64)))?; - let mut test_data: Vec = vec![0u8; serialized.len()]; - output.read_exact(&mut test_data)?; - let mut parser = tap::TeeAttestationPayloadParser::from_raw_pointer( - test_data.as_mut_ptr() as *const u8, - test_data.len() - 4, - )?; - let tap = parser.parse_and_verify()?; - for digest in tap.digests.iter() { - println!("Read PCR{}={}", digest.pcr_id, digest.value_in_hex()); - } - Ok(()) } diff --git a/tools/local_attestation/src/main.rs b/tools/cove_tap_tool/src/main.rs similarity index 89% rename from tools/local_attestation/src/main.rs rename to tools/cove_tap_tool/src/main.rs index c02382a9..d3f24abd 100644 --- a/tools/local_attestation/src/main.rs +++ b/tools/cove_tap_tool/src/main.rs @@ -4,7 +4,7 @@ use crate::error::Error; use clap::{Parser, Subcommand}; -mod append; +mod attach; mod error; mod generate; @@ -17,7 +17,7 @@ struct Args { #[derive(Subcommand, Debug, Clone)] enum Commands { - Append { + Attach { #[arg(short, long)] input_file: String, #[arg(short, long)] @@ -28,8 +28,8 @@ enum Commands { Generate { #[arg(short='p', long="pcrs", value_parser = parse_key_val::, value_delimiter = ',', required=true)] pcrs: Vec<(u16, Vec)>, - #[arg(long="secrets", value_parser = parse_key_val::, value_delimiter = ',')] - confidential_vm_secrets: Vec<(usize, Vec)>, + #[arg(long="secrets", value_parser = parse_key_val::, value_delimiter = ',')] + confidential_vm_secrets: Vec<(u64, Vec)>, #[clap(short, long, value_delimiter = ' ', num_args = 1..)] tee_public_keys_files: Vec, #[arg(short, long)] @@ -69,11 +69,11 @@ pub fn decode_hex(s: &str) -> Result, core::num::ParseIntError> { fn main() -> Result<(), Error> { Ok(match Args::parse().cmd { - Commands::Append { + Commands::Attach { input_file, tap_file, output_file, - } => append::append_tap(input_file, tap_file, output_file), + } => attach::attach_tap(input_file, tap_file, output_file), Commands::Generate { pcrs, confidential_vm_secrets, diff --git a/tools/local_attestation/src/append.rs b/tools/local_attestation/src/append.rs deleted file mode 100644 index aa81193f..00000000 --- a/tools/local_attestation/src/append.rs +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-FileCopyrightText: 2024 IBM Corporation -// SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich -// SPDX-License-Identifier: Apache-2.0 -use crate::error::Error; -use byteorder::WriteBytesExt; -use std::fs::OpenOptions; -use std::io::Read; -use std::io::Seek; -use std::io::SeekFrom; - -pub fn append_tap( - input_file: String, - tap_file_name: String, - output_file: Option, -) -> Result<(), Error> { - let output_file_name = match output_file { - Some(f) if input_file != f => { - std::fs::copy(input_file, f.clone())?; - f - } - Some(f) => f, - None => input_file, - }; - let mut output_file_size = file_size(&output_file_name)?; - - let mut output_file = OpenOptions::new() - .read(true) - .write(true) - .append(true) - .open(output_file_name)?; - - // check first if there is a TAP already appended - output_file.seek(SeekFrom::End(-4))?; - let mut footer = [0u8; 4]; - output_file.read_exact(&mut footer)?; - if u16::from_le_bytes([footer[0], footer[1]]) == tap::spec::ACE_MAGIC_TAP_END { - println!("Removing old TAP"); - let old_tap_size = u16::from_le_bytes([footer[2], footer[3]]) as u64; - output_file.set_len(output_file_size - old_tap_size)?; - output_file.seek(SeekFrom::End(0))?; - output_file_size -= old_tap_size; - } - - // TAP must be 8-bytes aligned - let mut aligned = (output_file_size >> 3) << 3; - if aligned < output_file_size { - aligned = ((output_file_size >> 3) + 1) << 3; - } - let padding_size_in_bytes = aligned - output_file_size; - println!( - "Padding with {} bytes to align to u64", - padding_size_in_bytes - ); - (0..padding_size_in_bytes).try_for_each(|_| output_file.write_u8(0u8))?; - - let mut tap_file = OpenOptions::new().read(true).open(tap_file_name)?; - std::io::copy(&mut tap_file, &mut output_file)?; - - println!("TAP appended successfully"); - Ok(()) -} - -fn file_size(file_name: &str) -> Result { - Ok(OpenOptions::new() - .read(true) - .open(file_name)? - .seek(SeekFrom::End(0))?) -}