From e776d063ac6838665e6169978ecc1922f6c31ca6 Mon Sep 17 00:00:00 2001 From: Avi Deitcher Date: Sun, 23 Jul 2017 18:44:37 +0300 Subject: [PATCH 1/2] add tss image Signed-off-by: Avi Deitcher --- docs/trusted-computing.md | 59 +++++++++++++++++++++++++ examples/tpm.yml | 30 +++++++++++++ pkg/tss/Dockerfile | 64 ++++++++++++++++++++++++++++ pkg/tss/Makefile | 6 +++ pkg/tss/README.md | 35 +++++++++++++++ pkg/tss/etc/group | 6 +++ pkg/tss/etc/passwd | 5 +++ pkg/tss/etc/shadow | 5 +++ pkg/tss/src/glibc_stubs/Makefile | 18 ++++++++ pkg/tss/src/glibc_stubs/getpwent_r.c | 38 +++++++++++++++++ pkg/tss/src/savedeps/savedeps.sh | 33 ++++++++++++++ 11 files changed, 299 insertions(+) create mode 100644 docs/trusted-computing.md create mode 100644 examples/tpm.yml create mode 100644 pkg/tss/Dockerfile create mode 100644 pkg/tss/Makefile create mode 100644 pkg/tss/README.md create mode 100644 pkg/tss/etc/group create mode 100644 pkg/tss/etc/passwd create mode 100644 pkg/tss/etc/shadow create mode 100644 pkg/tss/src/glibc_stubs/Makefile create mode 100644 pkg/tss/src/glibc_stubs/getpwent_r.c create mode 100755 pkg/tss/src/savedeps/savedeps.sh diff --git a/docs/trusted-computing.md b/docs/trusted-computing.md new file mode 100644 index 000000000..88019e11e --- /dev/null +++ b/docs/trusted-computing.md @@ -0,0 +1,59 @@ +# Trusted Computing + +LinuxKit has support for using [Trusted Computing](http://trustedcomputinggroup.org) Platform Modules (tpm) chips. + +Supporting tpm requires support at three levels: + +* Hardware +* Kernel +* Software - The Trusted Computing Software Stack (TSS) + +## Hardware +You need to have a tpm chip installed in your computer to use tpm. Alternatively, you can use one of the virtual tpms implemented in software, provided that either: + +* your kernel supports it +* your hardware virtualization platform supports it + +## Kernel +As of [PR 2234](https://github.com/linuxkit/linuxkit/pull/2234), the in-tree linux kernel modules that support tpm are shipped with LinuxKit by default. + +The shipped modules support both tpm chip versions 1.2 and tpm 2.0. + +## Software +The software stack (TSS) functions differently between tpm versions 1.2 and 2.0. + +### tss 1.2 +In tss 1.2, the character device `/dev/tpm0` is meant to be addresses only by a single process. All other clients are expected to communicate with this single client that handles multiplexing of requests and various other low-level functionality. + +The single client normally used is [TrouSerS](https://sourceforge.net/p/trousers/trousers/). It creates a daemon, `tcsd`, that communicates with the character device (and via the character device and the kernel module to the actual tpm). + +`tcsd` in turn listens on `localhost:30003` for tpm commands. All other clients are expected to communicate via tcp to `tcsd`. + +LinuxKit provides the `linuxkit/tss` image which includes: + +* `tcsd` +* the various `tpm_*` tools + +To make a `tcsd` available to your LinuxKit image, just include it: + +```yml +services: + - name: tss + image: linuxkit/tss: +``` + +For a full example, see [tpm.yml](../examples/tpm.yml) + +### tss 2.0 +In tss 2.0, the character device `/dev/tpmrm0` can be addressed by as many processes, in parallel, as desired. All of the multiplexing and low-level services are built into the kernel module. + +To use a tpm 2.0 device, you do **not** need any special tss container. You just need an container that: + +1. Bind-mounts `/dev` in +2. Has your tools or libraries installed +3. Talks directly to `/dev/tpmrm0` + + +The image `linuxkit/tss` ships with the version 1.2 `tcsd` and the `tpm_*` tools for tpm version 1.2. The tools for tpm version 2.0 `tpm2_*` and its attendant libs are _not_ included in the image. + +We intend to release a tss 2.0 compatible image in the near future. In the meantime, nothing prevents you from using and compiling your own tss and including it in a LinuxKit image. diff --git a/examples/tpm.yml b/examples/tpm.yml new file mode 100644 index 000000000..91e9a814f --- /dev/null +++ b/examples/tpm.yml @@ -0,0 +1,30 @@ +kernel: + image: linuxkit/kernel:4.9.38 + cmdline: "console=tty0 console=ttyS0" +init: + - linuxkit/init:d049e7b2074da5cd699a27defb47eb101142455d + - linuxkit/runc:d5cbeb95bdafedb82ad2cf11cff1a5da7fcae630 + - linuxkit/containerd:e33e0534d6fca88e1eb86897a1ea410b4a5d722e + - linuxkit/ca-certificates:67acf038c44bb191ebb704ec7bb39a1524052cdf +onboot: + - name: sysctl + image: linuxkit/sysctl:d1a43c7c91e92374766f962dc8534cf9508756b0 + - name: dhcpcd + image: linuxkit/dhcpcd:4b7b8bb024cebb1bbb9c8026d44d7cbc8e202c41 + command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"] +services: + - name: getty + image: linuxkit/getty:1b651a91f1c17f50357be9873b580ccf81668630 + env: + - INSECURE=true + - name: tss + image: linuxkit/tss:e51164ceaa2bd6db7d68e74d071929f5cb1c6c2e + - name: rngd + image: linuxkit/rngd:1516d5d70683a5d925fe475eb1b6164a2f67ac3b +files: + - path: etc/getty.shadow + # sample sets password for root to "abcdefgh" (without quotes) + contents: 'root:$6$6tPd2uhHrecCEKug$8mKfcgfwguP7f.BLdZsT1Wz7WIIJOBY1oUFHzIv9/O71M2J0EPdtFqFGTxB1UK5ejqQxRFQ.ZSG9YXR0SNsc11:17322:0:::::' +trust: + org: + - linuxkit diff --git a/pkg/tss/Dockerfile b/pkg/tss/Dockerfile new file mode 100644 index 000000000..88b904d17 --- /dev/null +++ b/pkg/tss/Dockerfile @@ -0,0 +1,64 @@ +FROM linuxkit/alpine:43c139f87122e94af5fac9a9d1d96f0292ca1c0b AS build + +ENV TROUSERS_COMMIT de57f069ef2297d6a6b3a0353e217a5a2f66e444 +ENV TPM_TOOLS_COMMIT bdf9f1bc8f63cd6fc370c2deb58d03ac55079e84 + +RUN apk add --no-cache --initdb \ + automake \ + autoconf \ + gettext \ + gettext-dev \ + git \ + pkgconfig \ + libtool \ + libc-dev \ + linux-headers \ + gcc \ + make \ + openssl-dev \ + util-linux \ + && true + +RUN mkdir -p /usr/src +COPY src/glibc_stubs/ /usr/src/glibc_stubs +WORKDIR /usr/src/glibc_stubs +RUN make && make install + +RUN git clone https://git.code.sf.net/p/trousers/trousers /usr/src/trousers-trousers && cd /usr/src/trousers-trousers && git checkout $TROUSERS_COMMIT +RUN git clone https://git.code.sf.net/p/trousers/tpm-tools /usr/src/trousers-tpm-tools && cd /usr/src/trousers-tpm-tools && git checkout $TPM_TOOLS_COMMIT +WORKDIR /usr/src/trousers-trousers +RUN sh bootstrap.sh && \ + ./configure --prefix=/ --sysconfdir=/etc LDFLAGS="-L/out/lib/ -lgetpwent_r" && \ + make && \ + make install prefix=/out +WORKDIR /usr/src/trousers-tpm-tools + +RUN sh bootstrap.sh && \ + ./configure --prefix=/out CFLAGS="-I/out/include" LDFLAGS="-L/out/lib/ -lgetpwent_r" && \ + make && \ + make install + +COPY src/savedeps/ /usr/src/savedeps +RUN /usr/src/savedeps/savedeps.sh /out /out + +RUN mkdir -p /out/var/lib/tpm + +# we need busybox to run chmod, chown, touch, etc. +RUN mkdir -p /out/bin && cp /bin/busybox /out/bin/busybox && ln -s /bin/busybox /out/bin/sh + + + +FROM scratch +WORKDIR / +COPY --from=build /out / +COPY etc/ /etc +# set up the appropriate groups and perms +RUN busybox chmod 0644 /etc/passwd /etc/group && \ + busybox chmod 0640 /etc/shadow && \ + busybox touch /etc/tcsd.conf && \ + busybox chmod 0600 /etc/tcsd.conf && \ + busybox chown -R tss.tss /var/lib/tpm/ /etc/tcsd.conf && \ + busybox rm /bin/busybox /bin/sh + +CMD ["/sbin/tcsd","-f"] +LABEL org.mobyproject.config='{"pid": "host", "net":"host", "binds": ["/dev:/dev"], "capabilities": ["all"]}' diff --git a/pkg/tss/Makefile b/pkg/tss/Makefile new file mode 100644 index 000000000..c8278d22c --- /dev/null +++ b/pkg/tss/Makefile @@ -0,0 +1,6 @@ +IMAGE=tss +NETWORK=1 +DEPS=$(wildcard upload/out/*) $(wildcard upload/out/etc/*) $(wildacrd upload/src/savedeps/*) $(wildcard upload/src/glibc_stubs/*) + +include ../package.mk + diff --git a/pkg/tss/README.md b/pkg/tss/README.md new file mode 100644 index 000000000..4f002ebc3 --- /dev/null +++ b/pkg/tss/README.md @@ -0,0 +1,35 @@ +# LinuxKit tpm +Image to provide a tcsd daemon and tpm tools to support tpm, based on [trousers and tpm-tools](https://sourceforge.net/projects/trousers/) . + + +## Usage +If you want to interact with a tpm chip, you need a `tcsd` daemon running to control it and provide a communication endpoint for all of your tpm commands. + +This image provides both a `tcsd` daemon to run in a container, and the command line `tpm-tools`. + +### Daemon +To run a `tcsd` daemon - you **must** run exactly one on a tpm-enabled host to interact with the tpm - just start the container. + +#### LinuxKit +In LinuxKit, add the following to your moby `.yml`: + +``` +services: + - name: tcsd + image: "secureapp/tss:" +``` + +The above will launch `tcsd` listening on localhost only. + +#### Docker +In regular docker or other container environment, start the container in the background. Be sure to map `/dev:/dev` and expose port `30003`. + +``` +docker run -d -v /dev:/dev -p 30003:30003 secureapp/tcsd +``` +### CLI Tools +To run the CLI tools, just run them: + +``` +docker run -it --rm secureapp/tcsd tpm_nvread +``` diff --git a/pkg/tss/etc/group b/pkg/tss/etc/group new file mode 100644 index 000000000..1aa4f5ecb --- /dev/null +++ b/pkg/tss/etc/group @@ -0,0 +1,6 @@ +root:x:0:root +bin:x:1:root,bin,daemon +daemon:x:2:root,bin,daemon +sys:x:3:root,bin,adm +adm:x:4:root,adm,daemon +tss:x:116: diff --git a/pkg/tss/etc/passwd b/pkg/tss/etc/passwd new file mode 100644 index 000000000..e83039b41 --- /dev/null +++ b/pkg/tss/etc/passwd @@ -0,0 +1,5 @@ +root:x:0:0:root:/root:/bin/false +bin:x:1:1:bin:/bin:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +adm:x:3:4:adm:/var/adm:/sbin/nologin +tss:x:107:116::/var/lib/tpm:/bin/false diff --git a/pkg/tss/etc/shadow b/pkg/tss/etc/shadow new file mode 100644 index 000000000..cd82bf03c --- /dev/null +++ b/pkg/tss/etc/shadow @@ -0,0 +1,5 @@ +root:!::0::::: +bin:!::0::::: +daemon:!::0::::: +adm:!::0::::: +tss:*:16901:0:99999:7::: diff --git a/pkg/tss/src/glibc_stubs/Makefile b/pkg/tss/src/glibc_stubs/Makefile new file mode 100644 index 000000000..5364edd6a --- /dev/null +++ b/pkg/tss/src/glibc_stubs/Makefile @@ -0,0 +1,18 @@ + +.PHONY: all clean install + +SOLIB = libgetpwent_r.so + +DEPS = getpwent_r.o + +all: $(SOLIB) + +%.o: %.c + gcc -c -Wall -Werror -fpic ${CFLAGS} $< + +$(SOLIB): $(DEPS) + gcc -shared -o $(SOLIB) $^ + +install: + mkdir -p /out/lib + cp $(SOLIB) /out/lib diff --git a/pkg/tss/src/glibc_stubs/getpwent_r.c b/pkg/tss/src/glibc_stubs/getpwent_r.c new file mode 100644 index 000000000..f4edcc904 --- /dev/null +++ b/pkg/tss/src/glibc_stubs/getpwent_r.c @@ -0,0 +1,38 @@ +/* + * getpwent_r stub + * + * This is not really reentrant... but then again, neither is getpwent_r + * because getpwent_r is a GNU extension, and not posix compliant, + * a program using getpwent_r() will fail on a system with POSIX-compliant libc, + * e.g. musl libc on Alpine + * + * This library simply stubs it through + * It does nothing but: + * 1. populate the pwbuf with the data + * 2. populate pwbufp with the pointer to *pwbuf + * 3. return correct error codes + * + * It was created to get trousers libtspi to work with POSIX-compliant musl libc + * when that is fixed - https://sourceforge.net/p/trousers/bugs/211/ - this will + * be unnecessary + */ + +#include +#include +#include +#include + +struct passwd *pwp; +int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) +{ + struct passwd *pw; + // if NULL, we had an error, return the appropriate error code + if ((pw = getpwent()) == NULL) { + return ERANGE; + } + // so really we should memcpy mot just the (struct passwd), but everything it points to as well + // in practice, we just copy the (struct passwd) because this isn't really thread-safe anyways + memcpy(pwbuf, pw, sizeof(*pw)); + *pwbufp = pwbuf; + return 0; +} diff --git a/pkg/tss/src/savedeps/savedeps.sh b/pkg/tss/src/savedeps/savedeps.sh new file mode 100755 index 000000000..a9ec9d944 --- /dev/null +++ b/pkg/tss/src/savedeps/savedeps.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# find all of my dependencies under $1 and save them to $2 +OUTDIR=$1 + +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$OUTDIR/lib:$OUTDIR/usr/lib +# find the direct dependencies +DIRECTDEPS=$(for i in $(find $OUTDIR/*bin $OUTDIR/*lib -type f); do ldd $i 2>/dev/null; done | awk '{print $3}' | grep -v '^ldd$' | sort | uniq) +# find the secondary dependencies +SECONDDEPS=$(for i in $DIRECTDEPS; do ldd $i 2>/dev/null; done | awk '{print $3}' | grep -v '^ldd$' | sort | uniq) +# merge together into single unique list, excluding any already in OUTDIR +ALLDEPS=$(echo "$DIRECTDEPS $SECONDDEPS" | sort | uniq | grep -v "^$OUTDIR") + + +# recursively follows links +copyfile() { + local infile=${1#/} + tar cvf - $infile | (cd $OUTDIR ; tar xvf - ) + # if it was a symlink, dereference and copy that + if [ -L $infile ]; then + copyfile $(readlink -f $infile) + fi +} + +# we remove the leadink / and then do everything from / +cd / +# save to OUTDIR +mkdir -p $OUTDIR +for infile in $ALLDEPS; do + if [ ! -e $OUTDIR/$infile ]; then + # symlinks should be copied but also followed + copyfile $infile + fi +done From ffb33e9d6430a868369ddf7e71d2cc25216a480d Mon Sep 17 00:00:00 2001 From: Avi Deitcher Date: Wed, 26 Jul 2017 13:52:50 +0300 Subject: [PATCH 2/2] tpm.yml example update hash and add example test case Signed-off-by: Avi Deitcher --- examples/tpm.yml | 2 +- .../000_build/100_examples/060_tpm/test.sh | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/cases/000_build/100_examples/060_tpm/test.sh diff --git a/examples/tpm.yml b/examples/tpm.yml index 91e9a814f..fd381a650 100644 --- a/examples/tpm.yml +++ b/examples/tpm.yml @@ -18,7 +18,7 @@ services: env: - INSECURE=true - name: tss - image: linuxkit/tss:e51164ceaa2bd6db7d68e74d071929f5cb1c6c2e + image: linuxkit/tss:51d73be868e12af76965f5682ed59309c19972b6 - name: rngd image: linuxkit/rngd:1516d5d70683a5d925fe475eb1b6164a2f67ac3b files: diff --git a/test/cases/000_build/100_examples/060_tpm/test.sh b/test/cases/000_build/100_examples/060_tpm/test.sh new file mode 100644 index 000000000..dbfa40ab5 --- /dev/null +++ b/test/cases/000_build/100_examples/060_tpm/test.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# SUMMARY: Test the tpm example +# LABELS: + +set -e + +# Source libraries. Uncomment if needed/defined +#. "${RT_LIB}" +. "${RT_PROJECT_ROOT}/_lib/lib.sh" + +IMAGE_NAME=tpm + +clean_up() { + # remove any files, containers, images etc + rm -rf ${IMAGE_NAME}* +} + +trap clean_up EXIT + +# Test code goes here +moby build "${LINUXKIT_EXAMPLES_DIR}/${IMAGE_NAME}.yml" + +exit 0