diff --git a/Makefile b/Makefile index 98159a2..a96a216 100644 --- a/Makefile +++ b/Makefile @@ -85,9 +85,9 @@ emulator: setup devtools fi tools: setup - mkdir -p $(TOOLS_WORK_DIR) - cp -rf $(TOOLS_SOURCE_DIR)/*.sh $(TOOLS_WORK_DIR)/ - cp -rf $(TOOLS_SOURCE_DIR)/ace $(TOOLS_WORK_DIR)/ + mkdir -p $(TOOLS_WORK_DIR) ;\ + cp -rf $(TOOLS_SOURCE_DIR)/*.sh $(TOOLS_WORK_DIR)/ ;\ + PATH="$(RISCV_GNU_TOOLCHAIN_WORK_DIR)/bin:$(PATH)" TOOLS_WORK_DIR=$(TOOLS_WORK_DIR) ACE_DIR=$(ACE_DIR) $(MAKE) -C tools/cove_tap_tool; verify: rm -rf $(ACE_DIR)/security_monitor/verify/ diff --git a/README.md b/README.md index 2b44414..3ecf2f7 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ACE-RISCV is an open-source project, whose goal is to deliver a confidential computing framework with a formally proven security monitor. It is based on the [canonical architecture](https://dl.acm.org/doi/pdf/10.1145/3623652.3623668) and targets RISC-V with the goal of being portable to other architectures. The formal verification efforts focus on the [security monitor implementation](security-monitor/). We invite collaborators to work with us to push the boundaries of provable confidential computing technology. -This project implements the RISC-V CoVE spec's deployment model 3 referenced in [Appendix D](https://github.com/riscv-non-isa/riscv-ap-tee/blob/main/). The formal specification is embedded in the security monitor's source code and the proofs are in [verification/ folder](verification/). Please read our [paper](https://dl.acm.org/doi/pdf/10.1145/3623652.3623668) to learn about the approach and goals. +This project implements the RISC-V CoVE spec's deployment model 3 referenced in [Appendix D](https://github.com/riscv-non-isa/riscv-ap-tee/blob/main/). The formal specification is embedded in the security monitor's source code and the proofs are in the [verification/](verification/) folder. Please read our [paper](https://dl.acm.org/doi/pdf/10.1145/3623652.3623668) to learn about the approach and goals. ## Hardware requirements We are currently building on RISC-V 64-bit with integer (I), atomic (A) and hypervisor extentions (H), physical memory protection (PMP), memory management unit (MMU), IOPMP, core-local interrupt controller (CLINT), and supervisor timecmp extension (Sstc). @@ -53,7 +53,7 @@ cargo install cargo-binutils ``` ### Sources -Checkout this repository with submodules (this takes a long time!): +Checkout this repository with submodules: ``` git clone --recurse-submodules git@github.com:IBM/ACE-RISCV.git ``` @@ -127,6 +127,55 @@ To run the sample Linux OS as a confidential VM (login: root, password: passwd) ./run_linux_vm.sh ``` +## Local attestation +Local attestation allows you to expose secrets (e.g., dm-crypt/LUKS key, TLS pre-shared key, etc) to your confidential VM in a secure way. + +Collect reference measurements of your virtual machines, like kernel, initrd, initial boot hart state. +Below as, an example, we just collect kernel measurement: +``` +cove-tap-tool measure --kernel-file $ACE_DIR/confidential_vms/linux_vm/buildroot/images/Image +# Example output: +# Digest 0x86774eec200ca6552cbc50211e4b32e7a4ba815c190d56b11ffabc8df1ebb6d9c41d04a64099d860b90c65729a28ded8 +``` + +Create a TVM attestation payload (TAP) that contains a secret (0xc0ffee), which will be release to confidential VMs whose measurement in PCR4 equals the reference measurement of your kernel. +Please note that in real systems you would define values of more PCRs to ensure the integrity of the firmware, security monitor, initrd, etc. +``` +cove-tap-tool generate --output-file=$ACE_DIR/cove_tap --pcrs 4=0x86774eec200ca6552cbc50211e4b32e7a4ba815c190d56b11ffabc8df1ebb6d9c41d04a64099d860b90c65729a28ded8 --secrets 0=0xc0ffee +# Example output: +# Writing PCR4=86774eec200ca6552cbc50211e4b32e7a4ba815c190d56b11ffabc8df1ebb6d9c41d04a64099d860b90c65729a28ded8 +# Writing secret 0 +``` + +Attach the TAP to the kernel image: +``` +cove-tap-tool append --tap-file=$ACE_DIR/cove_tap --kernel-file=$ACE_DIR/confidential_vms/linux_vm/buildroot/images/Image +``` + +Run again the hypervisor and then your confidential VM (see section `Run and Test`). +You should see the output +``` +#ACE: Reference PCR4=Sha512=0x86774eec200ca6552cbc50211e4b32e7a4ba815c190d56b11ffabc8df1ebb6d9c41d04a64099d860b90c65729a28ded8 +#ACE: Attestation succeeded, read 1 secret +``` + +You can read the secret from the inside of the confidential VM: +``` +# if the root file system has not been mounted, then execute below: +mount /dev/vda /root +cd /root/root/ace_module +insmod ace.ko +``` + +You should see the secret: +``` +[ 203.051959] Requesting secret from the security monitor +[ 203.107150] Secret=0xc0ffee +``` + +Integrating local attestation with dm-crypt/LUKS is work in progress. When finished, you will encrypt your rootfs and pass the decryption key via TAP. +A script in initrd will then retrieve the decryption key from TAP and decrypt the rootfs. + # License This repository is distributed under the terms of the Apache 2.0 License, see [LICENSE](LICENSE). diff --git a/tools/cove_tap_tool/Makefile b/tools/cove_tap_tool/Makefile index 3d011ce..d429d22 100644 --- a/tools/cove_tap_tool/Makefile +++ b/tools/cove_tap_tool/Makefile @@ -4,31 +4,28 @@ # SPDX-License-Identifier: Apache-2.0 CARGO = cargo RELEASE = --release -CHAIN=riscv64gc-unknown-linux-gnu -TARGET = --target=$(CHAIN) -RUSTFLAGS = -C linker=riscv64-unknown-linux-gnu-gcc 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)/cove_tap_tool -TOOLS_DIR=$(ACE_DIR)/tools +WORK_DIR = $(ACE_DIR)/cove_tap_tool +TOOLS_WORK_DIR ?= $(ACE_DIR)/tools -PLATFORM_RISCV_ABI ?= lp64d -PLATFORM_RISCV_ISA ?= rv64gc -PLATFORM_RISCV_XLEN ?= 64 -CROSS_COMPILE ?= riscv64-unknown-linux-gnu- +PLATFORM_RISCV_ABI ?= lp64d +PLATFORM_RISCV_ISA ?= rv64gc +PLATFORM_RISCV_XLEN ?= 64 +CROSS_COMPILE ?= riscv64-unknown-linux-gnu- all: build build: fmt echo "Building Local Attestation utility" ;\ mkdir -p $(WORK_DIR) ; \ - rm -f $(WORK_DIR)/$(CHAIN)/release/$(EXEC_NAME); \ - RUSTFLAGS='$(RUSTFLAGS)' CARGO_TARGET_DIR=$(WORK_DIR) INSTALL_DIR=$(ACE_DIR)/ $(CARGO) build $(RELEASE) $(TARGET) ; \ - cp $(WORK_DIR)/$(CHAIN)/release/$(EXEC_NAME) $(TOOLS_DIR)/ ; + rm -f $(WORK_DIR)/release/$(EXEC_NAME); \ + RUSTFLAGS='$(RUSTFLAGS)' CARGO_TARGET_DIR=$(WORK_DIR) INSTALL_DIR=$(ACE_DIR)/ $(CARGO) build $(RELEASE) ; \ + cp $(WORK_DIR)/release/$(EXEC_NAME) $(TOOLS_WORK_DIR)/ ; doc: @$(CARGO) doc diff --git a/tools/cove_tap_tool/src/attach.rs b/tools/cove_tap_tool/src/attach.rs index 85e0078..f787ccc 100644 --- a/tools/cove_tap_tool/src/attach.rs +++ b/tools/cove_tap_tool/src/attach.rs @@ -10,23 +10,24 @@ use std::io::Seek; use std::io::SeekFrom; pub fn attach_tap( - input_file: String, + kernel_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())?; + Some(f) if kernel_file != f => { + std::fs::copy(kernel_file, f.clone())?; f } Some(f) => f, - None => input_file, + None => kernel_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))?; - (riscv_cove_tap::ACE_HEADER_SIZE..riscv_cove_tap::ACE_MAX_TAP_SIZE).try_for_each(|_| output_file.write_u8(0u8))?; + (riscv_cove_tap::ACE_HEADER_SIZE..riscv_cove_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)?; diff --git a/tools/cove_tap_tool/src/generate.rs b/tools/cove_tap_tool/src/generate.rs index c8d3fd7..b69f7ef 100644 --- a/tools/cove_tap_tool/src/generate.rs +++ b/tools/cove_tap_tool/src/generate.rs @@ -3,8 +3,6 @@ // SPDX-License-Identifier: Apache-2.0 use crate::ensure; use crate::error::Error; -use std::fs::OpenOptions; -use std::io::Write; use riscv_cove_tap::AttestationPayload; use riscv_cove_tap::AttestationPayloadSerializer; use riscv_cove_tap::Digest; @@ -12,6 +10,8 @@ use riscv_cove_tap::DigestAlgorithm; use riscv_cove_tap::Lockbox; use riscv_cove_tap::LockboxAlgorithm; use riscv_cove_tap::Secret; +use std::fs::OpenOptions; +use std::io::Write; pub fn generate_tap( pcrs: Vec<(u16, Vec)>, diff --git a/tools/cove_tap_tool/src/main.rs b/tools/cove_tap_tool/src/main.rs index a99731b..f25b79e 100644 --- a/tools/cove_tap_tool/src/main.rs +++ b/tools/cove_tap_tool/src/main.rs @@ -20,7 +20,7 @@ struct Args { enum Commands { Attach { #[arg(short, long)] - input_file: String, + kernel_file: String, #[arg(short, long)] tap_file: String, #[arg(short, long)] @@ -75,10 +75,10 @@ pub fn decode_hex(s: &str) -> Result, core::num::ParseIntError> { fn main() -> Result<(), Error> { Ok(match Args::parse().cmd { Commands::Attach { - input_file, + kernel_file, tap_file, output_file, - } => attach::attach_tap(input_file, tap_file, output_file), + } => attach::attach_tap(kernel_file, tap_file, output_file), Commands::Generate { pcrs, confidential_vm_secrets,