Skip to content

Commit

Permalink
minor improvements to documentation and scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
gianlucascopelliti committed Jun 3, 2024
1 parent 708ea93 commit 7c046b1
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 92 deletions.
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ setup_luks:
mkdir -p $(BUILD_DIR)/luks
./guest-vm/setup_luks.sh -in $(IMAGE) -out $(LUKS_IMAGE)

fetch_vm_config_template:
fetch_vm_config_template: init_dir
cp $(VM_CONF_PATH) $(VM_CONF_TEMPLATE)

attest_luks_vm:
Expand All @@ -122,9 +122,9 @@ ssh:
ssh -p $(VM_PORT) -o UserKnownHostsFile=$(SSH_HOSTS_FILE) $(VM_USER)@$(VM_HOST)

init_dir:
mkdir -p $(BUILD_DIR)
mkdir -p $(BIN_DIR)
mkdir -p $(GUEST_DIR)
@mkdir -p $(BUILD_DIR)
@mkdir -p $(BIN_DIR)
@mkdir -p $(GUEST_DIR)

clean:
rm -rf $(BUILD_DIR)
Expand Down
128 changes: 78 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
# SNPGuard

This repository demonstrates an end-to-end secured setup for a SEV-SNP VM. To
achieve this, we build on the [ideas from the open source community](https://www.youtube.com/watch?v=4wZnl0njxm8) and use the attestation process of
SEV-SNP in combination with software tools like full authenticated disk
encryption to provide a secure SEV setup. While the official [AMD repo](https://github.com/AMDESE/AMDSEV/tree/snp-latest)
explains how to set up a SEV-SNP VM, it does not cover these topics at all.
achieve this, we build on the [ideas from the open source
community](https://www.youtube.com/watch?v=4wZnl0njxm8) and use the attestation
process of SEV-SNP in combination with software tools like full authenticated
disk encryption to provide a secure confidential VM (CVM) setup. While the
official [AMD repo](https://github.com/AMDESE/AMDSEV/tree/snp-latest) explains
how to set up a SEV-SNP VM, it does not cover these topics.

Currently, this repo is mainly intended as a technical demo and NOT intended to
be used in any kind of production scenario.

This repo is part of the SysTEX24 Tool Paper "SNPGuard: Remote Attestation of SEV-SNP VMs Using Open Source Tools". Please cite as
This repo is part of the SysTEX24 Tool Paper _"SNPGuard: Remote Attestation of
SEV-SNP VMs Using Open Source Tools"_. Please cite as follows:

```bibtex
@article{wilke2024snpguard,
title = {{SNPG}uard: Remote Attestation of {SEV-SNP} {VM}s Using Open Source Tools},
author = {Luca Wilke and Gianluca Scopelliti},
year={2024},
note ={To appear at SysTEX 2024}
@inproceedings{wilke2024snpguard,
author = {Wilke, Luca and Scopelliti, Gianluca},
title = {SNPGuard: Remote Attestation of SEV-SNP VMs Using Open Source Tools},
year = {2024},
booktitle = {Proceedings of the 7th Workshop on System Software for Trusted Execution},
series = {SysTEX '24}
}
```

We explicitly decided to boot into a feature rich initramfs to enable easy
tweaking of the boot process to explore novel ideas.

The workflow consists of five different stages:

1. [Install dependencies](#install-dependencies)
Expand All @@ -31,15 +33,18 @@ The workflow consists of five different stages:
5. Run: [integrity](#run-integrity-only-workflow) and
[encrypted](#run-encrypted-workflow) workflows

The first three steps are supposed to be done only once, unless you wish to
install updated versions of the SNP tools and packages. Except for preparing the
host and running VMs, the other steps do not need to be executed on a SNP
machine.
Steps 1 to 3 are supposed to be done only once, unless you wish to install
updated versions of the SNP tools and packages.

Note: the guide below is intended for users running a Debian-based Linux
distribution such as Ubuntu or Debian. If you are using a different distribution
most of our scripts likely will not work out of the box but will require some
adaptation.
In order to run our workflows, a machine with AMD EPYC 7xx3 (Milan) or 9xx4
(Genoa) is required. The guide below assume that all steps are performed
directly on the SNP host, although this is not strictly required for steps 1, 2
and 4.

Note: the guide below is intended for users running a recent Debian-based Linux
distribution such as Ubuntu or Debian, and it has been tested successfully on
Ubuntu 22.04 LTS. If you are using a different distribution, some scripts might
not work out of the box and might require some adaptation.

## Install dependencies

Expand Down Expand Up @@ -71,7 +76,8 @@ these repositories in [our
organization](https://github.com/orgs/SNPGuard/repositories) that can be used to
build the SEV-SNP toolchain. Each of the options below can be configured to use
our snapshots, and we recommend using them for the time being. This is only a
temporary workaround, as Linux kernel 6.10 is supposed to contain SEV-SNP hypervisor support.
temporary workaround, as Linux kernel 6.10 is supposed to contain SEV-SNP
hypervisor support.

### Option 1: Download pre-built packages

Expand Down Expand Up @@ -212,7 +218,7 @@ Note: outputs may slightly differ.
```bash
# Check kernel version
uname -r
# 6.5.0-rc2-snp-host-ad9c0bf475ec
# 6.9.0-rc7-snp-host-05b10142ac6a

# Check if SEV is among the CPU flags
grep -w sev /proc/cpuinfo
Expand All @@ -229,11 +235,15 @@ cat /sys/module/kvm_amd/parameters/sev_snp

# Check if SEV is enabled in the kernel
sudo dmesg | grep -i -e rmp -e sev
# SEV-SNP: RMP table physical address 0x0000000035600000 - 0x0000000075bfffff
# ccp 0000:23:00.1: sev enabled
# ccp 0000:23:00.1: SEV-SNP API:1.51 build:1
# SEV supported: 410 ASIDs
# SEV-ES and SEV-SNP supported: 99 ASIDs
# SEV-SNP: RMP table physical range [0x000000bf7e800000 - 0x000000c03f0fffff]
# SEV-SNP: Reserving start/end of RMP table on a 2MB boundary [0x000000c03f000000]
# ccp 0000:01:00.5: sev enabled
# ccp 0000:01:00.5: SEV firmware update successful
# ccp 0000:01:00.5: SEV API:1.55 build:21
# ccp 0000:01:00.5: SEV-SNP API:1.55 build:21
# kvm_amd: SEV enabled (ASIDs 510 - 1006)
# kvm_amd: SEV-ES enabled (ASIDs 1 - 509)
# kvm_amd: SEV-SNP enabled (ASIDs 1 - 509)
```

## Prepare guest
Expand All @@ -252,7 +262,8 @@ make unpack_kernel
### Step 1: Build custom initramfs

We need to build a customized initramfs (i.e., initial RAM disk) to configure
boot options at early userspace and enable our workflows.
boot options at early userspace and enable our workflows. This allows easy
tweaking of the boot process to explore novel ideas.

We do this by leveraging Docker. In short, we run an Ubuntu container, and then
we export its filesystem on `build/initramfs/`. Afterwards, we make the
Expand All @@ -272,34 +283,37 @@ make initramfs

### Step 2: Prepare guest image

#### Option A: use an existing image
To run our workflows, we recommend creating a new guest image from scratch, but
we also support running from an existing image.

Note: if you wish to run our integrity-only workflow you should make sure to
delete *all secrets* from the guest VM (see
[below](#run-integrity-only-workflow)). SSH keys, instead, are regenerated
automatically.
#### Option A: create a new image

```bash
# Run VM for configuration
make run IMAGE=<your_image>
# create image (will be stored under build/guest/sevsnptest.qcow2)
make create_new_vm

# run image for initial setup
make run_setup

# Copy kernel and headers to guest
# note: if the guest does not have an IP address check below instructions
scp -P 2222 build/snp-release/linux/guest/*.deb <username>@localhost:
```

Continue with [checking the guest configuration](#guest-configuration) from within in the guest.

#### Option B: create a new image
#### Option B: use an existing image

```bash
# create image (will be stored under build/guest/sevsnptest.qcow2)
make create_new_vm
Note: if you wish to run our integrity-only workflow you should make sure to
delete *all secrets* from the guest VM (see
[below](#run-integrity-only-workflow)). SSH keys, instead, are regenerated
automatically.

# run image for initial setup
make run_setup
```bash
# Run VM for configuration
make run IMAGE=<your_image>

# Copy kernel and headers to guest
# note: if the guest does not have an IP address check below instructions
scp -P 2222 build/snp-release/linux/guest/*.deb <username>@localhost:
```

Expand Down Expand Up @@ -343,18 +357,24 @@ make fetch_vm_config_template

The template will then be stored in `./build/guest/vm-config-template.toml`. It
is important to properly configure the template according to the host and guest
configuration. Most of the options will be automatically configured by our
scripts, but the user should manually check the following options to ensure they
are correct (the template contains useful information to understand them):
configuration.

**NOTE**: Most of the options will be automatically configured by our scripts,
but the user should manually check the following options to ensure they are
correct (the template contains useful information to understand them):

- `host_cpu_family`
- `platform_info`
- `min_commited_tcb`

**Caution**: The make command above adds the `console=ttyS0` option to the kernel command line of the VM. This enables console output from the VM on the terminal, making it much easier to follow the steps in this manual and to debug potential errors.
However, this is not a secure production setup, as all console data passes through unencrypted host memory.
In addition, it increases the attack surface of the hypervisor.
If you are running the VM locally this does not matter, but for a remote production setup, you should remove this option from the template config file and only log in via SSH.
**Caution**: The make command above adds the `console=ttyS0` option to the
kernel command line of the VM. This enables console output from the VM on the
terminal, making it much easier to follow the steps in this manual and to debug
potential errors. However, this is not a secure production setup, as all console
data passes through unencrypted host memory. In addition, it increases the
attack surface of the hypervisor. If you are running the VM locally this does
not matter, but for a remote production setup, you should remove this option
from the template config file and only log in via SSH.

## Run integrity-only workflow

Expand Down Expand Up @@ -481,6 +501,10 @@ Both commands above accept the following parameters:
- `VM_PORT`: port of the guest VM (default: `2222`)
- `VM_USER`: user of the guest VM used for login (default: `ubuntu`)

**Note**: attestation may fail if the host CPU family, minimum TCB and platform
info are not the expected ones, as explained
[above](#step-3-prepare-template-for-attestation).

## Run encrypted workflow

### Step 1: Prepare dm-crypt
Expand Down Expand Up @@ -535,6 +559,10 @@ still use its original keys. Therefore, it is up to the guest owner to verify
the authenticity of future SSH connections by checking that the fingerprints
match the expected values.

**Note**: attestation may fail if the host CPU family, minimum TCB and platform
info are not the expected ones, as explained
[above](#step-3-prepare-template-for-attestation).

## Optional features

### ID Block and an ID Author block
Expand Down
2 changes: 1 addition & 1 deletion guest-vm/setup_luks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ sudo mkfs.ext4 /dev/mapper/snpguard_root
sudo mount $SRC_ROOT_FS_DEVICE $SRC_FOLDER
sudo mount /dev/mapper/snpguard_root $DST_FOLDER

echo "Copying files.."
echo "Copying files (this may take some time).."
copy_filesystem

echo "Success. Your encrypted disk image is at $DST_IMAGE"
2 changes: 1 addition & 1 deletion guest-vm/setup_verity.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ echo "Mounting images.."
sudo mount $SRC_ROOT_FS_DEVICE $SRC_FOLDER
sudo mount $DST_DEVICE $DST_FOLDER

echo "Copying files.."
echo "Copying files (this may take some time).."
copy_filesystem

echo "Preparing output filesystem for dm-verity.."
Expand Down
77 changes: 41 additions & 36 deletions tools/attestation_server/examples/vm-config.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
#Name of the CPU generation running the VM. Relevant for selecting the correct
#certificate chain when veryfing the attestation report
# Name of the CPU generation running the VM. Relevant for selecting the correct
# certificate chain when veryfing the attestation report
host_cpu_family = "Milan"
#Number of virtual CPUs used by the VM. As each VCPU has its own VMSA, this influences the launch digest in the attestation report

# Number of virtual CPUs used by the VM. As each VCPU has its own VMSA
# this influences the launch digest in the attestation report
vcpu_count = 1
#Path to the OVMF binary that should be used to boot the VM. Influences the launch digest in the attestation report
ovmf_file = "path to OVMF.fd file used by QEMU"

# Path to the OVMF binary that should be used to boot the VM
# Influences the launch digest in the attestation report
ovmf_file = "<path to OVMF file used by QEMU>"

# Guest-controlled SEV feature selection as defined in the SEV_FEATURES section
# of the VMSA (Table B-4 in [1] )
# Since these are part of the VMSA, they influence the launch digest in the attestation report
# of the VMSA (Table B-4 in [1]). Since these are part of the VMSA,
# they influence the launch digest in the attestation report
# For now, there does not seem to be an easy way to configure these from userspace
# All SEV-SNP VMs have bit 0 set, other bits are unset by default
guest_features = 0x1
#Path to the kernel that should get booted. Influences the lauch digest in the attestation report
kernel_file = "path to kernel file that gets passed to QMEU"
#Path to the initramdisk file that should be used for booting. Influences the launch digest in the attestation report
initrd_file = "path to initramdisk file that gets passed to QEMU"
#Kernel commandline parameters. Influences the launch digest in the attestation support
# For debugging, you might want to use "console=ttyS0" to have a shell. Note however, that all information shown in this shell is copied to unecrytped video buffer memory

# Path to the kernel that should get booted.
# Influences the lauch digest in the attestation report
kernel_file = "<path to kernel file that is passed to QEMU>"

# Path to the initrd file that should be used for booting.
# Influences the launch digest in the attestation report
initrd_file = "<path to initrd file that is passed to QEMU>"

# Kernel command-line parameters
# Influences the launch digest in the attestation support
kernel_cmdline = ""

# Information about security relevant configuration option that affect the
# whole host system, e.g. if SMT or RAPL are enabled.
# Values are defined in Table 23 in [2]
# whole host system, e.g. if SMT or RAPL are enabled
# Attested by the the attestation report
platform_info = 1
# Values are defined in Table 23 in [2]. Below the meaning of currently used bits:
# Bit 0 set: SMT (Simultaneous MultiThreading) is enabled
# Bit 1 set: TSME (Transparent Secure Memory Encryption) is enabled
# Bit 2 set: ECC (Error Correcting Code) is enabled
# Bit 3 set: RAPL (Running Average Power Limit) is _disabled_
# Bit 4 set: Ciperthext Hiding is enabled
platform_info = 0x1

# Guest-controlled config that can request the enablement of certain security
# reveleant configuration on the host and also controls if the VM is debuggable
Expand All @@ -32,44 +47,35 @@ platform_info = 1
guest_policy = 0x30000


# OPTIONAL: Only used if id block and auth block are used see [3] for more information
# OPTIONAL: Only used if id block and auth block are used (see [3] for more info)
# Arbitrary used defined data to describe the VM. Defined in Table 74 in [2]
# Interpreted as hex. Must be exactly 16 bytes long
# Attested by the attestation report
family_id = "00000000000000000000000000000000"

# OPTIONAL: Only used if id block and auth block are used see [3] for more information
# OPTIONAL: Only used if id block and auth block are used (see [3] for more info)
# Arbitrary used defined data to describe the VM. Defined in Tablej 74 in [2]
# Interpreted as hex. Must be exactly 16 bytes long
# Attested by the attestation report
image_id = "00000000000000000000000000000000"


#Request the minium version number that the host can use
#for certain security relevant software components
#Use the "sev-feature-info" tool on the host to discover the
# Request the minimum version number that the host can use
# for certain security relevant software components
# Use the "sev-feature-info" tool on the host to discover the
# currently used values
# The attestation report contains 3 different variants for the
# TCB: committed, launch and current
# We check against the committed version as this ensures that the HV
# We check against the committed version as this ensures that the hypervisor
# cannot use a version older than this. However, the commmited version
# might be lower than the version reported by the tool.
# Currently I don't now an easy way to find the commited version
# If you boot without any firmware files in /lib/firmware/amd/
# the reported version should match the committed version
# might be lower than the version reported by the tool.
[min_commited_tcb]
bootloader = 3
tee = 0
#do not change this
_reserved = [
0,
0,
0,
0,
]
snp = 20
microcode = 209

# reserved fields (do not change)
_reserved = [0, 0, 0, 0]


# References
Expand All @@ -83,5 +89,4 @@ microcode = 209
# to populate the "ID_KEY_DIGEST" and "AUTHOR_KEY_DIGEST" fields of
# the attestation report with the hash of two VM owner controlled public
# keys
# You can use the "idblock-generator" tool to create
#
# You can use the "idblock-generator" tool to create an ID block.

0 comments on commit 7c046b1

Please sign in to comment.