-
Notifications
You must be signed in to change notification settings - Fork 22
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 swtpm example #57
Open
dimakuv
wants to merge
2
commits into
master
Choose a base branch
from
dimakuv/add-swtpm
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next
Next commit
Add swtpm example
Signed-off-by: Dmitrii Kuvaiskii <[email protected]>
- Loading branch information
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
ARCH_LIBDIR ?= /lib/$(shell $(CC) -dumpmachine) | ||
|
||
ifeq ($(DEBUG),1) | ||
GRAMINE_LOG_LEVEL = all | ||
else | ||
GRAMINE_LOG_LEVEL = error | ||
endif | ||
|
||
ifeq ($(SGX),1) | ||
GRAMINE_ENCRYPTION_KEY = "_sgx_mrenclave" | ||
else | ||
GRAMINE_ENCRYPTION_KEY = "direct" | ||
endif | ||
|
||
.PHONY: all | ||
all: swtpm.manifest | ||
ifeq ($(SGX),1) | ||
all: swtpm.manifest.sgx swtpm.sig | ||
endif | ||
|
||
swtpm.manifest: swtpm.manifest.template | ||
gramine-manifest \ | ||
-Dlog_level=$(GRAMINE_LOG_LEVEL) \ | ||
-Dencryption_key=$(GRAMINE_ENCRYPTION_KEY) \ | ||
-Darch_libdir=$(ARCH_LIBDIR) \ | ||
-Dentrypoint=$(realpath $(shell sh -c "command -v swtpm")) \ | ||
$< $@ | ||
|
||
# gramine-sgx-sign generates both a .sig file and a .manifest.sgx file. This is somewhat | ||
# hard to express properly in Make. The simple solution would be to use | ||
# "Rules with Grouped Targets" (`&:`), however make on Ubuntu <= 20.04 doesn't support it. | ||
# | ||
# Simply using a normal rule with "two targets" is equivalent to creating separate rules | ||
# for each of the targets, and when using `make -j`, this might cause two instances | ||
# of gramine-sgx-sign to get launched simultaneously, potentially breaking the build. | ||
# | ||
# As a workaround, we use a dummy intermediate target, and mark both files as depending on it, to | ||
# get the dependency graph we want. We mark this dummy target as .INTERMEDIATE, which means | ||
# that make will consider the source tree up-to-date even if the sgx_sign file doesn't exist, | ||
# as long as the other dependencies check out. This is in contrast to .PHONY, which would | ||
# be rebuilt on every invocation of make. | ||
swtpm.sig swtpm.manifest.sgx: sgx_sign | ||
@: | ||
|
||
.INTERMEDIATE: sgx_sign | ||
sgx_sign: swtpm.manifest | ||
gramine-sgx-sign \ | ||
--manifest $< \ | ||
--output $<.sgx | ||
|
||
ifeq ($(SGX),) | ||
GRAMINE = gramine-direct | ||
else | ||
GRAMINE = gramine-sgx | ||
endif | ||
|
||
.PHONY: clean | ||
clean: | ||
$(RM) *.token *.sig *.manifest.sgx *.manifest myvtpm2/.lock myvtpm2/*.permall | ||
|
||
.PHONY: distclean | ||
distclean: clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# swtpm | ||
|
||
This directory contains a Makefile and a manifest template for running swtpm. | ||
See https://github.com/stefanberger/swtpm/. | ||
|
||
**NOTE**: Currently works only with PR https://github.com/gramineproject/gramine/pull/1210. | ||
See also https://github.com/stefanberger/swtpm/issues/792. | ||
|
||
## Installing | ||
|
||
1. Install `libtpms` like this: | ||
https://github.com/stefanberger/libtpms/wiki#build-a-package-on-ubuntu | ||
- Version used: `git checkout v0.9.6` | ||
|
||
2. Install `swtpm` like this: https://github.com/stefanberger/swtpm/wiki#compile-on-ubuntu-2104 | ||
- Don't install `libtpms-dev` since we've done it already in step 1 | ||
- Version used: `git checkout v0.8.0` | ||
|
||
Now swtpm tools are installed. We run only `swtpm` executable with Gramine. | ||
|
||
## Configuration of `swtpm` | ||
|
||
`swtpm` executable can be run in several modes. We hard-code the following configuration | ||
(command-line options) to run with Gramine: | ||
```sh | ||
$ swtpm socket --tpm2 --tpmstate dir=/myvtpm2 --seccomp action=none \ | ||
--server type=tcp,port=2321,disconnect --ctrl type=tcp,port=2320 \ | ||
--flags not-need-init,startup-clear | ||
``` | ||
|
||
This configuration means: | ||
- run `swtpm` in TPM2 mode, | ||
- save all TPM state under `/myvtpm2/` dir (encrypted under Gramine with SGX), | ||
- don't use seccomp (Gramine doesn't support it, and it's not needed in Gramine env anyway), | ||
- listen for client connections on TCP/IP port 2321 (in contrast to CUSE or chardev), | ||
- create a control channel on TCP/IP port 2320, | ||
- additional flags for the initial state of TPM. | ||
|
||
For more information, see `man swtpm`. | ||
|
||
## Building | ||
|
||
- `make clean; make` for Gramine without SGX (`gramine-direct`). | ||
- `make clean; make SGX=1` for Gramine with SGX (`gramine-sgx`). | ||
|
||
You can add `DEBUG=1` for verbose Gramine logs. | ||
|
||
Notice that `gramine-direct` uses a dummy encryption key for TPM files, hard-coded in the manifest. | ||
Whereas `gramine-sgx` uses the MRENCLAVE-based sealing encryption key for TPM files (and is | ||
therefore secure). To make sure the correct key is used, we require a `make clean` step. For details | ||
on how the key is chosen, see Makefile and manifest template. | ||
|
||
## Quick tests of swtpm with Gramine | ||
|
||
### 1. Self-test | ||
|
||
The test idea is taken from https://github.com/stefanberger/swtpm/wiki/Useful-scripts-for-TPM, | ||
Section "Trigger a self-test on a TPM 2 listening on command port 2321 with the disconnect flag". | ||
|
||
```sh | ||
# swtpm server in one window | ||
gramine-sgx swtpm | ||
|
||
# client script in another window | ||
bash -c "exec 100<>/dev/tcp/localhost/2321; \ | ||
echo -en '\x80\x01\x00\x00\x00\x0b\x00\x00\x01\x43\x01' >&100; \ | ||
od -tx1 <&100" | ||
|
||
## output must be like this: | ||
## 0000000 80 01 00 00 00 0a 00 00 00 00 | ||
``` | ||
|
||
### 2. Hashing in PCR 17 | ||
|
||
The test idea is taken from the unit test: | ||
https://github.com/stefanberger/swtpm/blob/346b3d62/tests/_test_tpm2_hashing. | ||
|
||
```sh | ||
# swtpm server in one window | ||
gramine-sgx swtpm | ||
|
||
# client scripts in another window | ||
|
||
## 1 step: init TPM to known state | ||
swtpm_ioctl --tcp localhost:2320 -i | ||
|
||
## 2 step: startup TPM2 | ||
bash -c "exec 100<>/dev/tcp/localhost/2321; \ | ||
echo -en '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00' >&100; \ | ||
od -tx1 <&100" | ||
|
||
## output must be like this: | ||
## 0000000 80 01 00 00 00 0a 00 00 00 00 | ||
|
||
## 3 step: ask TPM to hash string "1234" in PCR 17 | ||
swtpm_ioctl --tcp localhost:2320 -h 1234 | ||
|
||
## 4 step: read PCR 17 | ||
bash -c "exec 100<>/dev/tcp/localhost/2321; \ | ||
echo -en '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02' >&100; \ | ||
od -tx1 <&100" | ||
|
||
## output must be like this: | ||
## 0000000 80 01 00 00 00 3e 00 00 00 00 00 00 00 2c 00 00 | ||
## 0000020 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 | ||
## 0000040 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af | ||
## 0000060 d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54 | ||
|
||
## 5 step: check TPM Established flag (must be 1) | ||
swtpm_ioctl --tcp localhost:2320 -e | ||
|
||
## 6 step: shutdown TPM | ||
swtpm_ioctl --tcp localhost:2320 -s | ||
``` |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# swtpm (TPM emulator) manifest file example | ||
|
||
loader.entrypoint = "file:{{ gramine.libos }}" | ||
libos.entrypoint = "{{ entrypoint }}" | ||
loader.log_level = "{{ log_level }}" | ||
|
||
loader.env.LD_LIBRARY_PATH = "/lib:{{ arch_libdir }}:/usr/{{ arch_libdir }}" | ||
|
||
loader.argv = [ | ||
"swtpm", "socket", "--tpm2", | ||
"--tpmstate", "dir=/myvtpm2", | ||
"--seccomp", "action=none", | ||
"--server", "type=tcp,port=2321,disconnect", | ||
"--ctrl", "type=tcp,port=2320", | ||
"--flags", "not-need-init,startup-clear", | ||
] | ||
|
||
sys.enable_sigterm_injection = true | ||
sys.enable_extra_runtime_domain_names_conf = true | ||
|
||
fs.mounts = [ | ||
{ path = "/lib", uri = "file:{{ gramine.runtimedir() }}" }, | ||
{ path = "{{ arch_libdir }}", uri = "file:{{ arch_libdir }}" }, | ||
{ path = "/usr/{{ arch_libdir }}", uri = "file:/usr/{{ arch_libdir }}" }, | ||
{ path = "/usr/lib/swtpm/", uri = "file:/usr/lib/swtpm/" }, | ||
|
||
{ path = "{{ entrypoint }}", uri = "file:{{ entrypoint }}" }, | ||
{ type = "encrypted", path = "/myvtpm2/", uri = "file:myvtpm2/", key_name = "{{ encryption_key }}" }, | ||
] | ||
|
||
{% if encryption_key == "direct" %} | ||
fs.insecure__keys.direct = "ffeeddccbbaa99887766554433221100" | ||
{% endif %} | ||
|
||
sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} | ||
sgx.enclave_size = "1G" | ||
|
||
sgx.trusted_files = [ | ||
"file:{{ gramine.libos }}", | ||
"file:{{ entrypoint }}", | ||
"file:{{ gramine.runtimedir() }}/", | ||
"file:{{ arch_libdir }}/", | ||
"file:/usr/{{ arch_libdir }}/", | ||
"file:/usr/lib/swtpm/", | ||
] |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does Gramine with SGX transparently encrypt file contents? If not you could pass a state encryption key here (though have to keep the encryption key then in a safe place).