-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for vTPM and its runtime protocol #135
Conversation
Sorry for the branch conflict. I will fix it as soon as I find a new way to get the slab item size in the function |
Feel free to revert that commit by including the slab size instead of the pointer. |
A hint for building on Fedora: make sure to install these dependencies:
|
407b60f
to
d3fb0bb
Compare
|
adae550
to
6b2be53
Compare
This PR version works with the upstream Microsoft TPM and OpenSSL. So, for testing, you only need to the OVMF and guest kernel mentioned in the PR description. |
@cclaudio thanks for this great work! I'll review in the next days, in the meantime I report some building issues I'm having.
I can't see these changes (e.g. git submodule initialization), maybe we forgot them during rebase. I think we should also update our container image with something like this: diff --git a/scripts/container/opensuse-rust.docker b/scripts/container/opensuse-rust.docker
index bf8a109..ad276d6 100644
--- a/scripts/container/opensuse-rust.docker
+++ b/scripts/container/opensuse-rust.docker
@@ -19,7 +19,9 @@ ARG USER_NAME user
SHELL ["/bin/bash", "-c"]
RUN zypper ref && \
- zypper install -y system-user-mail make gcc curl && \
+ zypper install -y system-user-mail make gcc curl \
+ patterns-devel-base-devel_basis \
+ autoconf autoconf-archive pkg-config automake libopenssl-devel && \
useradd -u $USER_ID -m $USER_NAME
USER $USER_NAME This doesn't work for me, though, because I keep seeing:
I think I need some help from OpenSUSE users :-) |
I also saw build errors on my dev system (not in a container). I think the error @stefano-garzarella is seeing is because the glibc static libraries are missing in the container. In order to get the build to work, I had to install the static library plus a couple of other missing dependencies:
|
@roy-hopkins yeah thanks! diff --git a/scripts/container/opensuse-rust.docker b/scripts/container/opensuse-rust.docker
index bf8a109..621d107 100644
--- a/scripts/container/opensuse-rust.docker
+++ b/scripts/container/opensuse-rust.docker
@@ -19,7 +19,9 @@ ARG USER_NAME user
SHELL ["/bin/bash", "-c"]
RUN zypper ref && \
- zypper install -y system-user-mail make gcc curl && \
+ zypper install -y system-user-mail make gcc curl \
+ patterns-devel-base-devel_basis glibc-devel-static git libclang13 \
+ autoconf autoconf-archive pkg-config automake libopenssl-devel && \
useradd -u $USER_ID -m $USER_NAME
USER $USER_NAME Edit: we also need |
Thanks @stefano-garzarella @roy-hopkins. diff --git a/Documentation/INSTALL.md b/Documentation/INSTALL.md
index 477b4d1c93b1..487e99e16719 100644
--- a/Documentation/INSTALL.md
+++ b/Documentation/INSTALL.md
@@ -176,6 +176,14 @@ Building the SVSM itself requires:
- `x86_64-unknown-none` target toolchain installed (`rustup target add x86_64-unknown-none`)
- `binutils` >= 2.39
+Also make sure you have the Microsoft TPM build dependencies installed. On OpenSUSE
+you can do this by:
+```
+$ sudo zypper in system-user-mail make gcc curl patterns-devel-base-devel_basis \
+ glibc-devel-static git libclang13 autoconf autoconf-archive pkg-config \
+ automake libopenssl-devel
+```
+
Then checkout the SVSM repository and build the SVSM binary:
|
6b2be53
to
c6caab2
Compare
Feedback applied |
/cc @zvonkok |
Ensure the Microsoft TPM build dependencies are installed when building the SVSM for the github CI and using the container build script. The INSTALL.md will be updated with the same steps in a separate patch. Signed-off-by: Claudio Carvalho <[email protected]>
This reverts commit 8fd4c80. With that the slab is again encoded in the SlabPageInfo and we can use it to determine the size of an allocated memory pointer. That is required to implement realloc() and free() wrappers for the libcrt. Signed-off-by: Claudio Carvalho <[email protected]>
The signature of the allocate_slab_page function has been updated, now it requires Option<VirtAddr>. fn allocate_slab_page(&mut self, slab: Option<VirtAddr>) -> Result<VirtAddr, AllocError> Signed-off-by: Claudio Carvalho <[email protected]>
The functions malloc(), realloc(), calloc(), free(), abort() and serial_out() are required to build OpenSSL and the Microsoft TPM 2.0, but they cannot be implemented in the libcrt because memory and standard I/O codes are owned by the SVSM rust code. Signed-off-by: Claudio Carvalho <[email protected]>
Add the libmstpm workspace member to own the C libraries that the Microsoft TPM depends on: - libcrt: the libcrt.a - OpenSSL: the libcrypto.a - Microsoft TPM: the libplatform.a and libtpm.a This workspace member will be used to keep self-contained all the complexity to build the C libraries as well as generation of FFI bindings using bindgen. Signed-off-by: Claudio Carvalho <[email protected]>
The libcrt is a subset of the musl libc that provides only the symbols required to build the Microsoft TPM 2.0 and the OpenSSL for the SVSM. In general, the libcrt header files are just a proxy for the libcrt.h, which centralizes all the definitions. That's similar to what OVMF does to build OpenSSL without having to patch missing headers. Some libcrt functions are required at build time, but they are not called at runtime. These functions are stubbed out in stub.c, a WARNING message is printed if the stub is executed. The required malloc(), realloc(), calloc(), free(), abort() and serial_out() will be implemented in Rust. The required rand() function uses the RDRAND instruction to get random bytes. The time() function uses the RDTSC instruction to get the current time. The libmstpm is compiled in quiet mode by default, but "make V=2" can be used to show all its compilation messages. Co-developed-by: Vikram Narayanan <[email protected]> Signed-off-by: Vikram Narayanan <[email protected]> Signed-off-by: Claudio Carvalho <[email protected]>
Add OpenSSL as a git submodule and build it. As of now, the upstream Microsoft TPM 2.0 requires OpenSSL 1.1.1d or higher. OpenSSL 3.x support is still under review upstream in a pull request. Similar to OVMF, we also build OpenSSL 1.1.1q by providing an OpenSSL config and disabling crypto modules that are not needed. Later we can move to OpenSSL 3.x. Signed-off-by: Claudio Carvalho <[email protected]>
Add the Microsoft TPM as a git submodule and build it. The SVSM does not need the Microsoft TPM simulator, so we build only the libplatform.a and libtpm.a. For now we are disabling the TPM Self Test command (-DSELF_TEST=NO) as it is failing. This issue is explained and fixed in a separate patch. Signed-off-by: Claudio Carvalho <[email protected]>
TPM commands such as SelfTests and CreatePrimary end up calling into the OpenSSL Elliptic Curve subsystem, but they will fail if the OpenSSL entropy pool is empty. There are multiple ways to confirm that, for instance: (1) when OVMF tries to run the SelfTests during boot: TPM2Startup: TPM_RC_SUCCESS [..] ReadPcr: Unable to read TPM capabilities [..] Tpm2PcrExtend: Response Code error! 0x00000143 HashLogExtendEvent - Device Error. Disable TPM. (2) when we try to create an ECC primary key from guest userspace: $ tpm2_createek -c 0x81000000 -G ecc -u key.tss [SVSM] WARN: VMPCK0 disabled! [SVSM] ERROR: Panic: CPU[0] panicked at src/vtpm/ek.rs:78:23: Failed to create the TPM Endorsment Key Rc( 0x154, ) [SVSM] ---BACKTRACE---: [SVSM] ---END--- This patch fix that by building OpenSSL with --with-rand-seed=getrandom and also implementing getentropy() to return entropy obtained through RDRAND. Co-developed-by: Claudio Carvalho <[email protected]> Signed-off-by: Claudio Carvalho <[email protected]> Signed-off-by: Mike Rapoport <[email protected]>
Generate FFI (Foreign Functions Interface) bindings for the libmstpm symbols we call in Rust. To avoid adding bindgen dependencies to Cargo.toml we use the bindgen command line. The libmstpm.h has a complete list of the C symbols we need. Signed-off-by: Claudio Carvalho <[email protected]>
The libmstpm.a is linked against the kernel only when the mstpm cargo feature is enabled; currently it is enabled by default. Tracking cargo features in the Makefile doesn't seem an easy/simple task, maybe that's why we are not doing that (Issue coconut-svsm#65). So, for now the libmstpm is always built. "make distclean" can be used to clean the libmstpm. Later that could be improved by forcing the libmstpm to be built in the $OUT_DIR directory (place in the target directory that cargo uses to build packages). With that the libmstpm would also be cleaned when "make clean" is issued to delete the target directory. Signed-off-by: Claudio Carvalho <[email protected]>
Add the interfaces that a tpm backend needs to implement in order to be supported in the SVSM: - VtpmProtocolInterface: basic services required to perform the runtime vTPM protocol (added in a separate patch). - MsTpmSimulatorInterface: define one handler for each TPM Platform Command supported in the vTPM protocol. It extends the VtpmProtocolInterface. - VtpmInterface: basic TPM driver services. It extends the MsTpmSimulatorInterface. Signed-off-by: Claudio Carvalho <[email protected]>
Implement the vtpm interfaces for the Microsoft TPM, they all call into the libmstpm. This also defines the MsTpm structure that later can be used to instatiate the Microsoft TPM backend. Signed-off-by: Claudio Carvalho <[email protected]>
Initialize the virtual TPM by calling the init() function of the TPM backend. Signed-off-by: Claudio Carvalho <[email protected]>
Add a constant for the SVSM core protocol ID to improve code readability. Signed-off-by: Claudio Carvalho <[email protected]>
The vTPM protocol is introduced in the SVSM specification v1.0 to allow other software components (e.g. OVMF and guest kernel) to communicate with the SVSM vTPM at runtime. It follows the Microsoft TPM 2.0 Simulator protocol. The specification enumerates two call IDs supportted by the vTPM protocol: 1. SVSM_VTPM_QUERY: query vTPM command and features support. 2. SVSM_VTPM_CMD: Execute a TPM platform command. As for the SVSM_VTPM_CMD, the TPM platform commands are described in libvtpm/ms-tpm-20-ref/TPMCmd/Simulator/include/prototypes/Simulator_fp.h e.g.: - TPM_SIGNAL_HASH_DATA - TPM_SEND_COMMAND - TPM_REMOTE_HANDSHAKE - TPM_SET_ALTERNATIVE_RESULT This patch implements both the SVSM_VTPM_QUERY and the SVSM_VTPM_CMD call IDs. For the SVSM_VTPM_CMD, only the TPM_SEND_COMMAND platform command is implemented. Signed-off-by: Claudio Carvalho <[email protected]>
Document the Microsoft TPM build requirements. Signed-off-by: Claudio Carvalho <[email protected]>
Add the default-test cargo feature to control what features we want to enable in the tests. The vtpm/mstpm/wrappers.rs, for example, can't run in the test environment because its malloc() etc functions conflict with the libc standard libraries. Signed-off-by: Claudio Carvalho <[email protected]>
Set CARGO_HOME and add it to PATH in the Dockerfile. This way we don't have to source the setup script every time. Signed-off-by: Oliver Steffen <[email protected]>
Install bindgen-cli in container image. Signed-off-by: Oliver Steffen <[email protected]>
Mention submodule initialization in the comment exlaining how to use the container build scripts. Signed-off-by: Oliver Steffen <[email protected]>
The file libmstpm/src/bindings.rs is auto-generated during make, however the github CI is not building the code for the nightly tests. This patch initializes the bindings.rs before the cargo-fmt workflow so that it does not complain that bindings.rs does not exist. Signed-off-by: Claudio Carvalho <[email protected]>
a78d4f3
to
9ba6a6d
Compare
rebased and fixed conflict with Makefile |
This is merged now. Thanks @cclaudio and all the reviewers! |
This is a sketch of how the vTPM and the vTPM protocol would work in the SVSM, for now running in CPL0.
The vTPM is initialized (manufactured) on every boot. If OVMF and the Linux guest kernel have proper tpm drivers, they should be able to communicate with the SVSM vTPM. See the section Dependencies below.
Once this is merged I can post a PR for the attestation protocol.
Dependencies
OVMF
Guest kernel:
The linux branch below is based on the PR#2 posted against the coconut-svsm/linux repository with additional two patches for the TPM platform driver.
CONFIG_TCG_PLATFORM
should be enabled in the guest. The same kernel also needs to be installed on the host.QEMU:
Follow the instructions described in INSTALL.md to build the QEMU branch below.
How to test it
Follow the INSTALL.md to build this PR and run a QEMU guest.
During the boot you should be able to see messages from OVMF and the linux kernel like these:
From guest userspace you can also install the
tpm2-tools
package and use it to communicate with the SVSM-vTPM (e.g.tpm2_pcrread
without arguments)